স্যানিটাইজার API এর সাথে নিরাপদ DOM ম্যানিপুলেশন

নতুন স্যানিটাইজার API-এর লক্ষ্য একটি পৃষ্ঠায় নিরাপদে ঢোকানোর জন্য নির্বিচারে স্ট্রিংগুলির জন্য একটি শক্তিশালী প্রসেসর তৈরি করা।

জ্যাক জে
Jack J

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

সেই ঝুঁকি কমাতে, নতুন স্যানিটাইজার এপিআই প্রস্তাবের লক্ষ্য হল একটি শক্তিশালী প্রসেসর তৈরি করা যাতে নির্বিচারে স্ট্রিংগুলি নিরাপদে একটি পৃষ্ঠায় ঢোকানো যায়। এই নিবন্ধটি API এর সাথে পরিচয় করিয়ে দেয় এবং এর ব্যবহার ব্যাখ্যা করে।

// Expanded Safely !!
$div.setHTML(`<em>hello world</em><img src="" onerror=alert(0)>`, new Sanitizer())

ব্যবহারকারীর ইনপুট এস্কেপিং

DOM-এ ব্যবহারকারীর ইনপুট, ক্যোয়ারী স্ট্রিং, কুকি বিষয়বস্তু ইত্যাদি সন্নিবেশ করার সময়, স্ট্রিংগুলিকে অবশ্যই সঠিকভাবে এস্কেপ করতে হবে। .innerHTML এর মাধ্যমে DOM ম্যানিপুলেশনের দিকে বিশেষ মনোযোগ দেওয়া উচিত, যেখানে unescaped স্ট্রিংগুলি XSS-এর একটি সাধারণ উৎস।

const user_input = `<em>hello world</em><img src="" onerror=alert(0)>`
$div.innerHTML = user_input

আপনি যদি উপরের ইনপুট স্ট্রিং-এ HTML বিশেষ অক্ষর এড়িয়ে যান বা .textContent ব্যবহার করে এটিকে প্রসারিত করেন, তাহলে alert(0) কার্যকর করা হবে না। যাইহোক, যেহেতু ব্যবহারকারীর দ্বারা যুক্ত করা <em> কেও স্ট্রিং হিসাবে প্রসারিত করা হয়েছে, তাই এই পদ্ধতিটি HTML-এ পাঠ্য সজ্জা রাখার জন্য ব্যবহার করা যাবে না।

এখানে সবচেয়ে ভালো কাজ হচ্ছে পালানো নয়, স্যানিটাইজ করা

ব্যবহারকারীর ইনপুট স্যানিটাইজ করা

পালানো এবং স্যানিটাইজ করার মধ্যে পার্থক্য

Escaping বলতে বোঝায় বিশেষ HTML অক্ষর প্রতিস্থাপন HTML Entities দিয়ে।

স্যানিটাইজিং বলতে এইচটিএমএল স্ট্রিং থেকে শব্দার্থগতভাবে ক্ষতিকারক অংশ (যেমন স্ক্রিপ্ট এক্সিকিউশন) অপসারণকে বোঝায়।

উদাহরণ

পূর্ববর্তী উদাহরণে, <img onerror> ত্রুটি হ্যান্ডলারকে কার্যকর করতে দেয়, কিন্তু যদি onerror হ্যান্ডলারটি সরানো হয়, তাহলে <em> অক্ষত রেখে এটি নিরাপদে DOM-এ প্রসারিত করা সম্ভব হবে।

// XSS 🧨
$div.innerHTML = `<em>hello world</em><img src="" onerror=alert(0)>`
// Sanitized ⛑
$div.innerHTML = `<em>hello world</em><img src="">`

সঠিকভাবে স্যানিটাইজ করার জন্য, ইনপুট স্ট্রিংটিকে HTML হিসাবে পার্স করা, ক্ষতিকারক বলে মনে করা ট্যাগ এবং বৈশিষ্ট্যগুলি বাদ দেওয়া এবং ক্ষতিকারকগুলি রাখা প্রয়োজন৷

প্রস্তাবিত স্যানিটাইজার API স্পেসিফিকেশনের লক্ষ্য হল ব্রাউজারগুলির জন্য একটি আদর্শ API হিসাবে এই ধরনের প্রক্রিয়াকরণ প্রদান করা।

স্যানিটাইজার API

স্যানিটাইজার API নিম্নলিখিত উপায়ে ব্যবহার করা হয়:

const $div = document.querySelector('div')
const user_input = `<em>hello world</em><img src="" onerror=alert(0)>`
$div.setHTML(user_input, { sanitizer: new Sanitizer() }) // <div><em>hello world</em><img src=""></div>

যাইহোক, { sanitizer: new Sanitizer() } হল ডিফল্ট আর্গুমেন্ট। তাই এটা ঠিক নিচের মত হতে পারে।

$div.setHTML(user_input) // <div><em>hello world</em><img src=""></div>

