PHP’তে ডাটা Sanitization বনাম Validation

20250604 1640 PHP Input Security simple compose 01jwx8c37mewz8fg3zq641thd9

আসসালামুআলাইকুম, সবাইকে স্বাগতম আজকের লেখায়। আজকের বিষয়টি PHP তে ওয়েব ডেভলপমেন্টে প্রোফেশনাল কাজ করার জন্য খুবই গুরুত্বপূর্ন। ওয়েব এপ্লিকেশন নিয়ে কাজ করেন কিন্তু ইউজার ইনপুট বা ইউজার রিকুয়েষ্ট নিয়ে দুঃচিন্তা করেন না এমন ডেভলপার খুজে পাওয়া বোধহয় একটু কষ্টেরই হবে। এই লেখায় আমি চেষ্টা করবো ইউজার ইনপুটকে ফিল্টার করার গুরুত্ব, প্রয়োজনীয়তা ও এর প্রয়োগ সম্পর্কে একটু খুচরা আলাপ করতে। তাহলে চলুন আমরা একটু একটু করে আগাই।

প্রথমেই যে কথাটি মনে রাখতে হবে ‘কোনো ইউজারের ইনপুটকে বিশ্বাস করা যাবে না, সেটি যদি আপনার বাবাও পাঠায়‘। Fox Mulder এর ভাষায় —

trust no one.

তাহলে উপায় কি?

হ্যা এটি একটি ভালো প্রশ্ন, যদি ইউজারকে তথা ইউজার ইনপুটকে বিশ্বাসই না করি তবে এ এপ্লিকেশন দিয়ে কি হবে? হুম চিন্তা নেই, আপনি ইউজারের ইনপুটকৃত ডাটাকে নিয়ে কাজ করার পূর্বেই সেটিকে পরীক্ষা নিরীক্ষা করে নিতে পারবেন। আপনি যা চাচ্ছেন তা ইউজার দিচ্ছে কিনা অথবা ইউজার অনাকাংখিত কোনো ডাটা রিকুয়েস্টে পাঠিয়েছে কিনা সেটি ভালো করে যাচাই করে নিতে হবে। প্রয়োজনে ইউজারের ডাটাকে আপনার মতো করে মডিফাই করে নিন, কারন আপনার অ্যাপ্লিকেশনে একটি অনাকাংখিত ডাটা হতে পারে সারাজীবনের কান্না। PHP’তে যেসকল সোর্সের মাধ্যমে আপনার সিস্টেমের কাছে ডাটা আসতে পারেঃ

  • $_GET
  • $_POST
  • $_REQUEST
  • $_COOKIE
  • $argv
  • php://stdin
  • php://input
  • file_get_contents()
  • Remote databases
  • Remote APIs
  • Data from your clients

Sanitization

