বিশ্বস্ত প্রকারের সাথে DOM-ভিত্তিক ক্রস-সাইট স্ক্রিপ্টিং দুর্বলতা প্রতিরোধ করুন

ক্রিস্টোফ কোটোভিচ
Krzysztof Kotowicz

Browser Support

  • ক্রোম: ৮৩।
  • প্রান্ত: ৮৩।
  • ফায়ারফক্স: ১৪৮।
  • সাফারি: ২৬।

Source

DOM-ভিত্তিক ক্রস-সাইট স্ক্রিপ্টিং (DOM XSS) ঘটে যখন ব্যবহারকারী-নিয়ন্ত্রিত কোনো উৎস (যেমন ইউজারনেম, বা URL ফ্র্যাগমেন্ট থেকে নেওয়া কোনো রিডাইরেক্ট URL) থেকে ডেটা কোনো সিঙ্কে পৌঁছায়। এই সিঙ্ক হলো eval() মতো একটি ফাংশন বা .innerHTML এর মতো একটি প্রপার্টি সেটার, যা যেকোনো জাভাস্ক্রিপ্ট কোড এক্সিকিউট করতে পারে।

DOM XSS সবচেয়ে সাধারণ ওয়েব নিরাপত্তা দুর্বলতাগুলোর মধ্যে একটি, এবং ডেভেলপার দলগুলো প্রায়শই দুর্ঘটনাবশত তাদের অ্যাপে এটি যুক্ত করে ফেলে। Trusted Types আপনাকে অ্যাপ্লিকেশন লেখা, নিরাপত্তা পর্যালোচনা করা এবং বিপজ্জনক ওয়েব API ফাংশনগুলোকে ডিফল্টরূপে সুরক্ষিত করার মাধ্যমে সেগুলোকে DOM XSS দুর্বলতা থেকে মুক্ত রাখার জন্য প্রয়োজনীয় টুলস সরবরাহ করে। যেসব ব্রাউজার এখনও Trusted Types সমর্থন করে না, তাদের জন্য এটি একটি পলিফিল হিসেবে উপলব্ধ।

পটভূমি

বহু বছর ধরে DOM XSS সবচেয়ে প্রচলিত এবং বিপজ্জনক ওয়েব নিরাপত্তা দুর্বলতাগুলোর মধ্যে অন্যতম।

ক্রস-সাইট স্ক্রিপ্টিং দুই ধরনের হয়। কিছু XSS দুর্বলতা সার্ভার-সাইড কোডের কারণে ঘটে, যা অনিরাপদভাবে ওয়েবসাইট গঠনের জন্য HTML কোড তৈরি করে। অন্যগুলোর মূল কারণ থাকে ক্লায়েন্টে, যেখানে জাভাস্ক্রিপ্ট কোড ব্যবহারকারী-নিয়ন্ত্রিত বিষয়বস্তুসহ বিপজ্জনক ফাংশন কল করে।

সার্ভার-সাইড XSS প্রতিরোধ করতে, একাধিক স্ট্রিং জুড়ে দিয়ে HTML তৈরি করবেন না। এর পরিবর্তে নিরাপদ কনটেক্সচুয়াল-অটোএসকেপিং টেমপ্লেটিং লাইব্রেরি ব্যবহার করুন এবং অতিরিক্ত বাগ প্রতিরোধের জন্য একটি ননস-ভিত্তিক কন্টেন্ট সিকিউরিটি পলিসি (Content Security Policy) যুক্ত করুন।

এখন ব্রাউজারগুলোও ট্রাস্টেড টাইপস ব্যবহার করে ক্লায়েন্ট-সাইড DOM-ভিত্তিক XSS প্রতিরোধে সাহায্য করতে পারে।

এপিআই পরিচিতি

ট্রাস্টেড টাইপস নিম্নলিখিত ঝুঁকিপূর্ণ সিঙ্ক ফাংশনগুলোকে লক ডাউন করার মাধ্যমে কাজ করে। এগুলোর মধ্যে কয়েকটি হয়তো আপনি ইতিমধ্যেই চিনতে পারেন, কারণ ব্রাউজার নির্মাতা এবং ওয়েব ফ্রেমওয়ার্কগুলো নিরাপত্তার কারণে আপনাকে এই ফিচারগুলো ব্যবহার করা থেকে বিরত রাখে।

ট্রাস্টেড টাইপস ব্যবহার করলে, এই সিঙ্ক ফাংশনগুলিতে ডেটা পাঠানোর আগে আপনাকে তা প্রসেস করতে হবে। শুধুমাত্র একটি স্ট্রিং ব্যবহার করলে তা ব্যর্থ হয়, কারণ ব্রাউজার জানে না যে ডেটাটি বিশ্বাসযোগ্য কি না।

না
anElement.innerHTML  = location.href;
Trusted Types সক্রিয় থাকলে, ব্রাউজার একটি TypeError দেখায় এবং স্ট্রিং ব্যবহার করে DOM XSS সিঙ্কের ব্যবহার প্রতিরোধ করে।

