পাঠ ৫৭ · ৬০-এর মধ্যে · মডিউল ১২
Home / Courses / Cybersecurity & Ethical Hacking / CTF: স্যান্ডবক্সড XSS

CTF ওয়াকথ্রু: স্যান্ডবক্সড XSS

CTF walkthrough: sandboxed XSS
৯ মিনিট পড়া উচ্চ · Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • L26-এর Reflected/Stored/DOM XSS ও এস্কেপিং-ভিত্তিক ডিফেন্স আবার ঝালাই করা
  • একজন CTF সলভারের ধাপে-ধাপে চিন্তাপ্রক্রিয়া — payload জমা দেওয়া থেকে "solved" নিশ্চিত করা পর্যন্ত
  • একটি অটোমেটেড CTF checker আসলে কীভাবে কাজ করে (এবং আমাদের সিমুলেশন কীভাবে সেটিকে সরলীকৃত করেছে)
  • ঠিক একই পেলোড একটি সঠিকভাবে এস্কেপ করা রেন্ডারারের বিরুদ্ধে কেন ব্যর্থ হয়

১ · চ্যালেঞ্জ পরিস্থিতি — টয় গেস্টবুক

কল্পনা করুন একটি অনুমোদিত CTF প্ল্যাটফর্মে একটি ছোট্ট চ্যালেঞ্জ আছে: একটি সাধারণ গেস্টবুকGuestbookএকটি ওয়েব পেজ যেখানে ভিজিটররা মন্তব্য জমা দিতে পারে এবং সেগুলো পরে অন্য ভিজিটরদের কাছে প্রদর্শিত হয় — Stored XSS শেখানোর জন্য একটি ক্লাসিক টয় উদাহরণ। অ্যাপ, যেখানে ভিজিটররা একটি মন্তব্য জমা দিতে পারে এবং সেটি সাথে সাথে "রেন্ডার" হয়ে দেখানো হয়। চ্যালেঞ্জের ফ্ল্যাগ পাওয়ার শর্ত: এমন একটি ইনপুট জমা দিন যাতে আপনার <script> ট্যাগ HTML-এস্কেপ না হয়ে হুবহু আউটপুটে থেকে যায় — এটিই প্রমাণ করে যে অ্যাপটি Stored XSS-এর জন্য দুর্বল (L26-এর মূল সংজ্ঞা অনুযায়ী)।

এই চ্যালেঞ্জটি সম্পূর্ণ টয় ও স্যান্ডবক্সড

পুরো "গেস্টবুক" আসলে একটি ইন-মেমরি Python লিস্ট, এবং কোনো real ব্রাউজার আমাদের পেলোড এক্সিকিউট করছে না — আমরা শুধু স্ট্রিং হিসেবে যাচাই করছি পেলোডটি এস্কেপড ফর্মে আছে নাকি raw ফর্মে। কোর্সের CLAUDE.md সুরক্ষা নিয়ম অনুযায়ী এই পাঠে কোনো real নেটওয়ার্ক কল বা real ব্রাউজার এক্সিকিউশন নেই।

২ · একজন CTF সলভারের চিন্তাপ্রক্রিয়া