এটা লক্ষনীয় যে setHTML() Element সংজ্ঞায়িত করা হয়েছে। Element একটি পদ্ধতি হওয়ায়, পার্স করার প্রসঙ্গটি স্ব-ব্যাখ্যামূলক ( <div> এই ক্ষেত্রে), পার্সিং একবার অভ্যন্তরীণভাবে করা হয়, এবং ফলাফল সরাসরি DOM-এ প্রসারিত হয়।

একটি স্ট্রিং হিসাবে স্যানিটাইজেশনের ফলাফল পেতে, আপনি setHTML() ফলাফল থেকে .innerHTML ব্যবহার করতে পারেন।

const $div = document.createElement('div')
$div.setHTML(user_input)
$div.innerHTML // <em>hello world</em><img src="">

কনফিগারেশনের মাধ্যমে কাস্টমাইজ করুন

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

const config = {
  allowElements: [],
  blockElements: [],
  dropElements: [],
  allowAttributes: {},
  dropAttributes: {},
  allowCustomElements: true,
  allowComments: true
};
// sanitized result is customized by configuration
new Sanitizer(config)

নিম্নলিখিত বিকল্পগুলি উল্লেখ করে যে কীভাবে স্যানিটাইজেশন ফলাফলটি নির্দিষ্ট উপাদানের সাথে আচরণ করবে।

allowElements : স্যানিটাইজারের যে উপাদানগুলো রাখা উচিত তার নাম।

blockElements : স্যানিটাইজারকে তাদের বাচ্চাদের ধরে রাখার সময় উপাদানগুলির নামগুলি অপসারণ করা উচিত।

dropElements : স্যানিটাইজারকে তাদের বাচ্চাদের সাথে যে উপাদানগুলি অপসারণ করা উচিত তার নাম।

const str = `hello <b><i>world</i></b>`

$div.setHTML(str)
// <div>hello <b><i>world</i></b></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowElements: [ "b" ]}) })
// <div>hello <b>world</b></div>

$div.setHTML(str, { sanitizer: new Sanitizer({blockElements: [ "b" ]}) })
// <div>hello <i>world</i></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowElements: []}) })
// <div>hello world</div>

আপনি নিম্নলিখিত বিকল্পগুলির সাথে স্যানিটাইজার নির্দিষ্ট বৈশিষ্ট্যগুলিকে অনুমতি দেবে বা অস্বীকার করবে তাও নিয়ন্ত্রণ করতে পারেন:

  • allowAttributes
  • dropAttributes

allowAttributes এবং dropAttributes বৈশিষ্ট্যগুলি অ্যাট্রিবিউটের মিল তালিকার প্রত্যাশা করে — যে বস্তুগুলির কীগুলি বৈশিষ্ট্যের নাম এবং মানগুলি লক্ষ্য উপাদানগুলির তালিকা বা * ওয়াইল্ডকার্ড।

const str = `<span id=foo class=bar style="color: red">hello</span>`

$div.setHTML(str)
// <div><span id="foo" class="bar" style="color: red">hello</span></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowAttributes: {"style": ["span"]}}) })
// <div><span style="color: red">hello</span></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowAttributes: {"style": ["p"]}}) })
// <div><span>hello</span></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowAttributes: {"style": ["*"]}}) })
// <div><span style="color: red">hello</span></div>

$div.setHTML(str, { sanitizer: new Sanitizer({dropAttributes: {"id": ["span"]}}) })
// <div><span class="bar" style="color: red">hello</span></div>

$div.setHTML(str, { sanitizer: new Sanitizer({allowAttributes: {}}) })
// <div>hello</div>

allowCustomElements হল কাস্টম উপাদানের অনুমতি বা অস্বীকার করার বিকল্প। যদি তাদের অনুমতি দেওয়া হয়, উপাদান এবং বৈশিষ্ট্যগুলির জন্য অন্যান্য কনফিগারেশন এখনও প্রযোজ্য।

const str = `<custom-elem>hello</custom-elem>`

$div.setHTML(str)
// <div></div>

const sanitizer = new Sanitizer({
  allowCustomElements: true,
  allowElements: ["div", "custom-elem"]
})
$div.setHTML(str, { sanitizer })
// <div><custom-elem>hello</custom-elem></div>

API পৃষ্ঠ

DomPurify সঙ্গে তুলনা

DOMpurify একটি সুপরিচিত লাইব্রেরি যা স্যানিটাইজেশন কার্যকারিতা প্রদান করে। স্যানিটাইজার API এবং DOMPurify-এর মধ্যে প্রধান পার্থক্য হল যে DOMPurify একটি স্ট্রিং হিসাবে স্যানিটাইজেশনের ফলাফল প্রদান করে, যা আপনাকে .innerHTML এর মাধ্যমে একটি DOM উপাদানে লিখতে হবে।

const user_input = `<em>hello world</em><img src="" onerror=alert(0)>`
const sanitized = DOMPurify.sanitize(user_input)
$div.innerHTML = sanitized
// `<em>hello world</em><img src="">`

যখন স্যানিটাইজার API ব্রাউজারে প্রয়োগ করা হয় না তখন DOMpurify একটি ফলব্যাক হিসাবে কাজ করতে পারে।

