XSS

ওয়েব সিকিউরিটির দুনিয়ায় Cross-Site Scripting (XSS) একটি অত্যন্ত পরিচিত এবং বিপজ্জনক ভালনারেবিলিটি (Vulnerability)। তুমি যে লেখাটি দিয়েছ, সেখানে XSS-এর মূল ধারণাগুলো চমৎকারভাবে উঠে এসেছে।

যেহেতু তুমি Python (Django/FastAPI), Java (Spring Boot) এবং Frontend (React/Next.js) নিয়ে কাজ করো, তাই তোমার টেক-স্ট্যাকের সাথে মিলিয়ে বিষয়টিকে আরও প্রফেশনালভাবে গুছিয়ে এবং কিছু গুরুত্বপূর্ণ সিকিউরিটি প্র্যাকটিস যুক্ত করে নিচে দেওয়া হলো:

Cross-Site Scripting (XSS) কী এবং কীভাবে প্রতিরোধ করবে?

Cross-Site Scripting (XSS) হলো ওয়েবসাইটের এমন একটি সিকিউরিটি ত্রুটি, যেখানে একজন অ্যাটাকার (Attacker) ওয়েবসাইটের ইনপুট ফিল্ড, ইউআরএল প্যারামিটার বা কুকিজের মাধ্যমে ক্ষতিকর জাভাস্ক্রিপ্ট (JavaScript) কোড ইনজেক্ট করে।

যখন কোনো সাধারণ ইউজার সেই আক্রান্ত পেজটি ব্রাউজ করে, তখন ওই ক্ষতিকর স্ক্রিপ্টটি তার ব্রাউজারে এক্সিকিউট হয়। এর ফলে ইউজারের সেশন কুকি (Session Cookie) চুরি, ফিশিং (Phishing), ম্যালওয়্যার ডাউনলোড বা অন্য কোনো ক্ষতিকর ওয়েবসাইটে রিডাইরেক্ট হয়ে যাওয়ার মতো ঘটনা ঘটতে পারে।

XSS কীভাবে কাজ করে?

XSS মূলত ইউজারের ইনপুটকে যথাযথভাবে স্যানিটাইজ (Sanitize) বা এসকেপ (Escape) না করার কারণে ঘটে। ওয়েবসাইট যখন ইউজারের দেওয়া ডেটাকে সরাসরি ব্রাউজারে রেন্ডার করে, ব্রাউজার বুঝতে পারে না কোনটি আসল ডেটা আর কোনটি ক্ষতিকর স্ক্রিপ্ট। ব্রাউজার স্ক্রিপ্টটিকে ওয়েবসাইটেরই অংশ ভেবে রান করে দেয়।

XSS এর প্রকারভেদ

XSS কে সাধারণত তিনটি প্রধান ভাগে ভাগ করা যায়:

১. Stored XSS (Persistent XSS)

এটি সবচেয়ে বিপজ্জনক। এই আক্রমণে ক্ষতিকর স্ক্রিপ্টটি সরাসরি ডেটাবেস, ফোরাম পোস্ট, বা কমেন্ট সেকশনে সেভ হয়ে যায়। পরবর্তীতে যখনই কোনো ইউজার ওই পেজটি ভিজিট করে, সার্ভার ডেটাবেস থেকে সেই স্ক্রিপ্টটি ইউজারের ব্রাউজারে পাঠায় এবং তা এক্সিকিউট হয়।

২. Reflected XSS (Non-Persistent)

এই আক্রমণে স্ক্রিপ্ট ডেটাবেসে সেভ হয় না। বরং, ইউজারের দেওয়া ইনপুট (যেমন: সার্চ কোয়েরি) সরাসরি সার্ভার থেকে রেসপন্স হিসেবে ফিরে আসে (Reflect করে)। এটি সাধারণত ফিশিং লিংকের মাধ্যমে ছড়ানো হয়। উদাহরণস্বরূপ, একটি ভালনারেবল পাইথন কোড:

from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def search():
    query = request.args.get('q', '')
    # VULNERABLE: Directly rendering user input
    return f"<h1>Results for: {query}</h1>"

