JSON Toolkit

JSON দিয়ে XSS কীভাবে হয়

সংক্ষেপে: JSON নিজে কখনো চলে না। XSS হয় যখন আপনি এটিকে HTML ধরেন — সার্ভার-পক্ষ স্ট্রিং জোড়া লাগানো, ফ্রন্টএন্ড `innerHTML`, বা JSON সরাসরি স্ক্রিপ্ট ট্যাগে ইনলাইন করা।

মধ্যবর্তী~4 মিনিট পড়াপ্রকাশ 2026-10-30আপডেট 2026-10-30
JSON কীভাবে XSS হয় তার তিন পথ ও প্রতিরোধ

মূল কথা: JSON নিজে কখনো চলে না — আগে তিন আউটপুট পথ বন্ধ করুন: সার্ভার-পক্ষে প্রসঙ্গ অনুযায়ী এস্কেপ, innerHTML-এর বদলে textContent, আর JSON ইনলাইন করলে <-কে \u003c দিয়ে বদলানো।

{"name": "<img src=x onerror=alert(1)>"} বৈধ ডেটা। এটি বিপজ্জনক কি না সম্পূর্ণ নির্ভর করে আপনি কোথায় রাখছেন।

প্রবেশ এক: সার্ভার-পক্ষ স্ট্রিং গঠন

res.send(`<div>Hello, ${data.name}</div>`);

ব্রাউজার data.name-এর ভেতরের ট্যাগ পার্স করে। এখানে JSON কেবল কন্টেইনার; দোষ ভুল প্রসঙ্গের জন্য এস্কেপিংয়ের।

সমাধান: টেমপ্লেট ইঞ্জিনের ডিফল্ট এস্কেপিং ব্যবহার করুন (EJS-এ <%= %>, Vue ও Django-তে {{ }})। ব্যবহারকারী-নিয়ন্ত্রিত যেকোনো কিছুর জন্য <%- %>, v-html ও |safe এড়ান।

প্রবেশ দুই: innerHTML

el.innerHTML = user.bio;    // parses markup
el.textContent = user.bio;  // inserts text

React-এর {user.bio} ও Vue-র {{ user.bio }} টেক্সট নোড তৈরি করে আর ডিফল্টে নিরাপদ। dangerouslySetInnerHTML ও v-html স্পষ্ট opt-out।

সত্যিই rich text দরকার হলে ব্যাকএন্ড বিশ্বাস না করে হোয়াইটলিস্ট দিয়ে sanitise করুন (DOMPurify ও অনুরূপ)।

প্রবেশ তিন: স্ক্রিপ্ট ট্যাগে ইনলাইন

<script>
  window.__DATA__ = {"name": "x</script><script>alert(1)</script>"};
</script>

ডেটার ভেতরের </script> ব্লক আগেই বন্ধ করে আর তার পরের সব নতুন স্ক্রিপ্ট হিসেবে চলে। এটাই সবচেয়ে বাদ পড়া ক্ষেত্র।

JSON.stringify(data)
  .replace(/</g, '\\u003c')
  .replace(/>/g, '\\u003e')
  .replace(/&/g, '\\u0026');

এখনও বৈধ JSON, পার্সের পর অভিন্ন, আর ট্যাগ বন্ধ করতে পারে না। Next.js ও Nuxt __NEXT_DATA__ ও __NUXT__-এর জন্য একই কাজ করে।

জানার যোগ্য দুই প্রতিবেশী

JSON হাইজ্যাকিং — পুরোনো ব্রাউজার <script src> দিয়ে লোড JSON চালাত; Array পুনরায় সংজ্ঞায়িত করে কন্টেন্ট ফাঁস হতো। আধুনিক ব্রাউজার ঠিক করেছে, আর Content-Type: application/json প্লাস X-Content-Type-Options: nosniff বাকিটা বন্ধ করে।

JSONP-এর অবশিষ্ট — ব্যবহারকারী-নিয়ন্ত্রিত callback নাম নকশাগতভাবেই যেকোনো কোড এক্সিকিউশন। নতুন সিস্টেমে ব্যবহার করবেন না।

চেকলিস্ট

  • JSON ফিল্ড HTML-এ পৌঁছানো প্রতিটি জায়গা তার প্রসঙ্গ অনুযায়ী এস্কেপড (HTML, attribute, JS, URL)
  • API স্ট্রিং ভোগ করা কোনো innerHTML, v-html বা dangerouslySetInnerHTML নেই
  • ইনলাইন করা JSON <, > ও & এস্কেপ করে
  • Rich text হোয়াইটলিস্ট sanitisation-এর মধ্য দিয়ে যায়, ব্ল্যাকলিস্ট ফিল্টার নয়
  • রেসপন্স Content-Type: application/json ও nosniff বহন করে

সাধারণ প্রশ্ন

বৈধ JSON তবু XSS ঘটাতে পারে কেন?

JSON কেবল টেক্সট আর কখনো চলে না; বৈধ মানে কেবল পার্স হয়। বিপদ দেখা দেয় যখন তা HTML বা স্ক্রিপ্ট প্রসঙ্গে লেখা হয়: ব্রাউজার ট্যাগ পার্স করে, বা </script> ব্লক আগেই বন্ধ করে বাকিটা কোড হিসেবে চলে। দোষ আউটপুটে প্রসঙ্গ-সচেতন এস্কেপিংয়ের অনুপস্থিতি, ডেটা ফরম্যাট নয়।

API ফিল্ড রেন্ডারে textContent নাকি innerHTML?

textContent পছন্দ করুন: মান সাদা টেক্সট হিসেবে ঢোকায়, তাই ট্যাগ আক্ষরিকভাবে দেখায়। innerHTML মার্কআপ পার্স করে, তাই <img onerror=...> ধারণকারী API ফিল্ড চলে যায়। React-এর {user.bio} ও Vue-র {{ user.bio }} ডিফল্টে টেক্সট নোড তৈরি করে; dangerouslySetInnerHTML ও v-html স্পষ্ট opt-out।

<script> ট্যাগে ইনলাইন করা JSON কীভাবে এস্কেপ করব?

ডেটার ভেতরের </script> ব্লক আগেই বন্ধ করে বাকিটা নতুন স্ক্রিপ্ট হিসেবে চলে। সিরিয়ালাইজের পর <, > ও &-কে \u003c, \u003e ও \u0026 দিয়ে বদলান: ফল এখনও বৈধ JSON, অভিন্নভাবে পার্স হয়, আর ট্যাগ বন্ধ করতে পারে না।

আরও পড়ুন