Comment

PHP প্রসেসিং ফর্ম (Processing Forms)

PHP ক্রস-সাইট রিকোয়েস্ট ফ্রগেরই (CSRF)

Estimated reading: 4 minutes 11 views Contributors

সারাংশ: এই টিউটোরিয়ালে, আপনি ক্রস-সাইট রিকোয়েস্ট ফোরজি (CSRF) আক্রমণ এবং পিএইচপি-তে কীভাবে তাদের প্রতিরোধ করবেন সে সম্পর্কে শিখবেন।

CSRF কি

CSRF মানে ক্রস-সাইট অনুরোধ জালিয়াতি। এটি এমন এক ধরণের আক্রমণ যেখানে একজন হ্যাকার আপনাকে এমন একটি ওয়েবসাইটের বিরুদ্ধে একটি পদক্ষেপ করতে বাধ্য করে যেখানে আপনি বর্তমানে লগ ইন করেছেন।

উদাহরণস্বরূপ, আপনি malicious-site.com-এ যান যার একটি লুকানো ফর্ম রয়েছে৷ এবং সেই ফর্মটি yourbank.com/transfer-fund ফর্মে পৃষ্ঠা লোডের পরে জমা দেয়।

যেহেতু আপনি বর্তমানে yourbank.com-এ লগ ইন করেছেন, তাই অনুরোধটি নীরবে আপনার ব্যাঙ্ক অ্যাকাউন্ট থেকে একটি তহবিল স্থানান্তর করে।

yourbank.com/transfer-fund সঠিকভাবে CSRF প্রয়োগ করলে, এটি একটি এককালীন টোকেন তৈরি করে এবং তহবিল স্থানান্তর ফর্মে এইভাবে টোকেন সন্নিবেশ করায়:

<input type="hidden" 
       name="token"
       value="b3f44c1eb885409c222fdb78c125f5e7050ce4f3d15e8b15ffe51678dd3a33d3a18dd3">

malicious-site.com ফর্মটি জমা দিলে, yourbank.com/transfer-fund ফর্মটি yourbank.com-এর সার্ভারে থাকা টোকেনের সাথে তুলনা করে।

যদি জমা দেওয়া ডেটাতে টোকেনটি না থাকে বা এটি সার্ভারে থাকা টোকেনের সাথে না মেলে, তবে ফান্ড ট্রান্সফার ফর্ম জমাটি প্রত্যাখ্যান করবে এবং একটি ত্রুটি ফেরত দেবে।

যখন malicious-site.com ফর্মটি জমা দেওয়ার চেষ্টা করে, তখন টোকেনটি পাওয়া যাবে না বা মিলবে না।

PHP তে CSRF টোকেন কীভাবে প্রয়োগ করবেন

প্রথমে, একটি এককালীন টোকেন তৈরি করুন এবং এটিকে $_SESSION ভেরিয়েবলে যোগ করুন:

$_SESSION['token'] = md5(uniqid(mt_rand(), true));

দ্বিতীয়ত, একটি লুকানো ক্ষেত্র যোগ করুন যার মান হল টোকেন এবং ফর্মটিতে এটি সন্নিবেশ করান:

<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?? '' ?>">

তৃতীয়ত, ফর্মটি জমা দেওয়ার সময়, INPUT_POST-এ টোকেনটি বিদ্যমান আছে কিনা তা পরীক্ষা করুন এবং এটিকে $_SESSION[‘token’]-এর সাথে তুলনা করুন:

<?php

$token = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);

if (!$token || $token !== $_SESSION['token']) {
    // return 405 http status code
    header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed');
    exit;
} else {
    // process the form
}

যদি টোকেনটি বিদ্যমান না থাকে বা মেলে না, তাহলে 405 HTTP স্ট্যাটাস কোড ফেরত দিন এবং প্রস্থান করুন।

PHP CSRF উদাহরণ

কিভাবে একটি CSRF আক্রমণ প্রতিরোধ করা যায় তা প্রদর্শন করার জন্য আমরা একটি সাধারণ তহবিল স্থানান্তর ফর্ম তৈরি করব:

প্রথমে, নিম্নলিখিত ফাইল এবং ডিরেক্টরি তৈরি করুন:

.
├── css
│   └── style.css
├── inc
│   ├── footer.php
│   ├── get.php
│   ├── header.php
│   └── post.php
└── index.php

header.php

header.php ফাইলটিতে এমন কোড রয়েছে যা পৃষ্ঠার প্রথম বিভাগটি দেখায়:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <title>PHP CSRF - Fund Transfer Demo</title>
</head>
<body>
    <main>

footer.php

footer.php ফাইলটিতে header.php ফাইলের খোলার ট্যাগের সাথে সম্পর্কিত ক্লোজিং ট্যাগ রয়েছে:

     </main>
</body>
</html>

index.php

ফাইল নিম্নলিখিত কোডটি index.php ফাইলে রাখুন:

<?php

session_start();

require __DIR__ .  '/inc/header.php';

$errors = []; // for storing the error messages
$inputs = []; // for storing sanitized input values

$request_method = strtoupper($_SERVER['REQUEST_METHOD']);

if ($request_method === 'GET') {
	// generate a token
	$_SESSION['token'] = bin2hex(random_bytes(35));
	// show the form
	require __DIR__ . '/inc/get.php';
} elseif ($request_method === 'POST') {
	// handle the form submission
	require __DIR__ .  '/inc/post.php';
	// re-display the form if the form contains errors
	if ($errors) {
		require	__DIR__ .  '/inc/get.php';
	}
}

require __DIR__ . '/inc/footer.php';

কিভাবে index.php কাজ করে।

প্রথমে, session_start() ফাংশন কল করে একটি নতুন সেশন শুরু করুন; ত্রুটি বার্তা সংরক্ষণ করতে $errors অ্যারে ব্যবহার করুন এবং $inputs অ্যারে স্যানিটাইজড ইনপুট মান সংরক্ষণ করতে হয়।

এরপর, যদি HTTP অনুরোধ GET হয় তাহলে get.php ফাইলে ফর্মটি দেখান।

নিম্নলিখিত এক-কালীন টোকেন তৈরি করে:

$_SESSION['token'] = bin2hex(random_bytes(35));

random_bytes(35) 35টি অক্ষর সহ একটি এলোমেলো স্ট্রিং তৈরি করে। এবং bin2hex() ফাংশন র্যান্ডম স্ট্রিং এর হেক্সাডেসিমেল উপস্থাপনা প্রদান করে। টোকেন এই মত দেখাবে:

c4724e490407a1770efcc4ea19776c06e0bd4614a9dd37900f5eb001581dffee9b377a

তারপর, যদি HTTP অনুরোধটি POST হয় তবে ফর্ম জমা দেওয়ার জন্য post.php ফাইল থেকে কোডটি লোড করুন।

এর পরে, ফর্ম ডেটা ভুল হলে ত্রুটি বার্তা সহ ফর্মটি আবার দেখান৷ মনে রাখবেন যে ফর্মটিতে ত্রুটি থাকলে, $errors-এ ত্রুটির বার্তা থাকবে।

অবশেষে, তহবিল সফলভাবে স্থানান্তর করা হয়েছে তা জানানোর জন্য message.php ফাইল থেকে একটি বার্তা প্রদর্শন করুন।

get.php

নিম্নলিখিত দুটি ইনপুট ক্ষেত্র স্থানান্তর পরিমাণ এবং প্রাপকের অ্যাকাউন্ট সহ তহবিল স্থানান্তর ফর্ম তৈরি করে:

<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post">
    <header>
        <h1>Fund Transfer</h1>
    </header>
    <div>
        <label for="amount">Amount (between $1-$5000):</label>
        <input type="number" name="amount" value="<?= $inputs['amount'] ?? '' ?>" id="amount" placeholder="Enter the transfered amount">
        <small><?= $errors['amount'] ?? '' ?></small>
    </div>

    <div>
        <label for="recipient_account">Recipient Account:</label>
        <input type="number" name="recipient_account" value="<?= $inputs['recipient_account'] ?? '' ?>" id="recipient_account" placeholder="Enter the recipient account">
        <small><?= $errors['recipient_account'] ?? '' ?></small>
    </div>

    <input type="hidden" name="token" value="<?= $_SESSION['token'] ?? '' ?>">
    <button type="submit">Transfer Now</button>