এটি হলো এমন একটি প্রক্রিয়া যেখানে ইউজার ইনপুটকৃত ডাটাকে স্টোরেজে পাঠানোর পূর্বেই অথবা এই ডাটা নিয়ে কোনো প্রসেসের পূর্বেই এটি থেকে সমস্থ অনাকাংখিত কন্টেন্ট মুছে দেয়া হয় অথবা পরিশোধন করা হয়। এই প্রক্রিয়াটিকে আপনি ইউজার ইনপুট ও ডাটা স্টোরেজের মধ্যে একটি লেয়ারের সাথে কল্পনা করতে পারেন। এখানে মনে রাখা জরুরী যে ইউজারকে কখনই আপনার সিষ্টেমকে কন্ট্রোল করতে দেয়া যাবে না।
একটা উধাহরন দিয়ে বোঝার চেষ্টা করিঃ ধরুন আপনি একটি ফর্ম ডিজাইন করলেন যেখানে একটা ইনপুট ফিল্ড আছে এবং সেই ফিল্ডে আপনি ইউজারকে তার সম্মন্ধে কিছু লিখতে বললেন, অর্থাৎ ইউজার তার বায়ো লিখবে। প্রায় সকল ইউজার এখানে ঠিকঠাকভাবেই ডাটা ইনপুট করেছে কিন্তু একজন পাকনা ইউজার এসে সেই ইনপুট ফিল্ডে কিছু HTML কোড লিখে দিলো যেটি একটি iframe দিয়ে অন্য একটি ওয়েবসাইট কে প্রদর্শন করে। ভেবে দেখুন এটি কি হওয়া উচিৎ ছিলো। এতে করে সাইটে vulnerability ইসু তৈরী হয়েছে যেখানে ইউজার আপনার সিষ্টেমে HTML inject করতে পারছে। যেটি কখনই কাম্য নয় কারন এতে করে সাইটের সিকিউরিটি, ডিজাইন ও পারফরম্যান্স সবকিছুই নষ্ট হচ্ছে। তাহলে আমরা এখন কি করবো? হ্যা, এই সময়ে আমাদের প্রধান কাজ হলো ইনপুটের ডাটা filter অর্থাৎ sanitize করা। PHP’তে HTML ডাটা sanitize করার জন্য বেশকিছু ফাংশন আছে, যেমনঃ htmlentitieshtmlspecialchars. তাহলে চলুন একটা বাস্তবিক উদাহরন দেখিঃ

$input = '<button name="submit">Delere</button>';
echo htmlentities($input);

স্বাভাবিক ক্ষেত্রে এর আউটপুট হওয়া উচিৎ ছিলো একটি বাটন, কিন্তু যেহেতু আমরা এখানে htmlentities ফাংশনটি ব্যবহার করেছি তাই এটি এর সকল স্পেশাল ক্যারক্টারকে এনকোড করে ফেলবে। অর্থাৎ এরকমের একটা টেক্সট রেসপন্স হিসেবে দিবে এবং HTML রেন্ডার করে সেটাকে টেক্সট হিসেবেই দেখাবে।

PHP Output

kdSP7MF

HTML Output

Sij6N8a

এই একই ঘটনা ঘটতে পারে ডাটার ভিতর SQL Injection এর মাধ্যমে। হ্যা আপনি ইউজারকে ভালোবেসে প্রোগ্রামে কোনো ডাটা Sanitization করলেন না। এরপরে ইউজার অথেনটিকেশনের জন্য ইউজারের কাছে ইউজারনেম ও পাসওয়ার্ড চাইলেন কিন্তু আপনার এ ইউজারেও একটু পাকনা তাই সে ইউজার নেম এর স্থানে একটি SQL query লিখে দিলো, ব্যাস কেল্লা ফতে। এই ইউজার অথেনটিক ইউজারনেম ও পাসওয়ার্ড ছাড়াই আপনার সিষ্টেম এ্যাক্সেস অর্থাৎ লগইন করতে পারবে। কি ব্যাপারটা মজার না? হ্যা যতটুকুনা মজার তার থেকে ঢের বেশি বিপদজনক।

$username = $_GET['username'];

// Vulnerable SQL query
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);

এখানের কোয়ারীটা খুবই বিপদজনক, কারন আমরা ইউজারের ইনপুটকৃত ডাটাকে Sanitize করি নাই, ফলে ইউজার যদি username প্যারামিটারে একটা SQL কোয়েরী ইনজেক্ট করে তাহলে সে সকল ইউজারের ইনফরমেশন দেখতে পারবে। ধরুন নিচের মতো করে যদি সে Query Parameter’য়ে ডাটা পাস করে,

http://example.com/login.php?username=admin' OR '1'='1

তাহলে উপরে কোয়েরীটা হয়ে যাবে এরকম,

SELECT * FROM users WHERE username = 'admin' OR '1'='1'