ডেটা যে নিরাপদে প্রক্রিয়াজাত করা হয়েছে তা বোঝাতে, একটি বিশেষ অবজেক্ট—একটি ট্রাস্টেড টাইপ—তৈরি করুন।

করুন
anElement.innerHTML = aTrustedHTML;
  
ট্রাস্টেড টাইপস সক্রিয় থাকলে, ব্রাউজার এইচটিএমএল স্নিপেট প্রত্যাশাকারী সিঙ্কগুলোর জন্য একটি TrustedHTML অবজেক্ট গ্রহণ করে। এছাড়াও অন্যান্য সংবেদনশীল সিঙ্কগুলোর জন্য TrustedScript এবং TrustedScriptURL অবজেক্ট রয়েছে।

ট্রাস্টেড টাইপস আপনার অ্যাপ্লিকেশনের DOM XSS আক্রমণের ঝুঁকি উল্লেখযোগ্যভাবে হ্রাস করে। এটি নিরাপত্তা পর্যালোচনাকে সহজ করে এবং আপনাকে রানটাইমে, ব্রাউজারে, আপনার কোড কম্পাইল, লিন্টিং বা বান্ডলিং করার সময় করা টাইপ-ভিত্তিক নিরাপত্তা পরীক্ষাগুলো প্রয়োগ করতে দেয়।

বিশ্বস্ত প্রকারগুলি কীভাবে ব্যবহার করবেন

বিষয়বস্তু নিরাপত্তা নীতি লঙ্ঘনের প্রতিবেদনের জন্য প্রস্তুত হন

আপনি একটি রিপোর্ট কালেক্টর স্থাপন করতে পারেন, যেমন ওপেন-সোর্স reporting-api-processor বা go-csp-collector , অথবা এর বাণিজ্যিক বিকল্পগুলোর মধ্যে একটি ব্যবহার করতে পারেন। এছাড়াও আপনি একটি ReportingObserver ব্যবহার করে ব্রাউজারে কাস্টম লগিং যোগ করতে এবং ত্রুটি ডিবাগ করতে পারেন।

const observer = new ReportingObserver((reports, observer) => {
    for (const report of reports) {
        if (report.type !== 'csp-violation' ||
            report.body.effectiveDirective !== 'require-trusted-types-for') {
            continue;
        }

        const violation = report.body;
        console.log('Trusted Types Violation:', violation);

        // ... (rest of your logging and reporting logic)
    }
}, { buffered: true });

observer.observe();

অথবা ইভেন্ট লিসেনার যোগ করে:

document.addEventListener('securitypolicyviolation',
    console.error.bind(console));

শুধুমাত্র প্রতিবেদনের জন্য একটি CSP হেডার যোগ করুন

যেসব ডকুমেন্টকে আপনি ট্রাস্টেড টাইপস-এ মাইগ্রেট করতে চান, সেগুলিতে নিম্নলিখিত HTTP রেসপন্স হেডারটি যোগ করুন:

Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

এখন সমস্ত লঙ্ঘন //my-csp-endpoint.example এ রিপোর্ট করা হয়, কিন্তু ওয়েবসাইটটি কাজ করে চলে। পরবর্তী বিভাগে ব্যাখ্যা করা হয়েছে //my-csp-endpoint.example কীভাবে কাজ করে।

বিশ্বস্ত প্রকারের লঙ্ঘন শনাক্ত করুন

এখন থেকে, যখনই ট্রাস্টেড টাইপস কোনো লঙ্ঘন শনাক্ত করবে, ব্রাউজার একটি কনফিগার করা report-uri তে একটি রিপোর্ট পাঠাবে। উদাহরণস্বরূপ, যখন আপনার অ্যাপ্লিকেশন innerHTML এ একটি স্ট্রিং পাস করে, ব্রাউজার নিম্নলিখিত রিপোর্টটি পাঠায়:

{
"csp-report": {
    "document-uri": "https://my.url.example",
    "violated-directive": "require-trusted-types-for",
    "disposition": "report",
    "blocked-uri": "trusted-types-sink",
    "line-number": 39,
    "column-number": 12,
    "source-file": "https://my.url.example/script.js",
    "status-code": 0,
    "script-sample": "Element innerHTML <img src=x"
}
}

এখানে বলা হচ্ছে যে https://my.url.example/script.js ফাইলের ৩৯ নম্বর লাইনে, <img src=x দিয়ে শুরু হওয়া স্ট্রিং ব্যবহার করে innerHTML কল করা হয়েছে। এই তথ্যটি আপনাকে কোডের কোন অংশগুলো DOM XSS তৈরি করছে এবং সেগুলোতে পরিবর্তন আনা প্রয়োজন, তা খুঁজে বের করতে সাহায্য করবে।

লঙ্ঘনগুলো সংশোধন করুন

