কীভাবে আমি পিএইচপি-তে এসকিউএল ইঞ্জেকশন আটকাতে পারি?


2773

যদি কোনও এসকিউএল কোয়েরিতে কোনও পরিবর্তন ছাড়াই ব্যবহারকারীর ইনপুট sertedোকানো হয়, তবে অ্যাপ্লিকেশনটি এসকিউএল ইঞ্জেকশনের জন্য দুর্বল হয়ে পড়ে , যেমন নিম্নলিখিত উদাহরণটির মতো:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

এর কারণ ব্যবহারকারী এর মতো কিছু ইনপুট করতে পারে value'); DROP TABLE table;--এবং ক্যোয়ারিতে পরিণত হয়:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

এটি যাতে না ঘটে তার জন্য কী করা যেতে পারে?

উত্তর:


8953

প্রস্তুত বিবৃতি এবং প্যারামিটারাইজড কোয়েরি ব্যবহার করুন। এগুলি এসকিউএল স্টেটমেন্ট যা কোনও পরামিতি থেকে পৃথক করে ডেটাবেস সার্ভার দ্বারা পাঠানো এবং পার্স করা হয়। এইভাবে আক্রমণকারীটির পক্ষে দূষিত এসকিউএল ইনজেকশন করা অসম্ভব।

এটি অর্জনের জন্য আপনার কাছে মূলত দুটি বিকল্প রয়েছে:

  1. PDO ব্যবহার করে (কোনও সমর্থিত ডাটাবেস ড্রাইভারের জন্য):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    
    $stmt->execute([ 'name' => $name ]);
    
    foreach ($stmt as $row) {
        // Do something with $row
    }
  2. MySQLi (মাইএসকিউএল এর জন্য) ব্যবহার করে :

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
    $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        // Do something with $row
    }

আপনি যদি মাইএসকিউএল ব্যতীত অন্য কোনও ডাটাবেসে সংযোগ করছেন, তবে ড্রাইভার-নির্দিষ্ট দ্বিতীয় বিকল্প রয়েছে যা আপনি উল্লেখ করতে পারেন (উদাহরণস্বরূপ, pg_prepare()এবং pg_execute()পোস্টগ্র্রেএসকিউএল জন্য)। PDO সর্বজনীন বিকল্প।


সংযোগটি সঠিকভাবে স্থাপন করা হচ্ছে

নোট করুন যে PDOকোনও মাইএসকিউএল ডাটাবেস অ্যাক্সেস করতে ব্যবহার করার সময় আসল প্রস্তুত বিবৃতি ডিফল্টরূপে ব্যবহার হয় না । এটি ঠিক করতে আপনাকে প্রস্তুত বিবৃতিগুলির অনুকরণটি অক্ষম করতে হবে। PDO ব্যবহার করে সংযোগ তৈরির একটি উদাহরণ হ'ল:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'password');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

উপরের উদাহরণে ত্রুটি মোডটি কঠোরভাবে প্রয়োজনীয় নয়, তবে এটি যুক্ত করার পরামর্শ দেওয়া হচ্ছেFatal Errorকিছু ভুল হয়ে গেলে এইভাবে স্ক্রিপ্টটি থামবে না । এবং এটি বিকাশকারীকে catchকোনও ত্রুটি (গুলি) করার সুযোগ দেয় যা thrown হিসাবে রয়েছে PDOException

তবে যা বাধ্যতামূলক তা হ'ল প্রথম setAttribute()লাইন, যা পিডিওকে অনুকরণীয় প্রস্তুত বিবৃতি অক্ষম করতে এবং বাস্তব প্রস্তুত বিবৃতি ব্যবহার করতে বলে। এটি নিশ্চিত করে যে মাইএসকিউএল সার্ভারে প্রেরণ করার আগে পিএইচপি দ্বারা বিবৃতি এবং মানগুলি পার্স করা হয়নি (সম্ভাব্য আক্রমণকারীকে দূষিত এসকিউএল ইনজেক্ট করার সুযোগ না দেওয়া)।

যদিও আপনি charsetকনস্ট্রাক্টরের বিকল্পগুলিতে সেট করতে পারেন , পিএইচপি (5.3.6 এর আগে) এর পুরানো সংস্করণগুলি নীরবে ডিএসএন-তে চরসেট প্যারামিটার উপেক্ষা করেছে


ব্যাখ্যা

আপনি যে এসকিউএল বিবৃতিটি পাস করেছেন prepareতা পার্স এবং ডাটাবেস সার্ভার দ্বারা সংকলিত। প্যারামিটারগুলি নির্দিষ্ট করে ( উপরের উদাহরণের ?মতো একটি বা নামযুক্ত প্যারামিটার :name) আপনি ডাটাবেস ইঞ্জিনকে বলবেন যেখানে আপনি ফিল্টার করতে চান। তারপরে আপনি যখন কল করবেন তখন executeপ্রস্তুত বিবৃতিটি আপনার নির্দিষ্ট পরামিতি মানগুলির সাথে মিলিত হবে।

এখানে গুরুত্বপূর্ণ বিষয়টি হ'ল প্যারামিটার মানগুলি সংকলিত স্টেটমেন্টের সাথে সংযুক্ত করা হয়, কোনও এসকিউএল স্ট্রিং নয়। এসকিউএল ইঞ্জেকশনটি স্ক্রিপ্টটিকে দূষিত স্ট্রিংগুলি অন্তর্ভুক্ত করে যখন এটি ডাটাবেসে প্রেরণের জন্য এসকিউএল তৈরি করে তখন কাজ করে। সুতরাং প্যারামিটারগুলি থেকে পৃথক করে প্রকৃত এসকিউএল প্রেরণ করে, আপনি যা চাননি এমন কিছু দিয়ে শেষ হওয়ার ঝুঁকি সীমাবদ্ধ করুন।

প্রস্তুত বিবৃতি ব্যবহার করার সময় আপনি যে কোনও প্যারামিটারগুলি প্রেরণ করেন সেগুলি কেবল স্ট্রিং হিসাবে বিবেচিত হবে (যদিও ডাটাবেস ইঞ্জিনটি কিছু অপ্টিমাইজেশন করতে পারে সুতরাং অবশ্যই প্যারামিটারগুলি সংখ্যা হিসাবে শেষ হতে পারে)। উপরের উদাহরণে, যদি $nameভেরিয়েবলটি থাকে 'Sarah'; DELETE FROM employeesতবে ফলাফলটি কেবল স্ট্রিংয়ের জন্য অনুসন্ধান হতে পারে "'Sarah'; DELETE FROM employees"এবং আপনি খালি টেবিল দিয়ে শেষ করবেন না ।

প্রস্তুত বিবৃতি ব্যবহারের আরেকটি সুবিধা হ'ল যদি আপনি একই অধিবেশনটি একই অধিবেশনে বহুবার কার্যকর করেন তবে এটি কেবল একবার পার্স এবং সংকলিত হবে, আপনাকে কিছু গতি অর্জন করবে।

ওহ, এবং যেহেতু আপনি এটি কীভাবে সন্নিবেশ করানোর বিষয়ে জিজ্ঞাসা করেছিলেন তাই এখানে একটি উদাহরণ রয়েছে (পিডিও ব্যবহার করে):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute([ 'column' => $unsafeValue ]);

গতিশীল প্রশ্নের জন্য প্রস্তুত বিবৃতি ব্যবহার করা যেতে পারে?

আপনি এখনও ক্যোয়ারি প্যারামিটারগুলির জন্য প্রস্তুত বিবৃতিগুলি ব্যবহার করতে পারেন, ডায়নামিক ক্যোয়ারির কাঠামো নিজেই প্যারামাইট্রাইজ করা যায় না এবং নির্দিষ্ট কোয়েরি বৈশিষ্ট্যগুলিকে প্যারামিট্রাইজ করা যায় না।

এই নির্দিষ্ট পরিস্থিতির জন্য, সর্বোত্তম কাজ হ'ল একটি শ্বেতলিস্ট ফিল্টার ব্যবহার করা যা সম্ভাব্য মানগুলিকে সীমাবদ্ধ করে।

// Value whitelist
// $dir can only be 'DESC', otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}

86
কেবল যোগ করার কারণ আমি এটি অন্য কোথাও এটি দেখতে পাইনি, প্রতিরক্ষার আরেকটি লাইন হল একটি ওয়েব অ্যাপ্লিকেশন ফায়ারওয়াল (ডাব্লুএএফ) যা
স্কিল

37
এছাড়াও, mysql_query এর অফিশিয়াল ডকুমেন্টেশন কেবল একটি ক্যোয়ারী চালানোর অনুমতি দেয় তাই এর বাইরে অন্য কোনও কোয়েরি; উপেক্ষা করা হয়। এমনকি যদি এটি ইতিমধ্যে অবচয় করা হয় তবে পিএইচপি 5.5.0 এর অধীনে প্রচুর সিস্টেম রয়েছে এবং এটি এই ফাংশনটি ব্যবহার করতে পারে। php.net/manual/en/function.mysql-query.php
র্যান্ডাল ভ্যালেন্সিয়ানো

12
এটি একটি খারাপ অভ্যাস তবে সমস্যা সমাধানের পরে সমাধান: কেবল এসকিউএল ইঞ্জেকশনের জন্যই নয় তবে যে কোনও ধরণের ইনজেকশনগুলির জন্য (উদাহরণস্বরূপ F3 ফ্রেমওয়ার্ক v2-তে একটি ভিউ টেম্পলেট ইনজেকশন গর্ত ছিল) আপনার যদি প্রস্তুত একটি পুরাতন ওয়েবসাইট বা অ্যাপ্লিকেশন ভুগছে ইনজেকশন ত্রুটিগুলি থেকে, একটি সমাধান হ'ল বুটস্ট্র্যাপে পালানো মান সহ $ _POST এর মতো আপনার সুপারারগ্লোবাল পূর্বনির্ধারিত ভারগুলির মানগুলি পুনরায় সাইন করা। পিডিও দ্বারা, এখনও পালানো সম্ভব (আজকের ফ্রেমওয়ার্কগুলির জন্যও): সাবস্ট্রাস্ট ($ pdo-> উদ্ধৃতি ($আরটি, \ পিডিও :: PARAM_STR), 1, -1)
অ্যালিক্স

15
এই উত্তরে একটি প্রস্তুত বিবৃতি কী তা ব্যাখ্যাটির অভাব রয়েছে - একটি জিনিস - আপনি যদি আপনার অনুরোধের সময় প্রচুর প্রস্তুত বিবৃতি ব্যবহার করেন এবং কখনও কখনও এটি 10x পারফরম্যান্স হিট হয়ে থাকে তবে এটি একটি পারফরম্যান্স হিট। ভাল ক্ষেত্রে প্যারামিটার বন্ধন বন্ধ সঙ্গে PDO ব্যবহার করা হবে, কিন্তু বিবৃতি প্রস্তুতি বন্ধ।
ডোনিস

6
ব্যবহার PDO ভাল, যদি আপনি সরাসরি প্রশ্নের জবাবে ড ব্যবহার করছেন নিশ্চিত করুন যে আপনি ব্যবহার করতে mysqli :: escape_string
Kassem Itani

1652

অসম্মতিযুক্ত সতর্কতা: এই উত্তরের নমুনা কোড (প্রশ্নের প্রশ্নের নমুনা কোডের মতো) পিএইচপি-র MySQLএক্সটেনশন ব্যবহার করে , যা পিএইচপি 5.5.0 এ অবমূল্যায়ন করা হয়েছিল এবং পুরোপুরি পিএইচপি 7.0.0 এ অপসারণ করা হয়েছিল।

সুরক্ষা সতর্কতা : এই উত্তরটি সুরক্ষার সেরা অনুশীলনের সাথে সামঞ্জস্যপূর্ণ নয়। এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য এসকেপিং অপর্যাপ্ত , পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করুন। আপনার নিজের ঝুঁকিতে নীচে বর্ণিত কৌশলটি ব্যবহার করুন। (এছাড়াও, mysql_real_escape_string()পিএইচপি 7 এ অপসারণ করা হয়েছিল)