ফলে এই কোয়োরীতে username যদি admin নাও হয় তারপরেও '1'='1' true হবার কারনে এটি সকল ইউজারকে রিটার্ন করবে। যেটা কাঙ্খিত না। উপরের কোয়েরীটা হতে পারতো এরকমের,

$username = $_GET['username'];

// Escape the input
$safe_username = mysqli_real_escape_string($conn, $username);

// Safe (but not safest) query
$sql = "SELECT * FROM users WHERE username = '$safe_username'";
$result = $conn->query($sql);

তাই ডাটাবেসে কোনো কোয়েরী চালানোর পূর্বে সেটিকে sanitize করে নিন। নিচে কিছু ডাটা স্যানিটাইজেশনের ফাংশন দেয়া হলোঃ

  • htmlentities
  • htmlspecialchars
  • mysqli_real_escape_string
  • strip_tags

Validation

Sanitization ও Validation এদুটো এক জিনিস নয়। অনেকেই এদুটো বিষয়কে গুলিয়ে ফেলেন। ভ্যালিডেশন ডাটার পরিবর্তন বা পরিবর্ধন করেনা। ভ্যালিডেশন হচ্ছে সেই ঘটনা যেখানে সিষ্টেম কি চাচ্ছে আর ইউজার কি দিচ্ছে সেটার তুলনা করে। ধরুন আপনি চাচ্ছেন একটি ইনপুট ফিল্ডে ইউজার যেন ইমেইল দেয়। ইউজারের ইনপুটটি ইমেইল কিনা এটি চেক করে দেখার নামই হচ্ছে ভ্যালিডেশন। অর্থাৎ আমি যা চাচ্ছি ইউজার তাই দিয়েছে কিনা এটা নিশ্চিত হওয়াকেই বলে Validation.

$email = 'talk@nahid.co';

if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "This ($email) email address is considered valid.";
}

filter_var এই ফাংশনটি PHP তে মূলত ডাটা ভ্যালিডেশনের জন্য ব্যবহৃত হয়। এরকম আরো বেশ কিছু ফাংশান আছে। যেমনঃ

  • isset
  • empty
  • is_string
  • is_integer
  • is_boolean
  • is_numeric
  • is_array

এছাড়াও রয়েছে বিভিন্ন থার্ডপার্টি লাইব্রেরী, ডাটা বা ইনপুট ভ্যালিডেশনের জন্য আপনি আমার Validx প্যাকেজটি ব্যবহার করতে পারেন।

Escape

Escape আর Sanitize প্রায় একই জিনিস, এটা শুধু জাস্ট এটা টার্মিনোলজি। এর মূল পার্থক্য হলো sanitize ডাটাকে স্টোরের পূর্বেই ফিল্টার করে আর Escape ডাটাকে ফিল্টার করে Render করার পূর্বে অর্থাৎ কোনো রিকুয়েষ্টকে রেসপন্সের পূর্বে যে ওয়েতে Sanitize করা হয় সেটাই মূলত Escape। Escape এর ক্ষেত্রে sanitize এর ফাংশনগুলোই ব্যবহার করা যাবে। তবে আপনি যদি কোনো টেমপ্লেট ইঞ্জিন ব্যবহার করেনে যেমনঃ twig অথবা smarty তাহলে এটি অটোমেটিক্যালি ডাটা escape করে নিবে।

তাহলে আমরা জানলাম কেন ডাটাকে filter ও ‍validate করার প্রয়োজন হয় ও কিভাবে এগুলো কাজ করে। আশা করি সবাই বুঝতে পেরেছেন। কোনো বিষয়ে পরিষ্কার না হলে কিংবা আমি কিছু ভুল বলে থাকলে কমেন্টে সেটা শেয়ার করতে পারেন।

তো আশা করবো এরপর থেকে সবাই অবশ্যই ডাটাকে স্টোর করার পূর্বে অথবা রেন্ডার করার পূর্বে এ কাজ গুলো করে নিবেন।

ধন্যবাদ সবাইকে 🙂