কেউ যদি [http://example.com/search?q=](http://example.com/search?q=)<script>alert('Hacked')</script> লিংকে ক্লিক করে, তবে স্ক্রিপ্টটি রান হয়ে যাবে।

৩. DOM-Based XSS

এই আক্রমণটি সার্ভারে যায়ই না; এটি পুরোপুরি ক্লায়েন্ট-সাইডে (ব্রাউজারে) ঘটে। যখন জাভাস্ক্রিপ্ট DOM (Document Object Model) ম্যানিপুলেট করার সময় অনিরাপদভাবে ইউজারের ইনপুট ব্যবহার করে, তখন এটি ঘটে।

// VULNERABLE DOM MANIPULATION
let userInput = window.location.hash.substring(1);
document.getElementById("output").innerHTML = userInput;

XSS প্রতিরোধের উপায় (Best Practices)

XSS প্রতিরোধ করতে হলে তোমাকে "Zero Trust" পলিসিতে কাজ করতে হবে—অর্থাৎ ইউজারের কোনো ইনপুটকেই বিশ্বাস করা যাবে না।

১. Output Encoding এবং Input Sanitization

ডেটাবেসে সেভ করার আগে বা ইউজারকে দেখানোর আগে ইনপুটকে এসকেপ (Escape) করে নিতে হবে। এর ফলে <script> ট্যাগটি HTML এলিমেন্ট হিসেবে রেন্ডার না হয়ে সাধারণ টেক্সট (যেমন: &lt;script&gt;) হিসেবে দেখাবে।

Python (Flask/Django) উদাহরণ: Django টেমপ্লেট বাই-ডিফল্ট অটো-এসকেপ করে। তবে ম্যানুয়ালি করতে চাইলে:

import html

@app.route('/search')
def search():
    query = request.args.get('q', '')
    # SAFE: Escaping HTML characters
    safe_query = html.escape(query)
    return f"<h1>Results for: {safe_query}</h1>"

Java (Spring Boot) উদাহরণ:

import org.springframework.web.util.HtmlUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SearchController {
    
    @GetMapping("/search")
    public String search(@RequestParam String q) {
        // SAFE: HTML escaping in Java
        String safeQuery = HtmlUtils.htmlEscape(q);
        return "<h1>Results for: " + safeQuery + "</h1>";
    }
}

২. ফ্রন্টএন্ড ফ্রেমওয়ার্কের সঠিক ব্যবহার (React)

তুমি যদি React ব্যবহার করো, তবে এটি বাই-ডিফল্ট XSS প্রোটেকশন দেয় (JSX অটোমেটিক্যালি ভ্যালু এসকেপ করে)। তবে React-এ একটি ডেঞ্জারাস প্রপার্টি আছে, যা থেকে দূরে থাকতে হবে:

// DANGEROUS: Avoid this in React unless strictly sanitized
<div dangerouslySetInnerHTML={{ __html: userInput }} />

৩. Content Security Policy (CSP) হেডার ব্যবহার করা

CSP হলো একটি সিকিউরিটি লেয়ার, যা ব্রাউজারকে বলে দেয় কোন সোর্স থেকে স্ক্রিপ্ট লোড করা নিরাপদ। সার্ভারের রেসপন্স হেডারে এটি যুক্ত করতে হয়।

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com;

CSP চালু থাকলে, ইনজেক্ট করা কোনো ইনলাইন স্ক্রিপ্ট (Inline script) ব্রাউজার এক্সিকিউট হতে দেবে না।

৪. HttpOnly এবং Secure Cookies

XSS এর মূল টার্গেট থাকে সেশন কুকি চুরি করা। কুকি সেট করার সময় HttpOnly ফ্ল্যাগ ব্যবহার করলে জাভাস্ক্রিপ্ট (যেমন: document.cookie) দিয়ে কোনোভাবেই কুকি রিড করা যায় না।

# SAFE: Setting secure cookies in Python
response.set_cookie("session_id", value=session_id, httponly=True, secure=True)

৫. innerHTML এর বদলে নিরাপদ মেথড ব্যবহার

DOM-Based XSS প্রতিরোধের জন্য জাভাস্ক্রিপ্টে innerHTML এর বদলে textContent বা innerText ব্যবহার করতে হবে।

// SAFE: Using textContent to prevent script execution
document.getElementById("output").textContent = userInput;

XSS একটি ভয়ংকর ত্রুটি হলেও, আধুনিক ফ্রেমওয়ার্ক (যেমন: Django, React, Spring Boot) বাই-ডিফল্ট অনেক প্রোটেকশন দেয়। এর পাশাপাশি Input Sanitization, HttpOnly Cookie এবং CSP Header-এর সঠিক কনফিগারেশনের মাধ্যমে সিস্টেমকে পুরোপুরি সুরক্ষিত করা সম্ভব। কোড ডিপ্লয় করার আগে পেনিট্রেশন টেস্টিং (Penetration Testing) বা অটোমেটেড স্ক্যানার চালানো সবসময় একটি ভালো প্র্যাকটিস।