আপনি যদি পিএইচপি-র সাম্প্রতিক সংস্করণ ব্যবহার করছেন তবে mysql_real_escape_stringনীচে বর্ণিত বিকল্পটি আর পাওয়া যাবে না (যদিও mysqli::escape_stringএটি একটি আধুনিক সমতুল্য)। এই দিনগুলিতে mysql_real_escape_stringকেবল পিএইচপি-র একটি পুরানো সংস্করণে লিগ্যাসি কোডের বিকল্পটি বোধগম্য হবে।


আপনার দুটি বিকল্প রয়েছে - আপনার বিশেষ অক্ষরগুলি থেকে বেরিয়ে আসা unsafe_variableবা প্যারামিটারাইজড কোয়েরি ব্যবহার করে using উভয়ই আপনাকে এসকিউএল ইঞ্জেকশন থেকে রক্ষা করবে। প্যারামিটারাইজড ক্যোয়ারিকে আরও ভাল অনুশীলন হিসাবে বিবেচনা করা হয় তবে আপনি এটি ব্যবহারের আগে পিএইচপি-র একটি নতুন মাইএসকিউএল এক্সটেনশনে পরিবর্তন প্রয়োজন।

আমরা প্রথমে কম থাকা প্রভাবের স্ট্রিংটি কভার করব।

//Connect

$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

//Disconnect

এছাড়াও দেখুন, mysql_real_escape_stringফাংশন বিশদ ।

স্থিতিমাপ ক্যোয়ারী ব্যবহার করতে, আপনাকে ব্যবহার করতে হবে MySQLi বদলে মাইএসকিউএল ফাংশন। আপনার উদাহরণটি নতুন করে লিখতে আমাদের নীচের মতো কিছু দরকার।

<?php
    $mysqli = new mysqli("server", "username", "password", "database_name");

    // TODO - Check that connection was successful.

    $unsafe_variable = $_POST["user-input"];

    $stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");

    // TODO check that $stmt creation succeeded

    // "s" means the database expects a string
    $stmt->bind_param("s", $unsafe_variable);

    $stmt->execute();

    $stmt->close();

    $mysqli->close();
?>

আপনি এখানে পড়তে চান মূল ফাংশন হবে mysqli::prepare

এছাড়াও, অন্যরা যেমন পরামর্শ দিয়েছে, পিডিওর মতো কিছু দিয়ে বিমূর্ততার স্তর বাড়ানো আপনার পক্ষে দরকারী / সহজ হতে পারে ।

দয়া করে মনে রাখবেন আপনি যে কেসটি সম্পর্কে জিজ্ঞাসা করেছেন তা মোটামুটি সহজ এবং আরও জটিল ক্ষেত্রে আরও জটিল পদ্ধতির প্রয়োজন হতে পারে। নির্দিষ্টভাবে:

  • আপনি যদি ব্যবহারকারী ইনপুট এর উপর ভিত্তি করে এসকিউএল এর কাঠামো পরিবর্তন করতে চান, প্যারামিটারাইজড কোয়েরি সাহায্য করবে না, এবং প্রয়োজনীয় পলায়ন দ্বারা আবরণ করা হবে না mysql_real_escape_string। এই ধরণের ক্ষেত্রে, কেবলমাত্র 'নিরাপদ' মানগুলিই মঞ্জুরিপ্রাপ্ত তা নিশ্চিত করার জন্য কোনও শ্বেতলিস্টের মাধ্যমে ব্যবহারকারীর ইনপুটটি দেওয়া আপনার পক্ষে ভাল।
  • আপনি যদি কোনও অবস্থার মধ্যে ব্যবহারকারী ইনপুট থেকে পূর্ণসংখ্যার ব্যবহার করেন এবং এই mysql_real_escape_stringপদ্ধতিটি গ্রহণ করেন , তবে নীচের মন্তব্যে আপনি পলিনমিয়াল দ্বারা বর্ণিত সমস্যা থেকে ভুগবেন । এই কেসটি জটিলতর কারণ পূর্ণসংখ্যাগুলি কোট দ্বারা ঘেরাও হবে না, সুতরাং আপনি ব্যবহারকারীর ইনপুটটিতে কেবলমাত্র সংখ্যা রয়েছে তা প্রমাণ করে আপনি এটি মোকাবেলা করতে পারেন।
  • সম্ভবত অন্যান্য ক্ষেত্রেও আমি সচেতন নই। আপনি পেতে পারে এই আরও সূক্ষ্ম সমস্যার আপনি সম্মুখীন করতে কিছু একটি দরকারী সম্পদ।

1
ব্যবহার mysql_real_escape_stringকরা যথেষ্ট নাকি আমিও প্যারামিটারাইজড ব্যবহার করতে পারি?
পেরিম্যান এফ।

5
@peimanF। এমনকি স্থানীয় প্রকল্পেও প্যারামিট্রাইজড কোয়েরিগুলি ব্যবহার করার একটি ভাল অনুশীলন রাখুন। প্যারামিট্রাইজড কোয়েরিগুলির সাথে আপনি গ্যারান্টিযুক্ত যে এসকিউএল ইঞ্জেকশন থাকবে না। তবে মনে রাখবেন বোগাস পুনরুদ্ধার (যেমন এক্সএসএস ইনজেকশন, যেমন কোনও পাঠ্যে HTML কোড লাগানো) এড়াতে আপনার ডেটা স্যানিটাইজ করা উচিতhtmlentities
গফালাইট

2
@peimanF। প্যারামিট্রাইজড কোয়েরিগুলি এবং মানগুলিকে আবদ্ধ করার জন্য ভাল অনুশীলন, তবে আসল পালানোর স্ট্রিং আপাতত ভাল
রিচার্ড

আমি mysql_real_escape_string()সম্পূর্ণতার জন্য অন্তর্ভুক্তিটি বুঝতে পারি , তবে প্রথমে সবচেয়ে বেশি ত্রুটি-প্রবণ পদ্ধতির তালিকা দেওয়ার ভক্ত নই। পাঠক সম্ভবত প্রথম উদাহরণটি ধরুন। ভাল কথা এটি এখন
অবচয় করা

1
@ স্টেনশ্যাচট - সমস্ত mysql_*ক্রিয়াকলাপ হ্রাস করা হয়েছে। তারা অনুরূপ mysqli_* ফাংশন দ্বারা প্রতিস্থাপিত হয়েছিল , যেমন mysqli_real_escape_string
রিক জেমস

1072

এখানে প্রতিটি উত্তর সমস্যার একমাত্র অংশ জুড়ে। প্রকৃতপক্ষে, এখানে চারটি পৃথক ক্যোয়ারী অংশ রয়েছে যা আমরা এসকিউএলকে গতিশীলভাবে যুক্ত করতে পারি: -

  • একটি স্ট্রিং
  • একটি সংখ্যা
  • একটি সনাক্তকারী
  • একটি সিনট্যাক্স কীওয়ার্ড

এবং প্রস্তুত বিবৃতিগুলির মধ্যে কেবল দুটিই রয়েছে।

তবে কখনও কখনও আমাদের ক্যোয়ারীটিকে আরও গতিশীল করতে হয়, অপারেটর বা সনাক্তকারীও যুক্ত করতে হয়। সুতরাং, আমাদের বিভিন্ন সুরক্ষা কৌশল প্রয়োজন হবে।

সাধারণভাবে, এই জাতীয় সুরক্ষা পদ্ধতি হোয়াইটলিস্টিংয়ের উপর ভিত্তি করে ।

এই ক্ষেত্রে, প্রতিটি গতিশীল প্যারামিটার আপনার স্ক্রিপ্টে হার্ডকোড করা উচিত এবং সেট থেকে চয়ন করা উচিত। উদাহরণস্বরূপ, গতিশীল ক্রম করতে:

$orders  = array("name", "price", "qty"); // Field names
$key = array_search($_GET['sort'], $orders)); // if we have such a name
$orderby = $orders[$key]; // If not, first one will be set automatically. 
$query = "SELECT * FROM `table` ORDER BY $orderby"; // Value is safe

প্রক্রিয়াটি সহজ করার জন্য আমি একটি স্বেচ্ছাসেবীর সহায়ক ফাংশন লিখেছি যা সমস্ত কাজ এক লাইনে করে:

$orderby = white_list($_GET['orderby'], "name", ["name","price","qty"], "Invalid field name");
$query  = "SELECT * FROM `table` ORDER BY `$orderby`"; // sound and safe

সনাক্তকারীদের সুরক্ষিত করার অন্য একটি উপায় রয়েছে - পালানো তবে আমি বরং আরও দৃ rob় এবং স্পষ্ট পদ্ধতির হিসাবে শ্বেত তালিকাতে আঁকড়ে থাকি। তবুও আপনার যতক্ষণ অবধি কোনও শনাক্তকারীর উদ্ধৃতি রয়েছে, আপনি এটিকে নিরাপদ করতে উদ্ধৃতি চরিত্রটি এড়াতে পারবেন। উদাহরণস্বরূপ, মাইএসকিএল-র জন্য ডিফল্টরূপে এড়াতে আপনাকে উদ্ধৃতি চরিত্রটি দ্বিগুণ করতে হবে । অন্যান্য অন্যান্য ডিবিএমএসের জন্য পালানোর নিয়ম আলাদা হবে।

তা সত্ত্বেও, এসকিউএল সিনট্যাক্স কীওয়ার্ড সঙ্গে একটি বিষয় (যেমন হয় AND, DESCএবং এই ধরনের), কিন্তু সাদা তালিকা এই ক্ষেত্রে শুধুমাত্র পদ্ধতির বলে মনে হয়।

সুতরাং, একটি সাধারণ সুপারিশ হিসাবে চিহ্নিত করা যেতে পারে

  • কোনও ভেরিয়েবল যা কোনও এসকিউএল ডেটা আক্ষরিক প্রতিনিধিত্ব করে, (বা এটিকে সহজভাবে বলতে - একটি এসকিউএল স্ট্রিং, বা একটি সংখ্যা) অবশ্যই প্রস্তুত বিবৃতি দিয়ে যুক্ত করতে হবে। কোন আশা নাই.
  • কোনও এসকিউএল কীওয়ার্ড, একটি টেবিল বা ক্ষেত্রের নাম, বা একটি অপারেটরের মতো অন্য যে কোনও প্রশ্নের অংশ অবশ্যই একটি সাদা তালিকার মাধ্যমে ফিল্টার করতে হবে।

হালনাগাদ

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

উদাহরণস্বরূপ, (1) এখনও (2) এখনও (3) অনেক (4) উত্তর (5) রয়েছে, দ্বিতীয় সর্বাধিক উত্সাহিত উত্তর সহ আপনাকে ম্যানুয়াল স্ট্রিং পলায়নের পরামর্শ দেয় - একটি পুরানো পদ্ধতির যা অনিরাপদ বলে প্রমাণিত।

অথবা এর চেয়ে আরও ভাল উত্তর রয়েছে যা স্ট্রিং ফর্ম্যাটিংয়ের কেবলমাত্র অন্য একটি পদ্ধতির পরামর্শ দেয় এবং এটি চূড়ান্ত প্যানাসিয়া হিসাবে গর্বিত করে। অবশ্যই, এটি না। এই পদ্ধতিটি নিয়মিত স্ট্রিং ফর্ম্যাটিংয়ের চেয়ে ভাল নয়, তবুও এটি তার সমস্ত ত্রুটিগুলি রাখে: এটি কেবল স্ট্রিংগুলিতে প্রযোজ্য এবং অন্য কোনও ম্যানুয়াল ফরম্যাটের মতো এটিও মূলত alচ্ছিক, বাধ্যতামূলক-পরিমাপ, কোনও ধরণের মানুষের ত্রুটির প্রবণ।