একটি বাস্তব CTF চ্যালেঞ্জে হাতে বসে একজন সলভার সাধারণত এই ধাপগুলো অনুসরণ করেন —

  1. ধাপ ১ · বেসলাইন পরীক্ষা — প্রথমে একটি নিরীহ ইনপুট (যেমন সাধারণ টেক্সট) জমা দিয়ে দেখুন অ্যাপটি স্বাভাবিকভাবে কাজ করছে কি না।
  2. ধাপ ২ · প্রোবিং — একটি ছোট্ট বিশেষ ক্যারেক্টার (যেমন < বা ") দিয়ে দেখুন সেটি এস্কেপ হয়ে &lt; হয়ে যাচ্ছে, নাকি হুবহু থেকে যাচ্ছে।
  3. ধাপ ৩ · ক্লাসিক পেলোড — যদি এস্কেপিং না দেখেন, তাহলে ক্লাসিক টেস্ট পেলোড <script>alert('XSS')</script> জমা দিন।
  4. ধাপ ৪ · যাচাই — রেন্ডার হওয়া আউটপুট পরীক্ষা করে দেখুন পেলোডটি হুবহু (unescaped) আছে কি না — বাস্তব CTF-এ এখানেই একটি হেডলেস ব্রাউজার-চেকার alert() ফায়ার হলো কি না তা স্বয়ংক্রিয়ভাবে যাচাই করে "solved" মার্ক করে।
লক্ষ্য করুন — এই পুরো প্রক্রিয়ায় কোনো জটিল টুল লাগেনি। XSS-এর মতো অনেক ওয়েব দুর্বলতা আসলে পদ্ধতিগত পর্যবেক্ষণ দিয়েই খুঁজে পাওয়া যায়: ইনপুট দিন, আউটপুট পর্যবেক্ষণ করুন, প্যাটার্ন বুঝুন। এই একই পদ্ধতি L56-এর SQL ইনজেকশন CTF ওয়াকথ্রুতেও প্রয়োগ হয়েছিল।

৩ · কোড দিয়ে সমাধান — ইনসিকিউর বনাম সিকিউর রেন্ডারার

নিচে L26-এর ঠিক একই render_comment() প্যাটার্নের দুটি ভার্সন আছে — একটি ইনসিকিউর (raw স্ট্রিং ফেরত দেয়), একটি সিকিউর (html.escape() ব্যবহার করে)। সাথে আছে একটি ctf_check_solved() ফাংশন যা রেন্ডার হওয়া আউটপুটে raw <script> ট্যাগ আছে কি না তা যাচাই করে — এটিই এই সিমুলেশনে আমাদের "স্বয়ংক্রিয় CTF checker"।

Python
import html

# টয় "গেস্টবুক" — CTF চ্যালেঞ্জের ব্যাকএন্ড, ইন-মেমরি লিস্ট (L26-এর প্যাটার্ন)
guestbook = []

def render_comment_insecure(comment):
    """ইনসিকিউর ভার্সন — raw string ফেরত দেয়, কোনো এস্কেপিং নেই।"""
    guestbook.append(comment)
    return f"<div class='comment'>{comment}</div>"

def render_comment_secure(comment):
    """সিকিউর ভার্সন — html.escape() দিয়ে আউটপুট এনকোড করা।"""
    return f"<div class='comment'>{html.escape(comment)}</div>"

def ctf_check_solved(rendered_output):
    """CTF checker সিমুলেশন — বাস্তব CTF-এ এটি হেডলেস ব্রাউজারে alert() ফায়ার
    হলো কি না চেক করে; এখানে real ব্রাউজার নেই বলে raw <script> ট্যাগ
    unescaped অবস্থায় আউটপুটে আছে কি না তা যাচাই করছি।"""
    return "<script>" in rendered_output

payload = "<script>alert('XSS')</script>"

print("ধাপ ১ · পেলোড জমা দেওয়া হলো:", payload)
print()

insecure_output = render_comment_insecure(payload)
print("ইনসিকিউর গেস্টবুকে রেন্ডার হলো:", insecure_output)
print("CTF checker ফলাফল:", "SOLVED" if ctf_check_solved(insecure_output) else "NOT SOLVED")
print()

secure_output = render_comment_secure(payload)
print("সিকিউর গেস্টবুকে রেন্ডার হলো:  ", secure_output)
print("CTF checker ফলাফল:", "SOLVED" if ctf_check_solved(secure_output) else "NOT SOLVED")

    
ফলাফল বিশ্লেষণ

ইনসিকিউর ভার্সনে পেলোড হুবহু থেকে যায় — ctf_check_solved() তখন True ফেরত দেয়, অর্থাৎ চ্যালেঞ্জ "SOLVED"। সিকিউর ভার্সনে html.escape() পেলোডের < ও >-কে &lt;/&gt;-তে রূপান্তর করে দেয়, ফলে ctf_check_solved() কখনোই raw <script> খুঁজে পায় না — চ্যালেঞ্জ "NOT SOLVED"। এটিই প্রমাণ করে html.escape()-এর মতো আউটপুট-এনকোডিং XSS-এর বিরুদ্ধে কার্যকর ডিফেন্স।

৪ · কেন এটি শুধুই একটি সিমুলেশন

বাস্তব CTF প্ল্যাটফর্মে একটি স্বয়ংক্রিয় হেডলেস ব্রাউজার (যেমন Puppeteer বা Selenium) সত্যিই আপনার জমা দেওয়া পেলোড রেন্ডার করে এবং alert() বা document.cookie-এর মতো কোনো সাইড-ইফেক্ট সত্যিই ঘটেছে কি না তা মনিটর করে ফ্ল্যাগ ইস্যু করে। এই পাঠে কোনো real ব্রাউজার নেই বলে আমরা সেই পুরো প্রক্রিয়াকে একটি সরল স্ট্রিং-চেক দিয়ে সরলীকৃত করেছি — যুক্তিটা (unescaped payload = vulnerable) হুবহু একই থাকে।

মূল কথা · Key takeaway

একটি XSS চ্যালেঞ্জ সমাধান করা মানেই "হ্যাকিং" নয় — এটি একটি নিয়ন্ত্রিত, অনুমোদিত পরিবেশে একটি নির্দিষ্ট দুর্বলতা প্যাটার্ন যাচাই করা। ঠিক একই পদ্ধতিগত চিন্তা (বেসলাইন → প্রোব → পেলোড → যাচাই) একজন পেশাদার পেনিট্রেশন টেস্টার তার লিখিত-অনুমোদিত এনগেজমেন্টে প্রয়োগ করেন (L01, L02)।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ বাস্তব CTF প্ল্যাটফর্মে একটি হেডলেস ব্রাউজার ব্যবহার করে চেক করা হয়, এখানে আমরা কেন শুধু স্ট্রিং ম্যাচিং ব্যবহার করলাম?

এই কোর্সের কোড সেলগুলো সম্পূর্ণ স্যান্ডবক্সড ও ইন-মেমরি (L01, CLAUDE.md সুরক্ষা নিয়ম) — কোনো real ব্রাউজার এক্সিকিউট করা এখানে সম্ভব বা নিরাপদ নয়। তবে মূল যুক্তিটি অভিন্ন: যদি একটি <script> ট্যাগ এস্কেপ ছাড়া আউটপুটে থেকে যায়, তাহলে একটি real ব্রাউজারে সেটি এক্সিকিউট হতোই — স্ট্রিং-চেক সেই একই সিদ্ধান্তে পৌঁছানোর একটি নিরাপদ, সরলীকৃত উপায়।

প্র ০২ "বেসলাইন → প্রোব → পেলোড → যাচাই" পদ্ধতি কেন সরাসরি ক্লাসিক পেলোড দিয়ে শুরু করার চেয়ে ভালো?

বেসলাইন ও প্রোবিং ধাপ আপনাকে বলে দেয় ঠিক কী ধরনের এস্কেপিং (যদি থাকে) প্রয়োগ হচ্ছে — এটি না জেনে সরাসরি একটি জটিল পেলোড ব্যবহার করলে ব্যর্থতার কারণ বোঝা কঠিন হয় (এস্কেপিং আছে? পেলোড ভুল? অন্য কোনো ফিল্টার আছে?)। ধাপে-ধাপে পরীক্ষা প্রতিটি সম্ভাবনাকে আলাদাভাবে নিশ্চিত করে — এটি একটি পদ্ধতিগত, পুনরাবৃত্তিযোগ্য প্রক্রিয়া, শুধু অনুমান নয়।

প্র ০৩ এই একই টেকনিক অনুমোদিত CTF প্ল্যাটফর্মের বাইরে একটি real ওয়েবসাইটে প্রয়োগ করলে আইনি অবস্থা কী দাঁড়ায়?

L01-এ শেখা মূলনীতি অনুযায়ী — কৌশল একই থাকলেও, লিখিত অনুমতি ছাড়া কোনো real সিস্টেমে এই পেলোড টেস্ট করা অনুমোদিত অ্যাক্সেস আইন লঙ্ঘন করে, এমনকি যদি কোনো প্রকৃত ক্ষতি না হয়। CTF প্ল্যাটফর্ম নিজেই টেস্টিং-এর জন্য স্পষ্ট অনুমতি দেয় বলেই এটি বৈধ অনুশীলন — এই অনুমতিটাই একমাত্র পার্থক্য।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোড সেলে payload-কে একটি নিরীহ স্ট্রিং (যেমন "Hello!") দিয়ে বদলে দিন এবং দেখুন ctf_check_solved() উভয় রেন্ডারারের জন্য কী ফলাফল দেয়।

    একটি নিরীহ পেলোডে কোনো <script> ট্যাগই নেই, তাই উভয় রেন্ডারারের (ইনসিকিউর ও সিকিউর) আউটপুটেই ctf_check_solved() "NOT SOLVED" ফেরত দেবে — এটি প্রমাণ করে চেকারটি শুধু নির্দিষ্ট পেলোড প্যাটার্নের জন্যই ট্রিগার হয়, যেকোনো ইনপুটের জন্য নয়।

  2. চিন্তা করুন: যদি ctf_check_solved() শুধু "<script>"-এর বদলে "alert" শব্দটি খুঁজত, তাহলে কি এটি এখনও একটি নির্ভরযোগ্য চেকার হতো?

    না — "alert" শব্দটি এস্কেপ করা টেক্সটেও (যেমন একজন ব্যবহারকারী লিখেছে "please alert me") উপস্থিত থাকতে পারে, ফলে false positive হবে। এটিই দেখায় কেন বাস্তব CTF checker-রা আসল ব্রাউজার এক্সিকিউশন পর্যবেক্ষণ করে (side-effect সত্যিই ঘটল কি না), নিছক টেক্সট-ম্যাচিং দিয়ে নয় — আমাদের সরলীকরণটি শুধু শেখার উদ্দেশ্যে, প্রোডাকশন-গ্রেড checker ডিজাইনের জন্য নয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
CTF ওয়াকথ্রু: স্যান্ডবক্সড SQL ইনজেকশন