ট্রাস্টেড টাইপ ভায়োলেশন ঠিক করার জন্য কয়েকটি উপায় আছে। আপনি সমস্যা সৃষ্টিকারী কোডটি সরিয়ে ফেলতে পারেন, কোনো লাইব্রেরি ব্যবহার করতে পারেন , একটি ট্রাস্টেড টাইপ পলিসি তৈরি করতে পারেন অথবা, শেষ উপায় হিসেবে, একটি ডিফল্ট পলিসি তৈরি করতে পারেন

ত্রুটিপূর্ণ কোডটি পুনরায় লিখুন

এমন হতে পারে যে, নিয়ম-বহির্ভূত কোডটির আর প্রয়োজন নেই, অথবা যে ফাংশনগুলো নিয়ম লঙ্ঘন করে, সেগুলো বাদ দিয়ে কোডটি নতুন করে লেখা যেতে পারে:

করুন
el.textContent = '';
const img = document.createElement('img');
img.src = 'xyz.jpg';
el.appendChild(img);
না
el.innerHTML = '<img src=xyz.jpg>';

একটি লাইব্রেরি ব্যবহার করুন

কিছু লাইব্রেরি আগে থেকেই ট্রাস্টেড টাইপ তৈরি করে, যা আপনি সিঙ্ক ফাংশনগুলোতে পাস করতে পারেন। উদাহরণস্বরূপ, আপনি একটি HTML স্নিপেটকে স্যানিটাইজ করতে এবং XSS পেলোডগুলো অপসারণ করতে DOMPurify ব্যবহার করতে পারেন।

import DOMPurify from 'dompurify';
el.innerHTML = DOMPurify.sanitize(html, {RETURN_TRUSTED_TYPE: true});

DOMPurify ট্রাস্টেড টাইপস সমর্থন করে এবং একটি TrustedHTML অবজেক্টে মোড়ানো পরিমার্জিত HTML ফেরত দেয়, যাতে ব্রাউজার কোনো লঙ্ঘন তৈরি না করে।

একটি বিশ্বস্ত প্রকার নীতি তৈরি করুন

কখনও কখনও নিয়ম লঙ্ঘনের কারণ হওয়া কোডটি সরানো যায় না, এবং ভ্যালুটি পরিশুদ্ধ করে আপনার জন্য একটি ট্রাস্টেড টাইপ তৈরি করে দেওয়ার মতো কোনো লাইব্রেরিও থাকে না। সেইসব ক্ষেত্রে, আপনি নিজেই একটি ট্রাস্টেড টাইপ অবজেক্ট তৈরি করে নিতে পারেন।

প্রথমে, একটি পলিসি তৈরি করুন। পলিসি হলো ট্রাস্টেড টাইপ-এর ফ্যাক্টরি, যা তাদের ইনপুটের উপর নির্দিষ্ট নিরাপত্তা নিয়ম প্রয়োগ করে:

if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
  const escapeHTMLPolicy = trustedTypes.createPolicy('myEscapePolicy', {
    createHTML: string => string.replace(/\</g, '&lt;')
  });
}

এই কোডটি myEscapePolicy নামে একটি পলিসি তৈরি করে, যা এর createHTML() ফাংশন ব্যবহার করে TrustedHTML অবজেক্ট তৈরি করতে পারে। এতে সংজ্ঞায়িত নিয়মগুলো নতুন HTML এলিমেন্ট তৈরি হওয়া আটকাতে < অক্ষরগুলোকে HTML-escape করে।

পলিসিটি এইভাবে ব্যবহার করুন:

const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML);  // true
el.innerHTML = escaped;  // '&lt;img src=x onerror=alert(1)>'

একটি ডিফল্ট নীতি ব্যবহার করুন

কখনও কখনও আপনি সমস্যা সৃষ্টিকারী কোডটি পরিবর্তন করতে পারেন না, উদাহরণস্বরূপ, যদি আপনি একটি CDN থেকে কোনো থার্ড-পার্টি লাইব্রেরি লোড করেন। সেক্ষেত্রে, একটি ডিফল্ট পলিসি ব্যবহার করুন:

if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
  trustedTypes.createPolicy('default', {
    createHTML: (string, sink) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true})
  });
}

যেসব সিঙ্ক শুধুমাত্র ট্রাস্টেড টাইপ গ্রহণ করে, সেখানে কোনো স্ট্রিং ব্যবহৃত হলে default নামক পলিসিটি ব্যবহৃত হয়।

বিষয়বস্তু সুরক্ষা নীতি প্রয়োগে পরিবর্তন করুন

যখন আপনার অ্যাপ্লিকেশনটি আর কোনো লঙ্ঘন তৈরি করবে না, তখন আপনি বিশ্বস্ত প্রকারগুলি (Trusted Types) প্রয়োগ করা শুরু করতে পারেন:

Content-Security-Policy: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

এখন, আপনার ওয়েব অ্যাপ্লিকেশন যতই জটিল হোক না কেন, একমাত্র আপনার কোনো একটি পলিসির কোডই DOM XSS দুর্বলতা তৈরি করতে পারে, এবং পলিসি তৈরি সীমিত করার মাধ্যমে আপনি এটিকে আরও সুরক্ষিত করতে পারেন।

আরও পড়ুন