আমি মনে করি যে, ওডাব্লুএসএপি বা পিএইচপি ম্যানুয়াল যেমন যেমন কর্তৃপক্ষ দ্বারা সমর্থিত একটি খুব পুরানো কুসংস্কারের কারণে , যা এসকিউএল ইনজেকশন থেকে "পালাতে" এবং সুরক্ষার মধ্যে সমতা ঘোষণা করে।

যুগে যুগে পিএইচপি ম্যানুয়াল যা বলেছিল তা নির্বিশেষে, *_escape_stringকোনও উপায়ে ডেটা নিরাপদ করে না এবং এর উদ্দেশ্য কখনও হয়নি। স্ট্রিং ব্যতীত অন্য কোনও এসকিউএল অংশের জন্য অকেজো হওয়া ছাড়াও ম্যানুয়াল পলায়ন ভুল, কারণ এটি স্বয়ংক্রিয়র বিপরীতে ম্যানুয়াল।

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

সুতরাং, "পলায়ন" যাই হোক না কেন এর বিপরীতে প্রস্তুত বিবৃতিগুলি এমন একটি পরিমাপ যা সত্যই এসকিউএল ইঞ্জেকশন থেকে রক্ষা করে (যখন প্রযোজ্য)।


848

আমি প্যারামিটারাইজড এসকিউএল কোয়েরিগুলি চালানোর জন্য পিডিও (পিএইচপি ডেটা অবজেক্টস) ব্যবহার করার পরামর্শ দেব ।

এটি কেবল এসকিউএল ইঞ্জেকশন থেকে রক্ষা করে না, তবে এটি অনুসন্ধানগুলির গতি বাড়ায়।

আর বদলে PDO ব্যবহার করে mysql_, mysqli_এবং pgsql_ফাংশন, আপনি আপনার আবেদন একটু, ডাটাবেজ থেকে আরো আনমনা বিরল সংঘটন আপনি সুইচ ডাটাবেসের প্রদানকারীর আছে ভুলবেন না।


619

ব্যবহার PDOএবং প্রস্তুত ক্যোয়ারী।

( $connএকটি PDOবস্তু)

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();

549

আপনি দেখতে পাচ্ছেন, লোকেরা আপনাকে সর্বাধিক প্রস্তুতির বিবৃতি ব্যবহার করার পরামর্শ দেয়। এটি ভুল নয়, তবে যখন আপনার ক্যোয়ারী প্রতি প্রক্রিয়া অনুযায়ী একবার কার্যকর করা হয় , তখন সামান্য পারফরম্যান্স পেনাল্টি হবে।

আমি এই সমস্যার মুখোমুখি হয়েছি, তবে আমি মনে করি যে আমি এটিকে খুব পরিশীলিতভাবে সমাধান করেছি - হ্যাকাররা যেভাবে উদ্ধৃতি ব্যবহার এড়াতে ব্যবহার করে। আমি অনুকরণীয় প্রস্তুত বিবৃতিগুলির সাথে এটি ব্যবহার করেছি। আমি এটি সমস্ত ধরণের এসকিউএল ইঞ্জেকশন আক্রমণগুলি প্রতিরোধ করতে ব্যবহার করি ।

আমার পদ্ধতি:

  • আপনি যদি ইনপুটটি পূর্ণসংখ্যা হিসাবে প্রত্যাশা করেন তবে এটি সত্যই পূর্ণসংখ্যা নিশ্চিত করুন । পিএইচপি এর মতো ভেরিয়েবল-টাইপ ভাষায় এটি খুব গুরুত্বপূর্ণ this আপনি উদাহরণস্বরূপ এই খুব সহজ তবে শক্তিশালী সমাধানটি ব্যবহার করতে পারেন:sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);

  • আপনি যদি পূর্ণসংখ্য হেক্স থেকে অন্য কিছু আশা করেন । আপনি যদি এটি হেক্স করেন তবে আপনি সমস্ত ইনপুট পুরোপুরি পালাতে পারবেন। সি / সি ++ তে একটি ফাংশন বলা হয় mysql_hex_string(), পিএইচপি-তে আপনি ব্যবহার করতে পারেন bin2hex()

    ভাববেন না যে পালানো স্ট্রিংয়ের মূল দৈর্ঘ্যের 2x আকার থাকবে কারণ আপনি ব্যবহার করলেও mysql_real_escape_stringপিএইচপিকে একই ক্ষমতা বরাদ্দ করতে হবে ((2*input_length)+1), যা একই।

  • আপনি বাইনারি ডেটা স্থানান্তর করার সময় এই হেক্স পদ্ধতিটি প্রায়শই ব্যবহৃত হয়, তবে এসকিউএল ইঞ্জেকশন আক্রমণ রোধ করতে সমস্ত ডেটাতে এটি ব্যবহার না করার কোনও কারণ আমি দেখতে পাচ্ছি না। নোট করুন যে আপনাকে এর পরিবর্তে 0xমাইএসকিউএল ফাংশন সহ ডেটা প্রিপেন্ড করতে হবে বা ব্যবহার করতে UNHEXহবে।

সুতরাং, উদাহরণস্বরূপ, ক্যোয়ারী:

SELECT password FROM users WHERE name = 'root'

হয়ে যাবে:

SELECT password FROM users WHERE name = 0x726f6f74

অথবা

SELECT password FROM users WHERE name = UNHEX('726f6f74')

হেক্স হ'ল নিখুঁত পালানো। ইনজেকশন দেওয়ার কোনও উপায় নেই।

ইউএনএইচএক্স ফাংশন এবং 0x উপসর্গের মধ্যে পার্থক্য

মন্তব্যে কিছু আলোচনা ছিল, তাই আমি অবশেষে এটি পরিষ্কার করতে চাই। এই দুটি পদ্ধতির খুব মিল, তবে কিছু উপায়ে এগুলি কিছুটা আলাদা different

** 0x ** উপসর্গটি কেবল চর, বর্ণচর, পাঠ্য, ব্লক, বাইনারি ইত্যাদির মতো ডেটা কলামগুলির জন্য ব্যবহার করা যেতে পারে ।
এছাড়াও, আপনি যদি খালি স্ট্রিং toোকাতে চলেছেন তবে এর ব্যবহারটি কিছুটা জটিল। আপনাকে এটি সম্পূর্ণরূপে প্রতিস্থাপন ''করতে হবে, বা আপনি একটি ত্রুটি পাবেন।

ইউএনএইচএক্স () যে কোনও কলামে কাজ করে ; খালি স্ট্রিং সম্পর্কে আপনাকে চিন্তা করতে হবে না।


হেক্স পদ্ধতিগুলি প্রায়শই আক্রমণ হিসাবে ব্যবহৃত হয়

নোট করুন যে এই হেক্স পদ্ধতিটি প্রায়শই এসকিউএল ইনজেকশন আক্রমণ হিসাবে ব্যবহৃত হয় যেখানে পূর্ণসংখ্যা কেবল স্ট্রিংয়ের মতো থাকে এবং ঠিক তার সাথে পালিয়ে যায় mysql_real_escape_string। তাহলে আপনি উদ্ধৃতি ব্যবহার এড়াতে পারেন।

উদাহরণস্বরূপ, আপনি যদি এই জাতীয় কিছু করেন:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

একটি আক্রমণ আপনাকে খুব সহজেই ইনজেক্ট করতে পারে । আপনার স্ক্রিপ্ট থেকে ফিরে আসা ইনজেকশন কোডটি বিবেচনা করুন:

নির্বাচন করুন ... WHERE id = -1 ইউনিয়ন তথ্য_সেমিমা. টেবিলগুলি থেকে সমস্ত নির্বাচন করুন টেবিলের নাম

এবং এখন কেবল টেবিলের কাঠামোটি বের করুন:

নির্বাচন করুন ... যেখানে আইডি = -1 ইউনিয়ন তথ্য_সেমিমা কলাম থেকে সমস্ত নির্বাচন করুন কলাম_নাম যেখানে টেবিলের নাম = 0x61727469636c65

এবং তারপরে যা কিছু ডেটা চান তা নির্বাচন করুন। ভাল না?

তবে যদি কোনও ইনজেকশনযোগ্য সাইটের কোডার এটি হেক্স করে তোলে তবে কোনও ইনজেকশন সম্ভব হবে না কারণ ক্যোয়ারীটি এমন দেখাচ্ছে: SELECT ... WHERE id = UNHEX('2d312075...3635')


6
@ সুমিতগুপ্ত হ্যাঁ, আপনি করেছেন। মাইএসকিউএল +কিন্তু এর সাথে সামঞ্জস্য করে না CONCAT। এবং পারফরম্যান্সের জন্য: আমি মনে করি না এটি কার্য সম্পাদনকে প্রভাবিত করে কারণ মাইএসকিউএল ডেটা বিশ্লেষণ করতে হবে এবং উত্সটি স্ট্রিং বা হেক্স
কিনা তা বিবেচ্য নয়

11
@ ইয়ারকমনসেন্স আপনি ধারণাটি বুঝতে পারবেন না ... আপনি যদি মাইএসকিএল-তে স্ট্রিং রাখতে চান তবে আপনি এটিকে উদ্ধৃতি দিতে পারেন 'root'বা আপনি 0x726f6f74যদি একটি নম্বর চান এবং স্ট্রিং হিসাবে প্রেরণ করেন তবে আপনি সম্ভবত চিয়ার নয় '42' লিখবেন ) ... 0x34320x42
হেক্সে

7
@ আপনার কমোনসেন্সে আমার বলার কিছু নেই ... কেবলমাত্র ... আপনি যদি এখনও সংখ্যা সংক্রান্ত ক্ষেত্রগুলিতে হেক্স চেষ্টা করতে চান তবে দ্বিতীয় মন্তব্য দেখুন। আমি আপনার সাথে বাজি ধরলাম যে এটি কার্যকর হবে।
জাফি

2
উত্তরে পরিষ্কারভাবে বলা হয়েছে যে এটি পূর্ণসংখ্যার মানগুলির সাথে সেভাবে কাজ করবে না, কারণ দ্বি 2 শেেক্স উত্তীর্ণিত মানকে একটি স্ট্রিংয়ে রূপান্তর করে (এবং এভাবে বিন 2hex (0) 0x30, এবং 0x03 নয়) - সম্ভবত এটিই সেই অংশ যা আপনাকে বিভ্রান্ত করে । যদি আপনি এটি অনুসরণ করেন তবে এটি নিখুঁতভাবে কাজ করে (কমপক্ষে আমার সাইটে, ডেবিয়ান মেশিনে 4 টি বিভিন্ন মাইএসকিএল সংস্করণ, 5.1.x থেকে 5.6.x এর সাথে পরীক্ষিত)। সর্বোপরি, হেক্সাডেসিমাল কেবল উপস্থাপনের উপায়, মান নয়;)
গ্রিফিন

5
পছন্দ করেছেন আপনি 0x এবং কনক্যাট ব্যবহার করতে পারবেন না কারণ স্ট্রিংটি ফাঁকা থাকলে আপনি একটি ত্রুটির সাথে শেষ হয়ে যাবেন। আপনি যদি আপনার ক্যোয়ারির সরল বিকল্প চান তবে এটি চেষ্টা করে দেখুনSELECT title FROM article WHERE id = UNHEX(' . bin2hex($_GET["id"]) . ')
জাফি

499

অসম্মতিযুক্ত সতর্কতা: এই উত্তরের নমুনা কোড (প্রশ্নের প্রশ্নের নমুনা কোডের মতো) পিএইচপি-র MySQLএক্সটেনশন ব্যবহার করে , যা পিএইচপি 5.5.0 এ অবমূল্যায়ন করা হয়েছিল এবং পুরোপুরি পিএইচপি 7.0.0 এ অপসারণ করা হয়েছিল।