DOMpurify বাস্তবায়নের কয়েকটি খারাপ দিক রয়েছে। যদি একটি স্ট্রিং ফেরত দেওয়া হয়, তাহলে ইনপুট স্ট্রিংটি DOMpurify এবং .innerHTML দ্বারা দুবার পার্স করা হয়। এই দ্বৈত পার্সিং প্রক্রিয়াকরণের সময় নষ্ট করে, তবে দ্বিতীয় পার্সিংয়ের ফলাফল প্রথমটির থেকে আলাদা হওয়ার কারণে আকর্ষণীয় দুর্বলতাও হতে পারে।

HTML-এরও পার্স করার জন্য প্রসঙ্গ প্রয়োজন। উদাহরণস্বরূপ, <td> বোঝায় <table> , কিন্তু <div> এ নয়। যেহেতু DOMPurify.sanitize() শুধুমাত্র একটি স্ট্রিং একটি আর্গুমেন্ট হিসেবে নেয়, তাই পার্সিং প্রসঙ্গটি অনুমান করা উচিত ছিল।

স্যানিটাইজার এপিআই DOMpurify পদ্ধতির উপর উন্নতি করে এবং ডবল পার্সিংয়ের প্রয়োজনীয়তা দূর করতে এবং পার্সিং প্রসঙ্গ স্পষ্ট করার জন্য ডিজাইন করা হয়েছে।

API স্থিতি এবং ব্রাউজার সমর্থন

স্যানিটাইজার এপিআই স্ট্যান্ডার্ডাইজেশন প্রক্রিয়ায় আলোচনার অধীনে রয়েছে এবং ক্রোম এটি বাস্তবায়নের প্রক্রিয়ায় রয়েছে।

ধাপ স্ট্যাটাস
1. ব্যাখ্যাকারী তৈরি করুন সম্পূর্ণ
2. স্পেসিফিকেশন খসড়া তৈরি করুন সম্পূর্ণ
3. প্রতিক্রিয়া সংগ্রহ করুন এবং ডিজাইনের উপর পুনরাবৃত্তি করুন সম্পূর্ণ
4. ক্রোম অরিজিন ট্রায়াল সম্পূর্ণ
5. লঞ্চ করুন M105 এ পাঠানোর উদ্দেশ্য

Mozilla: এই প্রস্তাবটিকে প্রোটোটাইপ করার মূল্য বিবেচনা করে এবং সক্রিয়ভাবে এটি বাস্তবায়ন করছে

WebKit: WebKit মেলিং তালিকায় প্রতিক্রিয়া দেখুন।

কিভাবে স্যানিটাইজার API সক্ষম করবেন

about://flags বা CLI বিকল্পের মাধ্যমে সক্ষম করা হচ্ছে

ক্রোম

ক্রোম স্যানিটাইজার এপিআই বাস্তবায়নের প্রক্রিয়ায় রয়েছে। Chrome 93 বা তার পরবর্তীতে, আপনি about://flags/#enable-experimental-web-platform-features পতাকা সক্ষম করে আচরণটি চেষ্টা করতে পারেন। ক্রোম ক্যানারি এবং ডেভ চ্যানেলের আগের সংস্করণগুলিতে, আপনি --enable-blink-features=SanitizerAPI এর মাধ্যমে এটি সক্ষম করতে পারেন এবং এখনই এটি ব্যবহার করে দেখুন৷ পতাকা সহ Chrome কীভাবে চালাবেন তার নির্দেশাবলী দেখুন।

ফায়ারফক্স

ফায়ারফক্স একটি পরীক্ষামূলক বৈশিষ্ট্য হিসাবে স্যানিটাইজার API প্রয়োগ করে। এটি সক্ষম করতে, about:configdom.security.sanitizer.enabled পতাকাটিকে true হিসাবে সেট করুন।

বৈশিষ্ট্য সনাক্তকরণ

if (window.Sanitizer) {
  // Sanitizer API is enabled
}

প্রতিক্রিয়া

আপনি যদি এই APIটি চেষ্টা করেন এবং কিছু প্রতিক্রিয়া জানান, আমরা এটি শুনতে চাই। স্যানিটাইজার API GitHub সমস্যাগুলির বিষয়ে আপনার চিন্তাভাবনা শেয়ার করুন এবং এই API-তে আগ্রহী বিশেষ লেখক এবং লোকেদের সাথে আলোচনা করুন।

আপনি Chrome এর বাস্তবায়নে কোনো বাগ বা অপ্রত্যাশিত আচরণ খুঁজে পেলে, এটি প্রতিবেদন করতে একটি বাগ ফাইল করুনBlink>SecurityFeature>SanitizerAPI উপাদান নির্বাচন করুন এবং বাস্তবায়নকারীদের সমস্যা ট্র্যাক করতে সহায়তা করার জন্য বিশদ ভাগ করুন।

ডেমো

স্যানিটাইজার এপিআই অ্যাকশনে দেখতে মাইক ওয়েস্টের স্যানিটাইজার এপিআই প্লেগ্রাউন্ডটি দেখুন:

তথ্যসূত্র


আনস্প্ল্যাশে ছবি তুলেছেন তৌফিক বারভূইয়া