CTF ওয়াকথ্রু: স্যান্ডবক্সড SQL ইনজেকশন
এই পাঠে যা শিখবেন
- একজন CTF সলভার কীভাবে ধাপে ধাপে একটি SQLi-দুর্বল লগইন ফর্ম টেস্ট করেন
- L20-এর
' OR '1'='1বাইপাসটি বাস্তবে "কাজ করার" পেছনের যুক্তি আরও গভীরভাবে - একটি সিকিউর, parameterized-স্টাইল তুলনা কীভাবে একই payload-কে সম্পূর্ণ নিষ্ক্রিয় করে দেয়
- কেন এই ধরনের প্র্যাকটিস শুধুমাত্র স্যান্ডবক্সড/অনুমোদিত পরিবেশে করা উচিত
১ · চ্যালেঞ্জ ব্রিফ
একটি অনুমোদিত CTF প্ল্যাটফর্মে "Web — Easy" ক্যাটাগরির একটি চ্যালেঞ্জ: একটি লগইন ফর্ম দেওয়া আছে, লক্ষ্য হলো
পাসওয়ার্ড না জেনেই admin হিসেবে লগইন করা। এই লেসনের ব্যাকএন্ড সম্পূর্ণ toy —
শুধুমাত্র একটি in-memory Python লিস্ট, কোনো বাস্তব ডেটাবেস সার্ভার নেই। লক্ষ্যটি সম্পূর্ণ
নিয়ন্ত্রিত ও নিরাপদ, ঠিক L20-এর মতো।
২ · সলভারের চিন্তাপ্রক্রিয়া — ধাপে ধাপে
- ধাপ ১ — একটি নিরীহ ভুল ইনপুট দিয়ে বেসলাইন যাচাই করুন। সঠিক ইউজারনেম কিন্তু ভুল পাসওয়ার্ড দিয়ে ট্রাই করুন — যদি লগইন প্রত্যাখ্যাত হয় (প্রত্যাশিত), এটি নিশ্চিত করে ফর্মটি আসলে ক্রেডেনশিয়াল যাচাই করছে, একটি ব্রোকেন no-op নয়।
- ধাপ ২ — একটি single quote (
') দিয়ে query logic-এ প্রবেশের চেষ্টা করুন। বাস্তব SQLi টেস্টিং-এ, একটি একক quote প্রায়ই একটি SQL syntax error ট্রিগার করে যদি ইনপুটটি সরাসরি query-তে concatenate করা হয় (কোনো এসকেপিং ছাড়া) — এটি একটি শক্তিশালী সংকেত যে ইনজেকশন সম্ভব। - ধাপ ৩ — ক্লাসিক বাইপাস payload প্রয়োগ করুন। ইউজারনেম ফিল্ডে
' OR '1'='1দিন। যদি ব্যাকএন্ড আসলে string concatenation দিয়ে query তৈরি করে, তাহলে WHERE ক্লজ কার্যকরভাবে... WHERE username='' OR '1'='1' AND ...-এর মতো হয়ে যায় —'1'='1'সবসময় true, তাই পুরো শর্তটি true হয়ে যায় এবং প্রথম রেকর্ডটি (প্রায়ই admin) রিটার্ন হয়, পাসওয়ার্ড যাচাই না করেই।
এই পুরো ওয়াকথ্রুটি একটি সম্পূর্ণ স্যান্ডবক্সড, in-memory toy ডেটাবেসের বিরুদ্ধে চলে — কোনো বাস্তব নেটওয়ার্ক কল বা প্রকৃত ডেটাবেস সার্ভার জড়িত নেই। L01-এ যেমন বলা হয়েছে, এই ঠিক same কৌশল কোনো বাস্তব ওয়েবসাইট বা অ্যাপ্লিকেশনের বিরুদ্ধে লিখিত অনুমতি ছাড়া প্রয়োগ করা ফৌজদারি অপরাধ — এমনকি যদি আপনি কোনো ক্ষতি না করেন বা শুধু "টেস্ট" করছেন বলে মনে করেন। এই কৌশল শুধুমাত্র নিজের ল্যাব, এই লেসনের মতো স্যান্ডবক্সড কোড, অথবা স্পষ্ট লিখিত অনুমতি ও স্কোপসহ একটি অনুমোদিত CTF/বাগ-বাউন্টি প্ল্যাটফর্মে প্রয়োগ করুন।
৩ · সমাধান — সম্পূর্ণ কোড
নিচের কোডে L20-এর ঠিক same insecure toy প্যাটার্ন পুনরায় ব্যবহার করা হয়েছে: একটি in-memory
users_db লিস্ট, একটি insecure login_insecure() যা string-concatenation-স্টাইল query
সিমুলেট করে (কোনো real SQL এক্সিকিউট হচ্ছে না, শুধু বাইপাস-লজিকের সিমুলেশন), এবং একটি সিকিউর
login_safe() যা কখনো query string তৈরি করে না।
# CTF চ্যালেঞ্জের toy in-memory "ডেটাবেস" — বাস্তব কোনো DB সার্ভার নেই
users_db = [
{"username": "admin", "password": "S3cur3P@ss!", "role": "admin"},
{"username": "guest", "password": "guest123", "role": "guest"},
]
def login_insecure(username, password):
# শুধুমাত্র শিক্ষার জন্য — string-concatenation-স্টাইল query সিমুলেশন।
# কোনো real SQL ইঞ্জিন এখানে এক্সিকিউট হচ্ছে না, শুধু বাইপাস-লজিক সিমুলেট করা হচ্ছে।
simulated_query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
if "' OR '1'='1" in username or "' OR '1'='1" in password:
# ক্লাসিক bypass — WHERE ক্লজ সবসময় true হয়ে যায়, পাসওয়ার্ড কখনো চেক হয় না
return {"query": simulated_query, "result": users_db[0]}
for user in users_db:
if user["username"] == username and user["password"] == password:
return {"query": simulated_query, "result": user}
return {"query": simulated_query, "result": None}
def login_safe(username, password):
# সিকিউর ভার্সন — কখনো query string তৈরি করে না, শুধু ডেটা তুলনা করে
for user in users_db:
if user["username"] == username and user["password"] == password:
return user
return None
print("=== ইনসিকিউর ভার্সনের বিরুদ্ধে CTF সলভ ===")
print("ধাপ ১ — বেসলাইন (ভুল পাসওয়ার্ড):")
step1 = login_insecure("admin", "wrongpass")
print(" ফলাফল:", step1["result"])
print("ধাপ ৩ — ক্লাসিক বাইপাস payload:")
step3 = login_insecure("' OR '1'='1", "anything")
print(" simulated query:", step3["query"])
print(" ফলাফল:", step3["result"])
print()
print("=== একই payload সিকিউর ভার্সনের বিরুদ্ধে ===")
safe_result = login_safe("' OR '1'='1", "anything")
print(" ফলাফল:", safe_result)
login_insecure()-এ পুরো admin রেকর্ড (পাসওয়ার্ড সহ) রিটার্ন
হয়েছে, যদিও পাসওয়ার্ড কখনো সঠিকভাবে যাচাই হয়নি। কিন্তু login_safe()-এ ঠিক একই payload-এর ফলাফল
None — কারণ এটি কখনো ইনপুটকে একটি query-তে ব্যাখ্যা করার সুযোগ দেয় না, শুধু সরাসরি ডেটা তুলনা করে
(parameterized query-র সমতুল্য যুক্তি)। এটিই CTF চ্যালেঞ্জের "ফ্ল্যাগ" — সফল বাইপাস বনাম প্রত্যাখ্যাত প্রচেষ্টা।
একটি CTF ওয়াকথ্রু সবসময় দুটি জিনিস প্রমাণ করে — দুর্বলতা কীভাবে কাজ করে এবং ফিক্স কীভাবে সেটি নিষ্ক্রিয় করে। শুধু exploit দেখানো অর্ধেক পাঠ — L20-এর মতোই, প্রকৃত মূল্য হলো বোঝা যে parameterized/data-only তুলনা কেন এই পুরো আক্রমণ-শ্রেণিকে গোড়া থেকে অসম্ভব করে দেয়, শুধু একটি নির্দিষ্ট payload ব্লক করে নয়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ সলভার প্রথমে ধাপ ১-এ একটি সাধারণ ভুল পাসওয়ার্ড ট্রাই করলেন, সরাসরি বাইপাস payload দিয়ে শুরু করলেন না কেন?
বেসলাইন আচরণ যাচাই করা একটি গুরুত্বপূর্ণ প্রথম ধাপ — এটি নিশ্চিত করে যে ফর্মটি আদৌ ক্রেডেনশিয়াল-ভিত্তিক প্রত্যাখ্যান/গ্রহণ লজিক প্রয়োগ করছে। যদি সরাসরি বাইপাস payload ট্রাই করে "সফল" হন, কিন্তু আসলে ফর্মটি সবসময়ই সব ইনপুট গ্রহণ করত (একটি সম্পূর্ণ ভিন্ন, আরও গুরুতর বাগ), তাহলে ভুল উপসংহারে পৌঁছাতে পারতেন। বেসলাইন টেস্ট নিশ্চিত করে যে পর্যবেক্ষিত পরিবর্তনটি সত্যিই payload-এর কারণে ঘটেছে।
প্র ০২
' OR '1'='1 payload-টি ঠিক কেন কাজ করে — WHERE ক্লজের যুক্তিতে কী ঘটছে?
একটি insecure query WHERE username='<input>' AND password='...' এভাবে তৈরি হলে, ইনপুটে
' OR '1'='1 বসালে এটি হয়ে যায় WHERE username='' OR '1'='1' AND password='...'।
SQL-এ OR-এর প্রায়োরিটি এমন যে '1'='1' অংশটি সবসময় true, ফলে গোটা শর্তটি true হয়ে
যায় নির্বিশেষে বাকি অংশে কী আছে — তাই ডেটাবেস প্রথম ম্যাচিং রেকর্ড রিটার্ন করে, পাসওয়ার্ড আসলে যাচাই না
করেই।
প্র ০৩ এই লেসনে দেখানো toy সিমুলেশন কেন বাস্তব SQL ইঞ্জিন এক্সিকিউট না করেও এই শিক্ষামূলক লক্ষ্য পূরণ করতে যথেষ্ট?
SQL ইনজেকশনের মূল শিক্ষণীয় বিষয় হলো যুক্তি — অবিশ্বস্ত ইনপুট query-স্ট্রাকচারের অংশ হয়ে গেলে কী
ঘটে। এই যুক্তিটি একটি সাধারণ Python if "' OR '1'='1" in ... চেক দিয়েও নিখুঁতভাবে প্রদর্শন করা
যায়, বাস্তব SQL ইঞ্জিন ছাড়াই — এবং এটি করাটাই এই কোর্সের CLAUDE.md নিরাপত্তা নীতির মূল ভিত্তি: কৌশলের
যুক্তি শিখুন সম্পূর্ণ নিরাপদে, কোনো বাস্তব সিস্টেম বা নেটওয়ার্ককে স্পর্শ না করে।
অনুশীলন
-
চিন্তা করুন: উপরের কোডে
login_insecure()-কেguestইউজারনেম ও একটি ভুল পাসওয়ার্ড দিয়ে (বাইপাস payload ছাড়া) কল করুন। ফলাফল কী হবে তা আগে অনুমান করুন।ফলাফল হবে
None— কারণ বাইপাস প্যাটার্ন' OR '1'='1ইনপুটে নেই, তাই কোডটি স্বাভাবিক লুপে যায় এবংusers_db-তে ইউজারনেম-পাসওয়ার্ড ম্যাচ খুঁজে না পেয়েNoneরিটার্ন করে। এটি নিশ্চিত করে যে insecure ভার্সনটি শুধুমাত্র নির্দিষ্ট বাইপাস প্যাটার্নের ক্ষেত্রেই ভেঙে পড়ে, সব ইনপুটের ক্ষেত্রে নয়। -
পরীক্ষা করুন: পাসওয়ার্ড ফিল্ডে (ইউজারনেমের বদলে)
' OR '1'='1payload বসিয়েlogin_insecure("admin", "' OR '1'='1")কল করুন এবংlogin_safe()-এ একই ইনপুট দিয়ে তুলনা করুন।login_insecure()-এ এই চেকটিusernameওpasswordউভয় ফিল্ডেই বাইপাস প্যাটার্ন খোঁজে, তাই পাসওয়ার্ড ফিল্ডে দিলেও একই বাইপাস ঘটবে এবংusers_db[0](admin) রিটার্ন হবে।login_safe()-এ কোনো ফরম্যাটেই কোনো পার্থক্য হয় না — এটি সবসময়Noneরিটার্ন করবে, কারণ এটি ইনপুটকে কখনোই query-লজিকের অংশ হিসেবে ব্যাখ্যা করে না, শুধু প্লেইন স্ট্রিং তুলনা করে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৬০টি পাঠ পরবর্তী পাঠ — CTF ওয়াকথ্রু: স্যান্ডবক্সড XSS — এই মডিউলের পরবর্তী চ্যালেঞ্জ।
- L20 · A03: SQL ইনজেকশন রিভিউ এই CTF চ্যালেঞ্জের ভিত্তি হওয়া মূল দুর্বলতা ও ফিক্স আবার দেখুন।
- System Design & Software Architecture কোর্স সঙ্গী কোর্স বাস্তব সিস্টেমে ডেটাবেস অ্যাক্সেস স্তর কীভাবে নিরাপদে ডিজাইন করা হয় তা শিখতে দেখুন।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design ও Cybersecurity — সব এক জায়গায়।