সুরক্ষা সতর্কতা : এই উত্তরটি সুরক্ষার সেরা অনুশীলনের সাথে সামঞ্জস্যপূর্ণ নয়। এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য এসকেপিং অপর্যাপ্ত , পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করুন। আপনার নিজের ঝুঁকিতে নীচে বর্ণিত কৌশলটি ব্যবহার করুন। (এছাড়াও, mysql_real_escape_string()পিএইচপি 7 এ অপসারণ করা হয়েছিল)

গুরুত্বপূর্ণ

এসকিউএল ইঞ্জেকশন প্রতিরোধের সর্বোত্তম উপায় হ'ল গ্রহণযোগ্য উত্তরটি যেমন দেখায় তেমন পালানোর পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করা ।

আউরা.এসকিএল এবং ইজিডিবি এর মতো লাইব্রেরি রয়েছে যা বিকাশকারীদের প্রস্তুত বিবৃতিগুলি আরও সহজভাবে ব্যবহার করতে দেয়। এসকিউএল ইনজেকশন বন্ধ করতে প্রস্তুত বিবৃতি কেন আরও ভাল তা সম্পর্কে আরও জানতে , এই mysql_real_escape_string()বাইপাসটি এবং ওয়ার্ডপ্রেসে সম্প্রতি ইউনিকোড এসকিউএল ইঞ্জেকশন দুর্বলতাগুলি পড়ুন

ইনজেকশন প্রতিরোধ - mysql_real_escape_string ()

এই আক্রমণগুলি রোধ করতে পিএইচপি-র একটি বিশেষভাবে তৈরি ফাংশন রয়েছে। আপনাকে যা করতে হবে তা হ'ল কোনও ফাংশনের মাউথ ব্যবহার করা mysql_real_escape_string

mysql_real_escape_stringএকটি মাইএসকিউএল ক্যোয়ারীতে ব্যবহৃত হতে চলেছে এমন স্ট্রিং নেয় এবং নিরাপদভাবে পালিয়ে যাওয়া সমস্ত এসকিউএল ইঞ্জেকশন প্রচেষ্টা সহ একই স্ট্রিংটি ফেরত দেয়। মূলত, এটি সেই সমস্যাযুক্ত উক্তিগুলি (') প্রতিস্থাপন করবে যে কোনও ব্যবহারকারী কোনও মাইএসকিউএল-নিরাপদ বিকল্প, একটি পালানো উদ্ধৃতি \' দিয়ে প্রবেশ করতে পারে।

দ্রষ্টব্য: এই ফাংশনটি ব্যবহার করার জন্য আপনাকে অবশ্যই ডাটাবেসের সাথে সংযুক্ত থাকতে হবে!

// মাইএসকিউএলে কানেক্ট করুন

$name_bad = "' OR 1'"; 

$name_bad = mysql_real_escape_string($name_bad);

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: <br />" . $query_bad . "<br />";


$name_evil = "'; DELETE FROM customers WHERE 1 or username = '"; 

$name_evil = mysql_real_escape_string($name_evil);

$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
echo "Escaped Evil Injection: <br />" . $query_evil;

আপনি মাইএসকিউএল - এসকিউএল ইনজেকশন প্রতিরোধে আরও বিশদ জানতে পারেন ।


30
লিগ্যাসি মাইএসকিএল এক্সটেনশনে আপনি এটি করতে পারেন সেরা। নতুন কোডের জন্য, আপনাকে মাইএসকিলি বা পিডিওতে স্যুইচ করার পরামর্শ দেওয়া হচ্ছে।
vlvaro González

7
আমি এই 'এই আক্রমণগুলি রোধ করার জন্য একটি বিশেষভাবে তৈরি ফাংশন' এর সাথে একমত নই। আমি মনে করি যে mysql_real_escape_stringউদ্দেশ্যটি প্রতিটি ইনপুট ডেটা-স্ট্রিংয়ের জন্য সঠিক এসকিউএল কোয়েরি তৈরি করতে দেয়। প্রতিরোধ স্কুয়েল-ইনজেকশন হ'ল এই ফাংশনটির পার্শ্ব-প্রতিক্রিয়া।
সেক্টাস

4
আপনি সঠিক ইনপুট ডেটা-স্ট্রিং লিখতে ফাংশন ব্যবহার করবেন না। আপনি কেবল সঠিকগুলি লিখুন যা পালানোর দরকার নেই বা ইতিমধ্যে পালিয়ে গেছে। mysql_real_escape_string () আপনার উদ্দেশ্য বিবেচনায় রেখে ডিজাইন করা হয়েছে, তবে এর একমাত্র মান ইঞ্জেকশন প্রতিরোধ করা।
নাজকা

17
সতর্কবার্তা! mysql_real_escape_string() অচল নয়
উদয়পাল

9
mysql_real_escape_stringএখন হ্রাস করা হয়েছে, সুতরাং এটি আর একটি কার্যকর বিকল্প নয়। ভবিষ্যতে এটি পিএইচপি থেকে সরানো হবে। পিএইচপি বা মাইএসকিউএল লোকেরা যা প্রস্তাব দেয় সেদিকে সরিয়ে নেওয়া সেরা।
jww

461

আপনি এই জাতীয় কিছু করতে পারেন:

$safe_variable = mysqli_real_escape_string($_POST["user-input"], $dbConnection);
mysqli_query($dbConnection, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

এটি প্রতিটি সমস্যার সমাধান করবে না, তবে এটি একটি খুব ভাল পাথর পাথর। আমি সুস্পষ্ট আইটেমগুলি বাদ দিয়েছি যেমন ভেরিয়েবলের অস্তিত্ব, ফর্ম্যাট (সংখ্যা, অক্ষর, ইত্যাদি) পরীক্ষা করা।


28
আমি তোমার উদাহরণ এবং এটি এর me.Could জন্য কাজ জরিমানা চেষ্টা করেছি তোমাদের মাঝে পরিস্কার "এই যে সমস্যা সমাধান করতে হবে"
চিনুক

14
আপনি যদি স্ট্রিংটি উদ্ধৃত না করেন তবে এটি এখনও ইনজেক্টেবল। $q = "SELECT col FROM tbl WHERE x = $safe_var";উদাহরণস্বরূপ নিন । উদ্ধৃতি না থাকার কারণে এই ক্ষেত্রে কাজ $safe_varকরতে সেট করা 1 UNION SELECT password FROM users। এছাড়া ব্যবহার ক্যোয়ারী মধ্যে স্ট্রিং উদ্বুদ্ধ করতে সম্ভব CONCATএবং CHR
বহুপদী

4
@ পলিনোমিয়াল সম্পূর্ণরূপে সঠিক, তবে আমি এটিকে কেবল ভুল ব্যবহার হিসাবে দেখছি। যতক্ষণ আপনি এটি সঠিকভাবে ব্যবহার করবেন ততক্ষণ তা অবশ্যই কাজ করবে।
glglgl

22
সতর্কবার্তা! mysql_real_escape_string() অচল নয়
উদয়পাল

8
mysql_real_escape_stringএখন হ্রাস করা হয়েছে, সুতরাং এটি আর একটি কার্যকর বিকল্প নয়। ভবিষ্যতে এটি পিএইচপি থেকে সরানো হবে। পিএইচপি বা মাইএসকিউএল লোকেরা যা প্রস্তাব দেয় সেদিকে সরিয়ে নেওয়া সেরা।
jww

380

আপনি যা ব্যবহার করে শেষ করেন না কেন, নিশ্চিত হয়ে নিন যে আপনার ইনপুটটি ইতিমধ্যে magic_quotesবা অন্য কোনও ভাল অর্থের আবর্জনা দ্বারা ম্যাঙ্গেল করা হয়নি এবং যদি প্রয়োজন হয় তবে এটিকে চালিত করুন stripslashesবা এটি স্যানিটাইজ করার জন্য যা কিছু করুন।


11
প্রকৃতপক্ষে; ম্যাজিক_কোটিস নিয়ে চলমান দুর্বল অনুশীলনকে উত্সাহ দেয়। যাইহোক, কখনও কখনও আপনি পরিবেশটি সর্বদা সেই স্তরে নিয়ন্ত্রণ করতে পারবেন না - হয় আপনার সার্ভার পরিচালনা করার অ্যাক্সেস নেই, বা আপনার অ্যাপ্লিকেশনটির এমন অ্যাপ্লিকেশনগুলির সাথে সহাবস্থান করতে হবে যা (শিথিল) এই ধরনের কনফিগারেশনের উপর নির্ভর করে। এই কারণগুলির জন্য, পোর্টেবল অ্যাপ্লিকেশনগুলি লিখতে ভাল - যদিও আপনি স্থাপনার পরিবেশ নিয়ন্ত্রণ করেন তবে স্পষ্টতই প্রচেষ্টাটি নষ্ট হয়, উদাহরণস্বরূপ কারণ এটি কোনও অভ্যন্তরীণ অ্যাপ্লিকেশন, বা কেবল আপনার নির্দিষ্ট পরিবেশে ব্যবহৃত হতে চলেছে।
রব

24
পিএইচপি ৫.৪ অনুসারে, 'ম্যাজিক কোটস' নামে পরিচিত জঘন্য কাজটি মারা গেছে । এবং খারাপ জঞ্জাল ভাল riddance।
ব্রায়ানএইচ

363

অসম্মতিযুক্ত সতর্কতা: এই উত্তরের নমুনা কোড (প্রশ্নের প্রশ্নের নমুনা কোডের মতো) পিএইচপি-র MySQLএক্সটেনশন ব্যবহার করে , যা পিএইচপি 5.5.0 এ অবমূল্যায়ন করা হয়েছিল এবং পুরোপুরি পিএইচপি 7.0.0 এ অপসারণ করা হয়েছিল।

সুরক্ষা সতর্কতা : এই উত্তরটি সুরক্ষার সেরা অনুশীলনের সাথে সামঞ্জস্যপূর্ণ নয়। এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য এসকেপিং অপর্যাপ্ত , পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করুন। আপনার নিজের ঝুঁকিতে নীচে বর্ণিত কৌশলটি ব্যবহার করুন। (এছাড়াও, mysql_real_escape_string()পিএইচপি 7 এ অপসারণ করা হয়েছিল)

প্যারামিটারাইজড ক্যোয়ারী এবং ইনপুট বৈধতা যাবার উপায়। অনেকগুলি পরিস্থিতি রয়েছে যার অধীনে এসকিউএল ইঞ্জেকশনটি mysql_real_escape_string()ব্যবহার করা হলেও ঘটতে পারে ।

এই উদাহরণগুলি এসকিউএল ইঞ্জেকশনের পক্ষে ঝুঁকিপূর্ণ:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
RunQuery("SELECT userid, username FROM sql_injection_test LIMIT $offset, 10");

অথবা

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
RunQuery("SELECT userid, username FROM sql_injection_test ORDER BY `$order`");

উভয় ক্ষেত্রেই, আপনি 'এনক্যাপসুলেশন সুরক্ষার জন্য ব্যবহার করতে পারবেন না ।

উত্স : অপ্রত্যাশিত এসকিউএল ইঞ্জেকশন (যখন পালানো যথেষ্ট নয়)


2
আপনি এসকিউএল ইঞ্জেকশনটিকে আটকাতে পারবেন যদি আপনি কোনও ইনপুট বৈধকরণ কৌশল গ্রহণ করেন যা ব্যবহারকারীর ইনপুটটি দৈর্ঘ্য, প্রকার এবং সিনট্যাক্সের জন্য নির্ধারিত নিয়মের একটি সেট এবং ব্যবসায়িক বিধি বিপরীতার বিরুদ্ধে প্রমাণীকৃত হয়।
জোসিপ আইভিক

312

আমার মতে আপনার পিএইচপি অ্যাপ্লিকেশনটিতে (বা কোনও ওয়েব অ্যাপ্লিকেশন, সাধারণত) এসকিউএল ইনজেকশন রোধ করার সর্বোত্তম উপায় হ'ল আপনার অ্যাপ্লিকেশনটির আর্কিটেকচার সম্পর্কে চিন্তা করা। এসকিউএল ইঞ্জেকশন থেকে রক্ষা করার একমাত্র উপায় যদি কোনও বিশেষ পদ্ধতি বা ফাংশন ব্যবহার করা মনে রাখা হয় যা আপনি যখনই ডাটাবেসের সাথে কথা বলছেন তখন ডান জিনিসটি করেন, আপনি এটি ভুল করছেন। এইভাবে, আপনার কোডের কোনও পর্যায়ে আপনার কোয়েরিটি সঠিকভাবে ফর্ম্যাট করতে ভুলে যাওয়া অবধি অবধি সময় মাত্র।

এমভিসি প্যাটার্ন এবং কেকপিএইচপি বা কোডআইগিনিটারের মতো কাঠামোর অবলম্বন করা সম্ভবত সঠিক উপায়: নিরাপদ ডাটাবেস অনুসন্ধান তৈরির মতো সাধারণ কাজগুলি এই জাতীয় ফ্রেমওয়ার্কগুলিতে সমাধান করা হয়েছে এবং কেন্দ্রীয়ভাবে প্রয়োগ করা হয়েছে। তারা আপনাকে আপনার ওয়েব অ্যাপ্লিকেশনটি বুদ্ধিমান উপায়ে সংগঠিত করতে এবং একক এসকিউএল অনুসন্ধানগুলি সুরক্ষিতভাবে নির্মাণের চেয়ে অবজেক্ট লোড এবং সংরক্ষণ সম্পর্কে আরও বেশি ভাবাতে সহায়তা করে।


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

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

3
এখানে. এখানে. ভাল দিক. যাইহোক, আপনি কি সম্মত হবেন যে অনেক লোক এমভিসি সিস্টেম গ্রহণ করতে শিখতে এবং শিখতে পারে তবে সকলেই হাত দ্বারা এটি পুনরুত্পাদন করতে পারে না (নিয়ন্ত্রণকারী এবং সার্ভার)। এই পয়েন্টটি দিয়ে কেউ খুব বেশি দূর যেতে পারে। আমার মেয়ে বন্ধু আমাকে তৈরি করার আগে আমার চিনাবাদাম মাখন পেকান কুকিজ গরম করার আগে আমার মাইক্রোওয়েভটি বুঝতে হবে? ;-)
অ্যান্টনি রটলেজ

3
পছন্দ করুন আমি মনে করি ব্যবহারের ক্ষেত্রেও একটি পার্থক্য রয়েছে: আমি কি আমার ব্যক্তিগত হোমপেজের জন্য একটি ফটো গ্যালারী তৈরি করছি বা আমি একটি অনলাইন ব্যাংকিং ওয়েব অ্যাপ্লিকেশন তৈরি করছি? পরবর্তী ক্ষেত্রে সুরক্ষার বিশদ এবং আমি যে কাঠামোটি ব্যবহার করছি সেগুলি কীভাবে সম্বোধন করছে তা বোঝা খুব গুরুত্বপূর্ণ very
জোহানেস ফারেনক্রুগ

3
আহ, সুরক্ষা ব্যতিক্রম এটি নিজেই করুন ol দেখুন, আমি এগুলি সব ঝুঁকিপূর্ণ করতে চাই এবং বিরতিতে যেতে চাই। :-) দুষ্টুমি. পর্যাপ্ত সময় সহ, লোকেরা একটি সুন্দর রঙিন সুরক্ষিত অ্যাপ্লিকেশন তৈরি করতে শিখতে পারে। প্রচুর লোক ভিড় করছে। তারা তাদের হাত উপরে ফেলে এবং ধরে নেয় যে ফ্রেমওয়ার্কগুলি আরও নিরাপদ । সর্বোপরি, তাদের কাছে পরীক্ষা করার এবং জিনিসগুলি বের করার পর্যাপ্ত সময় নেই। অধিকন্তু, সুরক্ষা এমন একটি ক্ষেত্র যার জন্য নিবেদিত অধ্যয়ন প্রয়োজন। এটি অ্যালগরিদম এবং ডিজাইনের ধরণগুলি বোঝার দ্বারা নিখুঁত প্রোগ্রামাররা গভীরতার সাথে জানেন এমন কিছু নয়।
অ্যান্টনি রুটলেজ