</form>

post.php

নিম্নলিখিত কোড টোকেন এবং ফর্ম ডেটা যাচাই করে:

<?php

$token = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);

if (!$token || $token !== $_SESSION['token']) {
    // show an error message
    echo '<p class="error">Error: invalid form submission</p>';
    // return 405 http status code
    header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed');
    exit;
}

// Validate amount
$amount = filter_input(INPUT_POST, 'amount', FILTER_SANITIZE_NUMBER_INT);
$inputs['amount'] = $amount;

if ($amount) {
    $amount = filter_var(
        $amount,
        FILTER_VALIDATE_INT,
        ['options' => ['min_range' => 1, 'max_range' => 5000]]
    );

    if (!$amount) {
        $errors['amount'] = 'Please enter a valid amount (from $1 to $5000)';
    }
} else {
    $errors['amount'] = 'Please enter the transfered amount.';
}

// validate account (simple)
$recipient_account = filter_input(INPUT_POST, 'recipient_account', FILTER_SANITIZE_NUMBER_INT);

$inputs['recipient_account'] = $recipient_account;

if ($recipient_account) {
    $recipient_account = filter_var($recipient_account, FILTER_VALIDATE_INT);

    if (!$recipient_account) {
        $errors['recipient_account'] = 'Please enter a valid recipient account';
    }
    // validate the recipient account against the database
    // ...
} else {
    $errors['recipient_account'] = 'Please enter the recipient account.';
}

কিভাবে post.php কাজ করে।

প্রথমে, INPUT_POST থেকে টোকেনটি স্যানিটাইজ করুন:

$token = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);

filter_input() ফাংশনটি শূন্য প্রদান করে যদি টোকেন জমা দেওয়া ডেটাতে অন্তর্ভুক্ত করা হয়। FILTER_SANITIZE_STRING ফিল্টারটি টোকেন ফিল্টার করতে ব্যর্থ হলে এটি মিথ্যা ফেরত দেয়।

দ্বিতীয়ত, $_SESSION ভেরিয়েবলে সংরক্ষিত একটি স্যানিটাইজড টোকেনের সাথে তুলনা করুন:

if (!$token || $token !== $_SESSION['token']) {
    // process error
}

যদি সেগুলি মেলে না, আমরা হেডার() ফাংশন ব্যবহার করে ক্লায়েন্টকে HTTP স্ট্যাটাস কোড 405 (পদ্ধতি অনুমোদিত নয়) ফেরত দিই এবং সঙ্গে সঙ্গে স্ক্রিপ্ট বন্ধ করে দিই।

header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed');

অবশিষ্ট কোড স্যানিটাইজ করে এবং পরিমাণ এবং প্রাপকের অ্যাকাউন্ট যাচাই করে। যদি কোন ত্রুটি না থাকে, আমরা একটি নিশ্চিতকরণ বার্তা দেখাই:

<?php if (!$errors) : ?>
	<section>
		<div class="circle">
			<div class="check"></div>
		</div>

		<h1 class="message">You've transfered</h1>
		<h2 class="amount">$<?= $amount ?></h2>

		<a href="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" rel="prev">Done</a>
	</section>
<?php endif ?>

সারসংক্ষেপ

  • CSRF আক্রমণগুলি ব্যবহারকারীদের সেই সাইটের বিরুদ্ধে একটি পদক্ষেপ চালাতে বাধ্য করে যেখানে তারা বর্তমানে লগ ইন করেছে৷
  • এককালীন টোকেন তৈরি করতে bin2hex(random_bytes(35)) ব্যবহার করুন।
  • CSRF আক্রমণ প্রতিরোধ করতে $_SESSION-এ সংরক্ষিত একটি দিয়ে জমা দেওয়া টোকেনটি পরীক্ষা করুন।

Leave a Comment

Share this Doc

PHP ক্রস-সাইট রিকোয়েস্ট ফ্রগেরই (CSRF)

Or copy link

CONTENTS

Subscribe

×
Cancel