298

আমি সুরক্ষিত দৃষ্টিকোণ থেকে সঞ্চিত পদ্ধতিগুলি ( মাইএসকিউএল 5.0 সাল থেকে পদ্ধতিগুলির সহায়তা সংরক্ষণ করে রেখেছি ) - এর সুবিধাগুলি হল -

  1. সর্বাধিক ডাটাবেসগুলি ( মাইএসকিউএল সহ ) ব্যবহারকারীর অ্যাক্সেসকে সঞ্চিত প্রক্রিয়া চালানোর ক্ষেত্রে সীমাবদ্ধ রাখতে সক্ষম করে। সূক্ষ্ম-সুরক্ষিত সুরক্ষা অ্যাক্সেস নিয়ন্ত্রণ সুবিধাগুলির আক্রমণকে আরও বাড়িয়ে তুলতে কার্যকর। এটি আপোস করা অ্যাপ্লিকেশনগুলিকে সরাসরি ডাটাবেসের বিরুদ্ধে এসকিউএল চালাতে সক্ষম হতে বাধা দেয়।
  2. তারা অ্যাপ্লিকেশন থেকে কাঁচা এসকিউএল কোয়েরি বিমূর্ত করে তোলে তাই অ্যাপ্লিকেশনটিতে ডাটাবেস কাঠামোর কম তথ্য পাওয়া যায়। এটি ডাটাবেসের অন্তর্নিহিত কাঠামো বুঝতে এবং উপযুক্ত আক্রমণগুলির নকশা করা লোকদের পক্ষে আরও শক্ত করে তোলে।
  3. তারা কেবলমাত্র পরামিতি গ্রহণ করে, তাই প্যারামিটারাইজড কোয়েরিগুলির সুবিধা রয়েছে। অবশ্যই - আইএমও আপনাকে এখনও আপনার ইনপুটটি স্যানিটাইজ করতে হবে - বিশেষত যদি আপনি সঞ্চিত পদ্ধতির অভ্যন্তরে গতিশীল এসকিউএল ব্যবহার করছেন।

অসুবিধাগুলি হ'ল -

  1. এগুলি (সঞ্চিত পদ্ধতিগুলি) বজায় রাখা শক্ত এবং খুব দ্রুত গুনের ঝোঁক। এটি তাদের একটি সমস্যা পরিচালনা করে তোলে।
  2. তারা গতিশীল প্রশ্নের জন্য খুব উপযুক্ত নয় - যদি সেগুলি পরামিতি হিসাবে গতিশীল কোড গ্রহণ করতে নির্মিত হয় তবে অনেকগুলি সুবিধা অবহেলা করা হয়।

297

এসকিউএল ইঞ্জেকশন এবং অন্যান্য এসকিউএল হ্যাকগুলি প্রতিরোধের বিভিন্ন উপায় রয়েছে। আপনি এটি সহজেই ইন্টারনেটে (গুগল অনুসন্ধান) খুঁজে পেতে পারেন। অবশ্যই পিডিও হ'ল একটি ভাল সমাধান। তবে আমি আপনাকে এসকিউএল ইঞ্জেকশন থেকে কিছু ভাল লিঙ্ক প্রতিরোধের পরামর্শ দিতে চাই।

এসকিউএল ইঞ্জেকশন কী এবং কীভাবে প্রতিরোধ করবেন

এসকিউএল ইঞ্জেকশনের জন্য পিএইচপি ম্যানুয়াল

মাইক্রোসফ্ট পিএইচপি ইন এসকিউএল ইঞ্জেকশন এবং প্রতিরোধ সম্পর্কে ব্যাখ্যা explanation

এবং মাইএসকিউএল এবং পিএইচপি সহ এসকিউএল ইঞ্জেকশন প্রতিরোধের মতো আরও কিছু ।

এখন, আপনার কেন আপনার এসকিউএল ইঞ্জেকশনটি থেকে আটকাতে হবে?

আমি আপনাকে জানাতে চাই: আমরা নীচে একটি সংক্ষিপ্ত উদাহরণ সহ এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য কেন চেষ্টা করব:

লগইন প্রমাণীকরণ মিলের জন্য প্রশ্ন:

$query="select * from users where email='".$_POST['email']."' and password='".$_POST['password']."' ";

এখন, যদি কেউ (একজন হ্যাকার) রাখে

$_POST['email']= admin@emali.com' OR '1=1

এবং পাসওয়ার্ড কিছু ....

ক্যোয়ারীটি কেবলমাত্র সিস্টেমটিতে পার্স করা হবে:

$query="select * from users where email='admin@emali.com' OR '1=1';

অন্য অংশটি বাতিল করা হবে। তো, কী হবে? একজন অন-অনুমোদিত ব্যবহারকারী (হ্যাকার) তার পাসওয়ার্ড না রেখে প্রশাসক হিসাবে লগ ইন করতে সক্ষম হবেন। এখন, প্রশাসক / ইমেল ব্যক্তি যে কিছু করতে পারে সে সে করতে পারে। দেখুন, এসকিউএল ইঞ্জেকশন প্রতিরোধ না করা হলে এটি অত্যন্ত বিপজ্জনক।


267

আমার মনে হয় যদি কেউ পিএইচপি এবং মাইএসকিউএল বা অন্য কোনও ডেটাবেস সার্ভার ব্যবহার করতে চায়:

  1. PDO (পিএইচপি ডেটা অবজেক্টস) শেখার বিষয়ে চিন্তা করুন - এটি একটি ডাটাবেস অ্যাক্সেস স্তর যা একাধিক ডাটাবেসগুলিতে অ্যাক্সেসের একটি অভিন্ন পদ্ধতি সরবরাহ করে।
  2. মাইএসকিউলি শিখার কথা চিন্তা করুন
  3. নেটিভ পিএইচপি ফাংশনগুলি ব্যবহার করুন যেমন: স্ট্রিপ_ট্যাগগুলি , মাইএসকিএল_রিয়াল_সেস্কেপ_স্ট্রিং অথবা যদি পরিবর্তনশীল সংখ্যাসূচক হয়, ঠিক (int)$fooএখানে পিএইচপি-তে ভেরিয়েবলের ধরণ সম্পর্কে আরও পড়ুন । আপনি যদি PDO বা MySQLi এর মতো লাইব্রেরি ব্যবহার করেন তবে সর্বদা PDO :: quotote () এবং mysqli_real_escape_string () ব্যবহার করুন

গ্রন্থাগারগুলির উদাহরণ:

---- পিডিও

----- কোনও স্থানধারক নেই - এসকিউএল ইঞ্জেকশনের জন্য পাকা! এটা খারাপ

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

----- নামবিহীন স্থানধারীরা

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

----- নামযুক্ত স্থানধারক

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

--- মাইএসকিউএলআই

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

পিএস :

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

তবে PDO এবং মাইএসকিউএলআই উভয়ই বেশ দ্রুত, মাইএসকিউএই বেঞ্চমার্কগুলিতে তাত্পর্যপূর্ণভাবে দ্রুত সম্পাদন করে - অ-প্রস্তুত বিবৃতিগুলির জন্য ~ 2.5%, এবং প্রস্তুতকৃতদের জন্য .5 6.5%।

এবং দয়া করে আপনার ডাটাবেসে প্রতিটি ক্যোয়ারী পরীক্ষা করুন - এটি ইঞ্জেকশন প্রতিরোধের আরও ভাল উপায়।


যে mysqli ভুল। প্রথম প্যারাম ডেটা ধরণের প্রকাশ করে।
মিকম্যাকুসা

257

যদি সম্ভব হয় তবে আপনার পরামিতিগুলির প্রকারগুলি কাস্ট করুন। তবে এটি কেবল সহজ ধরণের যেমন ইনট, বুল এবং ফ্লোটে কাজ করছে।

$unsafe_variable = $_POST['user_id'];

$safe_variable = (int)$unsafe_variable ;

mysqli_query($conn, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

3
এটি এমন কয়েকটি ক্ষেত্রে একটি যেখানে আমি প্রস্তুত বিবৃতিটির পরিবর্তে "পালানো মান" ব্যবহার করব। এবং পূর্ণসংখ্যার ধরণের রূপান্তর অত্যন্ত দক্ষ।
হোল্ডঅফহাঙ্গার

233

আপনি কি ক্যাশে ইঞ্জিনের সুবিধা নিতে চান, তাহলে মত Redis বা memcached , হয়তো DALMP একটি পছন্দ হতে পারে। এটা তোলে বিশুদ্ধ ব্যবহার MySQLi । এটি দেখুন: পিএইচপি ব্যবহার করে মাইএসকিউএলের জন্য ডালএমপি ডেটাবেস অ্যাবস্ট্রাকশন স্তর।

এছাড়াও, আপনি আপনার ক্যোয়ারী প্রস্তুত করার আগে আপনার যুক্তিগুলি 'প্রস্তুত' করতে পারেন যাতে আপনি গতিশীল কোয়েরি তৈরি করতে পারেন এবং শেষে সম্পূর্ণ বিবরণী সম্পর্কিত কোয়েরি থাকতে পারে। পিএইচপি ব্যবহার করে মাইএসকিউএলের জন্য ডালএমপি ডেটাবেস অ্যাবস্ট্রাকশন স্তর।


224

পিডিও কীভাবে ব্যবহার করবেন সে সম্পর্কে অনিশ্চিতদের জন্য ( mysql_ফাংশনগুলি থেকে আগত ), আমি একটি খুব, খুব সাধারণ পিডিও মোড়ক তৈরি করেছি যা একটি ফাইল। অ্যাপ্লিকেশনগুলি করা প্রয়োজন এমন সমস্ত সাধারণ জিনিসগুলি করা কতটা সহজ তা দেখানোর জন্য এটি বিদ্যমান। পোস্টগ্রাইএসকিউএল, মাইএসকিউএল এবং এসকিউএলাইট সহ কাজ করে।

মূলত, এটা পড়তে যখন আপনি পড়তে ম্যানুয়াল কিভাবে বাস্তব জীবনে ব্যবহার PDO ফাংশন লাগাতে এটা সহজ সংরক্ষণ এবং বিন্যাস মান পুনরুদ্ধার করতে করতে দেখতে আপনি চান।

আমি একটি কলাম চাই

$count = DB::column('SELECT COUNT(*) FROM `user`);

আমি একটি অ্যারের (কী => মান) ফলাফল চাই (অর্থাত্ একটি নির্বাচন বাক্স তৈরির জন্য)

$pairs = DB::pairs('SELECT `id`, `username` FROM `user`);

আমি একটি একক সারির ফলাফল চাই

$user = DB::row('SELECT * FROM `user` WHERE `id` = ?', array($user_id));

আমি ফলাফলের একটি অ্যারে চাই

$banned_users = DB::fetch('SELECT * FROM `user` WHERE `banned` = ?', array(TRUE));

222

এই পিএইচপি ফাংশনটি ব্যবহার করে mysql_escape_string()আপনি দ্রুত উপায়ে একটি ভাল প্রতিরোধ পেতে পারেন।

উদাহরণ স্বরূপ:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'

mysql_escape_string - একটি mysql_query ব্যবহারের জন্য একটি স্ট্রিং এড়িয়ে যায় E

আরও প্রতিরোধের জন্য, আপনি শেষে যুক্ত করতে পারেন ...

wHERE 1=1   or  LIMIT 1

শেষ পর্যন্ত আপনি পাবেন:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1

219

এসকিউএল বিবৃতিতে বিশেষ অক্ষরগুলি থেকে বাঁচার জন্য কয়েকটি নির্দেশিকা।

মাইএসকিউএল ব্যবহার করবেন না । এই এক্সটেনশানটি হ্রাস করা হয়েছে। ব্যবহারের MySQLi বা PDO পরিবর্তে।

MySQLi

একটি স্ট্রিংয়ে ম্যানুয়ালি বিশেষ অক্ষরগুলি পালানোর জন্য আপনি mysqli_real_escape_string ফাংশন ব্যবহার করতে পারেন । Mysqli_set_charset দিয়ে সঠিক অক্ষর সেট না করা হলে ফাংশনটি সঠিকভাবে কাজ করবে না ।

উদাহরণ:

$mysqli = new mysqli('host', 'user', 'password', 'database');
$mysqli->set_charset('charset');

$string = $mysqli->real_escape_string($string);
$mysqli->query("INSERT INTO table (column) VALUES ('$string')");

প্রস্তুত বিবৃতি সহ মানগুলি স্বয়ংক্রিয়ভাবে পালানোর জন্য, mysqli_prepare , এবং mysqli_stmt_bind_param ব্যবহার করুন যেখানে উপযুক্ত বিন্যাসের জন্য সংশ্লিষ্ট বাইন্ড ভেরিয়েবলগুলির প্রকারগুলি সরবরাহ করতে হবে:

উদাহরণ:

$stmt = $mysqli->prepare("INSERT INTO table (column1, column2) VALUES (?,?)");

$stmt->bind_param("is", $integer, $string);

$stmt->execute();

আপনি প্রস্তুত বিবৃতি ব্যবহার করেন বা তা না mysqli_real_escape_string, আপনি সর্বদা আপনার যে ইনপুট ডেটা নিয়ে কাজ করছেন তা জানতে হবে।

সুতরাং আপনি যদি একটি প্রস্তুত বিবৃতি ব্যবহার করেন তবে আপনাকে অবশ্যই mysqli_stmt_bind_paramফাংশনের জন্য ভেরিয়েবলের প্রকারগুলি নির্দিষ্ট করতে হবে ।

এবং mysqli_real_escape_stringনামটি যেমনটি বলেছে তেমন ব্যবহার এর জন্য, যেমন একটি স্ট্রিংয়ের মধ্যে বিশেষ অক্ষরগুলি পালিয়ে যায়, সুতরাং এটি পূর্ণসংখ্যাকে নিরাপদ করে না। এই ফাংশনটির উদ্দেশ্য হ'ল এসকিউএল স্টেটমেন্টগুলিতে স্ট্রিংগুলি ভাঙ্গা রোধ করা, এবং এটি তৈরি করতে পারে এমন ডাটাবেসের ক্ষতি। mysqli_real_escape_stringসঠিকভাবে ব্যবহৃত হলে বিশেষত একত্রিত হলে এটি একটি কার্যকর ফাংশন sprintf

উদাহরণ:

$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';

$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5

$integer = '99999999999999999999';
$query = sprintf("SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647

3
প্রশ্নটি খুব জেনেরিক। উপরের কয়েকটি দুর্দান্ত উত্তর, তবে বেশিরভাগ প্রস্তুত বিবৃতি পরামর্শ দেয়। মাইএসকিউলি অ্যাসিঙ্ক প্রস্তুত বিবৃতি সমর্থন করে না, সুতরাং স্প্রিন্টফ এই পরিস্থিতির জন্য দুর্দান্ত বিকল্প হিসাবে দেখায়।
ডাস্টিন গ্রাহাম

183

এই সমস্যার সহজ বিকল্পটি ডাটাবেসে নিজেই উপযুক্ত অনুমতি প্রদানের মাধ্যমে সমাধান করা যেতে পারে। উদাহরণস্বরূপ: আপনি যদি মাইএসকিউএল ডাটাবেস ব্যবহার করে থাকেন তবে টার্মিনাল বা ইউআই সরবরাহিত ডাটাবেসে প্রবেশ করুন এবং কেবল এই আদেশটি অনুসরণ করুন:

 GRANT SELECT, INSERT, DELETE ON database TO username@'localhost' IDENTIFIED BY 'password';

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

FLUSH PRIVILEGES; 

ফ্লাশ সম্পর্কে আরও তথ্য ।

ব্যবহারকারীর জন্য বর্তমান সুবিধাগুলি দেখতে নীচের ক্যোয়ারীটি চালিত করুন।

select * from mysql.user where User='username';

গ্রান্ট সম্পর্কে আরও জানুন ।


25
এই উত্তরটি মূলত ভুল , কারণ এটি কোনও ইঞ্জেকশন প্রতিরোধ রোধ করতে সহায়তা করে না তবে কেবল ফলাফলগুলি নরম করার চেষ্টা করছে। বৃথা.
আপনার কমন সেন্স

1
ঠিক আছে, এটি কোনও সমাধান সরবরাহ করে না, তবে জিনিসগুলি এড়াতে আপনি হাতের সামনে যা করতে পারেন তা।
অপূর্ব নেরলেকার

1
@ অপূর্ব আমার লক্ষ্য যদি আপনার ডাটাবেস থেকে ব্যক্তিগত তথ্য পড়া হয় তবে ডিলেট অনুমোদনের অর্থ নেই কিছুই।
অ্যালেক্স হলসগ্রোভ

1
@ অ্যালেক্সহলসগ্রোভ: এটিকে সহজ করে নিন, আমি ফলাফলগুলি নরম করার জন্য ভাল অভ্যাসের পরামর্শ দিচ্ছিলাম।
অপূর্ব নেরলেকার

2
@ অপূর্ব আপনি "পরিণতিগুলিকে নরম করতে" চান না, আপনি এর বিরুদ্ধে সুরক্ষার জন্য যথাসাধ্য চেষ্টা করতে চান। যদিও ন্যায়সঙ্গত হওয়ার জন্য, সঠিক ব্যবহারকারীর অ্যাক্সেস সেট করা গুরুত্বপূর্ণ, তবে ওপি যা চাইছে তা সত্য নয়।
অ্যালেক্স হলসগ্রোভ

177

অনেক দরকারী উত্তর সম্পর্কে, আমি এই থ্রেড কিছু মান যোগ করতে আশা করি।

এসকিউএল ইঞ্জেকশন হ'ল একটি আক্রমণ যা ব্যবহারকারীর ইনপুট (ইনপুটগুলি যা কোনও ব্যবহারকারী পূরণ করে এবং তারপরে কোয়েরিগুলির অভ্যন্তরে ব্যবহৃত হয়) এর মাধ্যমে করা যেতে পারে। এসকিউএল ইঞ্জেকশন নিদর্শনগুলি সঠিক কোয়েরি সিনট্যাক্স, যখন আমরা এটি বলতে পারি: খারাপ কারণে খারাপ অনুসন্ধানগুলি, এবং আমরা ধরে নিয়েছি যে কোনও খারাপ ব্যক্তি থাকতে পারে যা গোপন তথ্য (অ্যাক্সেস নিয়ন্ত্রণকে বাইপাস করে) সুরক্ষার তিনটি নীতিকে প্রভাবিত করার চেষ্টা করে (গোপনীয়তা) , সততা এবং উপলব্ধতা))

এখন, আমাদের বক্তব্যটি এসকিউএল ইনজেকশন আক্রমণগুলির মতো সুরক্ষা হুমকি প্রতিরোধ করা, প্রশ্ন জিজ্ঞাসা (পিএইচপি ব্যবহার করে কীভাবে এসকিউএল ইনজেকশন আক্রমণ প্রতিরোধ করতে হবে) আরও বাস্তবসম্মত হোন, ডাটা ফিল্টারিং বা সাফাই ইনপুট ডেটা ব্যবহারকারীর অভ্যন্তরে ব্যবহারকারীর ক্ষেত্রে এই জাতীয় ক্যোয়ারী, পিএইচপি বা অন্য কোনও প্রোগ্রামিং ল্যাঙ্গুয়েজ ব্যবহার করা ঘটনা নয়, বা আধুনিক প্রযুক্তি যেমন প্রস্তুত বিবৃতি বা এসকিউএল ইনজেকশন প্রতিরোধকে সমর্থনকারী কোনও অন্যান্য সরঞ্জাম ব্যবহার করার জন্য আরও বেশি লোকের পরামর্শ অনুসারে, এই সরঞ্জামগুলি আর পাওয়া যায় না তা বিবেচনা করুন? আপনি কীভাবে আপনার আবেদনটি সুরক্ষিত করবেন?

এসকিউএল ইনজেকশনের বিরুদ্ধে আমার পদ্ধতির বিষয়টি হল: ডাটাবেসে প্রেরণের আগে ব্যবহারকারী-ইনপুট ডেটা সাফ করা (কোনও প্রশ্নের মধ্যে এটি ব্যবহারের আগে)।

এর জন্য ডেটা ফিল্টারিং (নিরাপদ ডেটাতে অনিরাপদ ডেটা রূপান্তর করা)

বিবেচনা করুন যে PDO এবং MySQLi উপলব্ধ নয়। আপনি কীভাবে আপনার আবেদনটি সুরক্ষিত করতে পারেন? আপনি কি আমাকে এগুলি ব্যবহার করতে বাধ্য করেন? পিএইচপি বাদে অন্য ভাষার কি হবে? আমি সাধারণ ধারণা সরবরাহ করতে পছন্দ করি কারণ এটি কেবল নির্দিষ্ট ভাষার জন্য নয়, বিস্তৃত সীমান্তের জন্য ব্যবহার করা যেতে পারে।

  1. এসকিউএল ব্যবহারকারী (ব্যবহারকারীর সুবিধাগুলি সীমাবদ্ধ করে): সর্বাধিক সাধারণ এসকিউএল অপারেশনগুলি (নির্বাচন করুন, আপডেট, INSERT) হয়, তবে, কোনও আপডেটের দরকার নেই এমন কোনও ব্যবহারকারীকে আপডেট আপডেট কেন দিন? উদাহরণস্বরূপ, লগইন এবং অনুসন্ধান পৃষ্ঠাগুলি কেবলমাত্র নির্বাচন নির্বাচন করছে, তারপরে, কেন এই পৃষ্ঠাগুলিতে উচ্চতর সুবিধাগুলি সহ ডিবি ব্যবহারকারীদের ব্যবহার করবেন?

বিধি: সমস্ত সুযোগ-সুবিধার জন্য একটি ডাটাবেস ব্যবহারকারী তৈরি করবেন না। সমস্ত এসকিউএল ক্রিয়াকলাপের জন্য, আপনি সহজেই ব্যবহারের জন্য ব্যবহারকারীর নাম হিসাবে আপনার প্রকল্পটি (বিতরণকারী, নির্বাচনকারী, আপডেটকারী) তৈরি করতে পারেন।

ন্যূনতম সুযোগ সুবিধার নীতি দেখুন ।

  1. ডেটা ফিল্টারিং: কোনও ক্যোয়ারী ব্যবহারকারী ইনপুট তৈরি করার আগে, এটি বৈধ ও ফিল্টার করা উচিত। প্রোগ্রামারদের জন্য প্রতিটি ব্যবহারকারীর ইনপুট ভেরিয়েবলের জন্য কিছু বৈশিষ্ট্য নির্ধারণ করা গুরুত্বপূর্ণ: ডেটা টাইপ, ডেটা প্যাটার্ন এবং ডেটা দৈর্ঘ্য । একটি ক্ষেত্র যা (x এবং y) এর মধ্যে একটি সংখ্যা অবশ্যই সঠিক নিয়মটি ব্যবহার করে অবশ্যই বৈধ হওয়া উচিত, এবং একটি ক্ষেত্রের একটি স্ট্রিং (পাঠ্য): প্যাটার্নটি কেস হ'ল উদাহরণস্বরূপ, ব্যবহারকারীর নামটিতে অবশ্যই কয়েকটি অক্ষর থাকতে হবে, আসুন [a-zA-Z0-9_-।] বলুন। দৈর্ঘ্য (x এবং n) এর মধ্যে পরিবর্তিত হয় যেখানে x এবং n (পূর্ণসংখ্যা, x <= n)। বিধি: সঠিক ফিল্টার তৈরি করা এবং বৈধতা নিয়ম করা আমার পক্ষে সেরা অনুশীলন।

  2. অন্যান্য সরঞ্জামগুলি ব্যবহার করুন: এখানে, আমি আপনার সাথে একমত হব যে একটি প্রস্তুত বিবৃতি (প্যারাম্যাট্রাইজড ক্যোয়ারী) এবং সঞ্চিত পদ্ধতি অসুবিধাগুলি এখানে এই উপায়গুলির জন্য উন্নত দক্ষতার প্রয়োজন যা বেশিরভাগ ব্যবহারকারীর জন্য বিদ্যমান নয়। এখানে মূল ধারণাটি এসকিউএল কোয়েরি এবং অভ্যন্তরীণ যে ডেটা ব্যবহার করা হয় তার মধ্যে পার্থক্য করা। উভয় পন্থাগুলিও অনিরাপদ ডেটা সহ ব্যবহার করা যেতে পারে, কারণ এখানে ব্যবহারকারী-ইনপুট ডেটা মূল ক্যোয়ারিতে কিছু যোগ করে না, যেমন (যে কোনও বা x = x)।

আরো তথ্যের জন্য, দয়া করে পড়ুন OWASP এসকিউএল ইনজেকশন প্রতিরোধ চিট শিট

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

অবশেষে, বিবেচনা করা যাক যে কোনও ব্যবহারকারী তার / তার ব্যবহারকারীর নাম প্রবেশের পরিবর্তে নীচে এই পাঠ্যটি প্রেরণ করেছেন:

[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'

এই ইনপুটটি কোনও প্রস্তুত বিবৃতি এবং সঞ্চিত পদ্ধতি ছাড়াই তাড়াতাড়ি যাচাই করা যেতে পারে, তবে সেগুলি ব্যবহার করে ব্যবহারকারীর ডেটা ফিল্টারিং এবং বৈধতার পরে শুরু হয়।

শেষ পয়েন্টটি অপ্রত্যাশিত আচরণ সনাক্ত করছে যার জন্য আরও প্রচেষ্টা এবং জটিলতা প্রয়োজন; এটি সাধারণ ওয়েব অ্যাপ্লিকেশনগুলির জন্য প্রস্তাবিত নয়।

উপরের ব্যবহারকারী ইনপুটটিতে অপ্রত্যাশিত আচরণ হ'ল নির্বাচন, ইউনিয়ন, আইএফ, সাবস্ট্রাকিং, বেঞ্চমার্ক, এসএএ এবং রুট root এই শব্দগুলি শনাক্ত হয়ে গেলে আপনি ইনপুটটি এড়াতে পারবেন।

আপডেট 1:

একজন ব্যবহারকারী মন্তব্য করেছেন যে এই পোস্টটি অকেজো, ঠিক আছে! OWASP.ORG যা সরবরাহ করেছে তা এখানে :

প্রাথমিক প্রতিরক্ষা:

বিকল্প # 1: প্রস্তুত বিবৃতি ব্যবহার (প্যারামিটারাইজড কোয়েরি)
বিকল্প # 2: সঞ্চিত পদ্ধতি ব্যবহার
বিকল্প # 3: সমস্ত ব্যবহারকারী সরবরাহিত ইনপুটকে ছাড়িয়ে নেওয়া

অতিরিক্ত প্রতিরক্ষা:

এছাড়াও কার্যকর করুন: স্বল্প
তালিকার প্রাপ্যতা সম্পাদন করুন: সাদা তালিকা ইনপুট বৈধকরণ

আপনি যেমন জানেন যে কোনও নিবন্ধ দাবি করার পক্ষে কমপক্ষে একটি রেফারেন্স দ্বারা একটি বৈধ যুক্তি দ্বারা সমর্থন করা উচিত! অন্যথায়, এটি আক্রমণ এবং একটি খারাপ দাবি হিসাবে বিবেচিত!

আপডেট 2:

পিএইচপি ম্যানুয়াল থেকে, পিএইচপি: প্রস্তুত বিবৃতি - ম্যানুয়াল :

এসকেপিং এবং এসকিউএল ইঞ্জেকশন

বাউন্ডের ভেরিয়েবলগুলি সার্ভার দ্বারা স্বয়ংক্রিয়ভাবে পালানো হবে। সার্ভার কার্যকর স্থগিতের পূর্বে বিবৃতি টেম্পলেটে উপযুক্ত স্থানগুলিতে তাদের পালানো মান সন্নিবেশ করায়। উপযুক্ত রূপান্তর তৈরি করতে বাউন্ড ভেরিয়েবলের ধরণের জন্য সার্ভারকে একটি ইঙ্গিত সরবরাহ করতে হবে। আরও তথ্যের জন্য mysqli_stmt_bind_param () ফাংশনটি দেখুন।

সার্ভারের মধ্যে মানগুলি স্বয়ংক্রিয়ভাবে পালিয়ে যাওয়া কখনও কখনও এসকিউএল ইনজেকশন প্রতিরোধের জন্য সুরক্ষা বৈশিষ্ট্য হিসাবে বিবেচিত হয়। যদি ইনপুট মানগুলি সঠিকভাবে অব্যাহতি দেওয়া হয় তবে প্রস্তুত না হওয়া বিবৃতিগুলির সাথে একই ডিগ্রি সুরক্ষা অর্জন করা যেতে পারে।

আপডেট 3:

আমি প্রস্তুত বিবৃতি ব্যবহার করার সময় পিডিও এবং মাইএসকিউলি কীভাবে মাইএসকিউএল সার্ভারে কোয়েরি প্রেরণ করে তা জানার জন্য পরীক্ষার কেস তৈরি করেছি:

PDO:

$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));

অনুসন্ধান লগ:

    189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
    189 Quit

MySQLi:

$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();

অনুসন্ধান লগ:

    188 Prepare   SELECT * FROM awa_user WHERE username =?
    188 Execute   SELECT * FROM awa_user WHERE username ='\'\'1\'\''
    188 Quit

এটি স্পষ্ট যে একটি প্রস্তুত বিবৃতি ডেটা এড়িয়ে চলেছে, অন্য কিছুই নয়।

উপরের বিবৃতিতে যেমন উল্লেখ করা হয়েছে,

সার্ভারের মধ্যে মানগুলি স্বয়ংক্রিয়ভাবে পালিয়ে যাওয়া কখনও কখনও এসকিউএল ইনজেকশন প্রতিরোধের জন্য সুরক্ষা বৈশিষ্ট্য হিসাবে বিবেচিত হয়। ইনপুট মানগুলি সঠিকভাবে এড়িয়ে গেলে, প্রস্তুত না হওয়া বিবৃতিগুলির সাথে একই ডিগ্রি সুরক্ষা অর্জন করা যেতে পারে

সুতরাং, এটি প্রমাণ করে যে ডেটা বৈধকরণ যেমন intval()কোনও জিজ্ঞাসা প্রেরণের আগে পূর্ণসংখ্যার মানগুলির জন্য একটি ভাল ধারণা। তদ্ব্যতীত, ক্যোয়ারী প্রেরণের আগে দূষিত ব্যবহারকারীর ডেটা প্রতিরোধ করা একটি সঠিক এবং বৈধ পদ্ধতির

দয়া করে আরও বিস্তারিত তথ্যের জন্য এই প্রশ্নটি দেখুন: পিডিও মাইএসকিউএলে কাঁচা কোয়েরি প্রেরণ করে যখন মাইস্ক্লি প্রস্তুত কোয়েরি প্রেরণ করে, উভয়ই একই ফলাফল দেয়

তথ্যসূত্র:

  1. এসকিউএল ইঞ্জেকশন চিট শীট
  2. এসকিউএল ইনজেকশন
  3. তথ্য নিরাপত্তা
  4. সুরক্ষা নীতি
  5. তথ্য বৈধতা

175

সুরক্ষা সতর্কতা : এই উত্তরটি সুরক্ষার সেরা অনুশীলনের সাথে সামঞ্জস্যপূর্ণ নয়। এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য এসকেপিং অপর্যাপ্ত , পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করুন। আপনার নিজের ঝুঁকিতে নীচে বর্ণিত কৌশলটি ব্যবহার করুন। (এছাড়াও, mysql_real_escape_string()পিএইচপি 7 এ অপসারণ করা হয়েছিল)

অবহেলিত সতর্কতা : এই সময়ে মাইএসকিএল এক্সটেনশানটি হ্রাস করা হয়েছে। আমরা PDO এক্সটেনশন ব্যবহার করার পরামর্শ দিই

আমার ওয়েব অ্যাপ্লিকেশনটিকে এসকিউএল ইঞ্জেকশনের ঝুঁকি থেকে রোধ করতে আমি তিনটি ভিন্ন উপায় ব্যবহার করি।

  1. ব্যবহারের mysql_real_escape_string(), কোনো প্রি-সংজ্ঞায়িত কার্যকারিতা যা পিএইচপি এবং নিম্নোক্ত অক্ষর করার জন্য এই কোড অ্যাড ব্যাকস্ল্যাশ: \x00, \n, \r, \, ', "এবং \x1a। এসকিউএল ইঞ্জেকশনের সম্ভাবনা হ্রাস করতে পরামিতি হিসাবে ইনপুট মানগুলি পাস করুন।
  2. সর্বাধিক উন্নত উপায় হ'ল পিডিও ব্যবহার করা।

আমি আশা করি এটা তোমাকে সাহায্য করবে।

নিম্নলিখিত কোয়েরি বিবেচনা করুন:

$iId = mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

mysql_real_escape_string () এখানে রক্ষা করবে না। আপনি যদি আপনার প্রশ্নের মধ্যে আপনার ভেরিয়েবলগুলির চারপাশে একক উদ্ধৃতি ('') ব্যবহার করেন তবে এটিই আপনাকে এর বিরুদ্ধে রক্ষা করে। এর জন্য নীচে একটি সমাধান এখানে দেওয়া হল:

$iId = (int) mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

এই প্রশ্নের এই সম্পর্কে কিছু ভাল উত্তর আছে।

আমার পরামর্শ, PDO ব্যবহার করা সবচেয়ে ভাল বিকল্প best

সম্পাদনা:

mysql_real_escape_string()পিএইচপি 5.5.0 হিসাবে অবচয় করা হয়েছে। Mysqli বা PDO ব্যবহার করুন either

Mysql_real_escape_string () এর বিকল্প

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

উদাহরণ:

$iId = $mysqli->real_escape_string("1 OR 1=1");
$mysqli->query("SELECT * FROM table WHERE id = $iId");

169

একটি সহজ উপায় মত একটি পিএইচপি ফ্রেমওয়ার্ক ব্যবহার করতে হবে CodeIgniter বা Laravel যা ফিল্টারিং এবং সক্রিয় রেকর্ড মত Inbuilt বৈশিষ্ট্য যাতে এইসব তারতম্য সম্পর্কে চিন্তা করতে হবে না।


7
আমি মনে করি যে প্রশ্নের পুরো বিন্দুটি এমন কাঠামোটি ব্যবহার না করেই এটি করা to
Sanke

147

সতর্কতা: এই উত্তরে বর্ণিত পদ্ধতিটি কেবলমাত্র সুনির্দিষ্ট পরিস্থিতিতে প্রযোজ্য এবং এটি নিরাপদ নয় যেহেতু এসকিউএল ইনজেকশন আক্রমণগুলি কেবল ইনজেকশনে সক্ষম হওয়ার উপর নির্ভর করে না X=Y

আক্রমণকারীরা যদি পিএইচপি-র $_GETভেরিয়েবলের মাধ্যমে বা URL- এর ক্যোয়ারী স্ট্রিং দিয়ে ফর্মটি হ্যাক করার চেষ্টা করে থাকে তবে তারা সুরক্ষিত না থাকলে আপনি তাদের ধরতে সক্ষম হবেন।

RewriteCond %{QUERY_STRING} ([0-9]+)=([0-9]+)
RewriteRule ^(.*) ^/track.php

কারণ 1=1, 2=2, 1=2, 2=1, 1+1=2, ইত্যাদি ... একটি আক্রমণকারী একজন SQL ডাটাবেস সাধারণ প্রশ্ন আছে। হতে পারে এটি অনেক হ্যাকিং অ্যাপ্লিকেশন ব্যবহার করে।

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


কি হচ্ছে 1-1=0? :)
রাপলি অ্যান্ড্রেস

@ রেপলিঅ্যান্ড্রেস কিছু প্রকার ([0-9\-]+)=([0-9]+)
5

127

পিএইচপি এবং মাইএসকিউএল এর জন্য অনেকগুলি উত্তর রয়েছে তবে এসকিউএল ইঞ্জেকশন প্রতিরোধের পাশাপাশি oci8 ড্রাইভারের নিয়মিত ব্যবহারের জন্য পিএইচপি এবং ওরাকল এর কোড এখানে রয়েছে :

$conn = oci_connect($username, $password, $connection_string);
$stmt = oci_parse($conn, 'UPDATE table SET field = :xx WHERE ID = 123');
oci_bind_by_name($stmt, ':xx', $fieldval);
oci_execute($stmt);

দয়া করে oci_bind_by_name পরামিতিগুলি ব্যাখ্যা করুন।
জাহানজেব আওয়ান

127

আইডিয়োরমের মতো কোনও অবজেক্ট-রিলেশনাল ম্যাপার ব্যবহার করা ভাল ধারণা :

$user = ORM::for_table('user')
->where_equal('username', 'j4mie')
->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

এটি আপনাকে কেবল এসকিউএল ইঞ্জেকশন থেকে রক্ষা করবে না, সিনট্যাক্স ত্রুটি থেকেও! এটি একবারে একাধিক ফলাফলগুলিতে এবং একাধিক সংযোগগুলিতে ফিল্টার করতে বা প্রয়োগ প্রয়োগ করার জন্য পদ্ধতি শৃঙ্খলাযুক্ত মডেলগুলির সংগ্রহগুলিকে সমর্থন করে।


124

অসম্মতিযুক্ত সতর্কতা: এই উত্তরের নমুনা কোড (প্রশ্নের প্রশ্নের নমুনা কোডের মতো) পিএইচপি-র MySQLএক্সটেনশন ব্যবহার করে , যা পিএইচপি 5.5.0 এ অবমূল্যায়ন করা হয়েছিল এবং পুরোপুরি পিএইচপি 7.0.0 এ অপসারণ করা হয়েছিল।

সুরক্ষা সতর্কতা : এই উত্তরটি সুরক্ষার সেরা অনুশীলনের সাথে সামঞ্জস্যপূর্ণ নয়। এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য এসকেপিং অপর্যাপ্ত , পরিবর্তে প্রস্তুত বিবৃতি ব্যবহার করুন। আপনার নিজের ঝুঁকিতে নীচে বর্ণিত কৌশলটি ব্যবহার করুন। (এছাড়াও, mysql_real_escape_string()পিএইচপি 7 এ অপসারণ করা হয়েছিল)

এসকিউএল ইনজেকশন প্রতিরোধের জন্য PDO এবং MYSQLi ব্যবহার করা একটি ভাল অনুশীলন, তবে আপনি যদি সত্যিই মাইএসকিউএল ফাংশন এবং কোয়েরি নিয়ে কাজ করতে চান তবে এটি ব্যবহার করা ভাল would

mysql_real_escape_string

$unsafe_variable = mysql_real_escape_string($_POST['user_input']);

এটি প্রতিরোধ করার জন্য আরও ক্ষমতা রয়েছে: সনাক্তকরণের মতো - যদি ইনপুটটি স্ট্রিং, সংখ্যা, চর বা অ্যারে হয় তবে এটি সনাক্ত করার জন্য অনেকগুলি ইনবিল্ট ফাংশন রয়েছে। এছাড়াও, ইনপুট ডেটা চেক করতে এই ফাংশনগুলি ব্যবহার করা ভাল।

is_string

$unsafe_variable = (is_string($_POST['user_input']) ? $_POST['user_input'] : '');

is_numeric

$unsafe_variable = (is_numeric($_POST['user_input']) ? $_POST['user_input'] : '');

এবং ইনপুট ডেটা যাচাই করতে এই ফাংশনগুলি ব্যবহার করা আরও ভাল mysql_real_escape_string


10
এছাড়াও, is_string () সহ _P _POST অ্যারে সদস্যদের চেক করার একেবারেই অর্থ নেই
আপনার সাধারণ জ্ঞান

21
সতর্কবার্তা! mysql_real_escape_string() অচল নয়
উদ্বিগ্ন

10
mysql_real_escape_stringএখন হ্রাস করা হয়েছে, সুতরাং এটি আর একটি কার্যকর বিকল্প নয়। ভবিষ্যতে এটি পিএইচপি থেকে সরানো হবে। পিএইচপি বা মাইএসকিউএল লোকেরা যা প্রস্তাব দেয় সেদিকে সরিয়ে নেওয়া সেরা।
jww

2
থিম: ব্যবহারকারীর জমা দেওয়া ডেটা বিশ্বাস করবেন না। আপনার প্রত্যাশিত যে কোনও কিছুই হ'ল বিশেষ অক্ষর বা বুলিয়ান যুক্তিযুক্ত একটি আবর্জনা ডেটা, যা নিজেই চালাচ্ছেন এমন এসকিউএল কোয়েরির একটি অংশ হয়ে উঠতে হবে। S _POST মানগুলিকে কেবল ডেটা হিসাবে রাখুন, এসকিউএল অংশ নয়।
বিমল পাউডেল

88

আমি এই ছোট ফাংশনটি বেশ কয়েক বছর আগে লিখেছি:

function sqlvprintf($query, $args)
{
    global $DB_LINK;
    $ctr = 0;
    ensureConnection(); // Connect to database if not connected already.
    $values = array();
    foreach ($args as $value)
    {
        if (is_string($value))
        {
            $value = "'" . mysqli_real_escape_string($DB_LINK, $value) . "'";
        }
        else if (is_null($value))
        {
            $value = 'NULL';
        }
        else if (!is_int($value) && !is_float($value))
        {
            die('Only numeric, string, array and NULL arguments allowed in a query. Argument '.($ctr+1).' is not a basic type, it\'s type is '. gettype($value). '.');
        }
        $values[] = $value;
        $ctr++;
    }
    $query = preg_replace_callback(
        '/{(\\d+)}/', 
        function($match) use ($values)
        {
            if (isset($values[$match[1]]))
            {
                return $values[$match[1]];
            }
            else
            {
                return $match[0];
            }
        },
        $query
    );
    return $query;
}

function runEscapedQuery($preparedQuery /*, ...*/)
{
    $params = array_slice(func_get_args(), 1);
    $results = runQuery(sqlvprintf($preparedQuery, $params)); // Run query and fetch results.   
    return $results;
}

এটি ওয়ান-লাইনার সি # আইশ স্ট্রিংয়ে চলমান বক্তব্যগুলিকে মঞ্জুরি দেয় Forএর মতো ফর্ম্যাট করুন:

runEscapedQuery("INSERT INTO Whatever (id, foo, bar) VALUES ({0}, {1}, {2})", $numericVar, $stringVar1, $stringVar2);

এটি ভেরিয়েবলের ধরণ বিবেচনা করে পালিয়ে যায়। আপনি যদি টেবিল, কলামের নামগুলি প্যারামিটারাইজ করার চেষ্টা করেন তবে এটি ব্যর্থ হবে কারণ এটি প্রতিটি স্ট্রিংকে উদ্ধৃতিতে রাখে যা একটি অবৈধ বাক্য গঠন।

নিরাপত্তা আপডেট: পূর্ববর্তী str_replaceসংস্করণ ব্যবহারকারীর ডেটাতে {#} টোকেন যুক্ত করে ইঞ্জেকশনগুলিকে অনুমতি দিয়েছে। preg_replace_callbackযদি প্রতিস্থাপনে এই টোকেনগুলি থাকে তবে এই সংস্করণে সমস্যা হয় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.