পিডিও এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য বিবৃতি প্রস্তুত কি যথেষ্ট?


661

ধরা যাক আমার কাছে এর মতো কোড রয়েছে:

$dbh = new PDO("blahblah");

$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

পিডিও নথি বলছে:

প্রস্তুত বিবৃতিগুলির পরামিতিগুলি উদ্ধৃত করার দরকার নেই; ড্রাইভার এটি আপনার জন্য পরিচালনা করে।

এসকিউএল ইনজেকশনগুলি এড়াতে আমার যা করা দরকার তা কি সত্যই? আসলেই কি এত সহজ?

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


5
ভাল পদ্ধতির 7th সংখ্যা উত্তর stackoverflow.com/questions/134099/...
NullPoiиteя

উত্তর:


807

সংক্ষিপ্ত উত্তর হ'ল না , পিডিও প্রস্তুত সমস্ত সম্ভাব্য এসকিউএল-ইনজেকশন আক্রমণ থেকে আপনাকে রক্ষা করবে না। কিছু অস্পষ্ট প্রান্ত-ক্ষেত্রে জন্য।

আমি PDO সম্পর্কে কথা বলার জন্য এই উত্তরটি রূপান্তর করছি ...

দীর্ঘ উত্তর এত সহজ নয়। এটি এখানে প্রদর্শিত একটি আক্রমণ ভিত্তিক ।

আক্রমণ

সুতরাং, আসুন আক্রমণ দেখিয়ে শুরু করা যাক ...

$pdo->query('SET NAMES gbk');
$var = "\xbf\x27 OR 1=1 /*";
$query = 'SELECT * FROM test WHERE name = ? LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));

নির্দিষ্ট পরিস্থিতিতে, এটি 1 সারির বেশি ফিরে আসবে। আসুন এখানে কী চলছে তা ছড়িয়ে দিন:

  1. একটি অক্ষর সেট নির্বাচন করা হচ্ছে

    $pdo->query('SET NAMES gbk');

    কাজ এই আক্রমণ, আমরা এনকোডিং প্রয়োজন যে সার্ভারের উভয় সঙ্কেতাক্ষরে লিখা সংযোগে আশা 'হওয়া ASCII অর্থাত হিসেবে 0x27 এবং কিছু চরিত্র যার চূড়ান্ত বাইট একটি ASCII হয় আছে \অর্থাত 0x5c। এটি সক্রিয় আউট হিসাবে, 5 ধরনের ডিফল্টরূপে মাইএসকিউএল 5.6 সমর্থিত এনকোডিং আছেন: big5, cp932, gb2312, gbkএবং sjis। আমরা gbkএখানে নির্বাচন করব ।

    এখন, SET NAMESএখানে ব্যবহার নোট করা খুব গুরুত্বপূর্ণ । এই অক্ষর সেট সেট করে সার্ভারে । এটি করার আরও একটি উপায় আছে তবে আমরা খুব শীঘ্রই সেখানে পৌঁছে যাব।

  2. পে লোড

    আমরা এই ইঞ্জেকশনের জন্য যে পেডলোডটি ব্যবহার করতে যাচ্ছি তা বাইট সিকোয়েন্স দিয়ে শুরু হয় 0xbf27। ইন gbk, এটি একটি অবৈধ মাল্টিবাইট চরিত্র; ইন latin1, এটি স্ট্রিং ¿'। মনে রাখবেন যে, মধ্যে latin1 এবং gbk , 0x27তার নিজের একটি আক্ষরিক হয় 'অক্ষর।

    আমরা এই পে-লোডটি বেছে নিয়েছি কারণ, যদি আমরা addslashes()এটির আহ্বান করি তবে আমরা একটি এএসসিআইআই \অর্থাত অক্ষরের 0x5cআগে sert োকাতাম '। সুতরাং আমরা সাথে বয়ে যাব 0xbf5c27, যা gbkএকটি দুটি চরিত্রের ক্রম: এর 0xbf5cপরে 0x27। বা অন্য কথায়, একটি অবৈধ অক্ষর অনুসরণ করে একটি বৈধ অক্ষর '। কিন্তু আমরা ব্যবহার করছি না addslashes()। পরবর্তী পদক্ষেপে তাই ...

  3. $ Stmt-> চালানো ()

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

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

    অতএব mysql_real_escape_string()ব্যাকস্ল্যাশ সন্নিবেশ করানোর জন্য কলটি , এবং 'আমাদের "পালানো" সামগ্রীতে আমাদের একটি বিনামূল্যে ঝুলন্ত চরিত্র রয়েছে! বস্তুত, যদি আমরা তাকান ছিল $varমধ্যে gbkঅক্ষর সেট, আমরা দেখতে চাই:

    OR 'বা 1 = 1 / *

    আক্রমণটি ঠিক কী প্রয়োজন।

  4. প্রশ্ন

    এই অংশটি কেবল একটি আনুষ্ঠানিকতা, তবে এখানে রেন্ডার্ড কোয়েরি রয়েছে:

    SELECT * FROM test WHERE name = '縗' OR 1=1 /*' LIMIT 1

অভিনন্দন, আপনি কেবলমাত্র সাফল্যের সাথে পিডিও প্রস্তুত বিবৃতি ব্যবহার করে একটি প্রোগ্রাম আক্রমণ করেছেন ...

সিম্পল ফিক্স

এখন, এটি লক্ষণীয় যে আপনি অনুকরণীয় প্রস্তুত বিবৃতি অক্ষম করে এটি প্রতিরোধ করতে পারেন:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

এটি সাধারণত একটি সত্য প্রস্তুত বিবৃতিতে (যেমন কোয়েরি থেকে পৃথক প্যাকেটে ডেটা প্রেরণ করা হবে) ফলাফল করে। যাইহোক, সচেতন থাকবেন PDO চুপটি হবে ফলব্যাক বিবৃতি এমুলেট যে মাইএসকিউএল স্থানীয়ভাবে প্রস্তুত পারে না: ঐ যে এটা করছে পারেন তালিকাভুক্ত ম্যানুয়াল কিন্তু উপযুক্ত সার্ভার সংস্করণ নির্বাচন করুন করার জন্য) হুঁশিয়ার।

সঠিক ফিক্স

এখানে সমস্যাটি হ'ল আমরা এর mysql_set_charset()পরিবর্তে সিপিআই'র কল করি নি SET NAMES। আমরা যদি তা করি তবে আমরা ভাল থাকব যদি আমরা 2006 থেকে একটি মাইএসকিউএল রিলিজ ব্যবহার করি।

আপনি আগের মাইএসকিউএল রিলিজ, তারপর একটি ব্যবহার করেন, তাহলে বাগ মধ্যে mysql_real_escape_string()অর্থ ছিল যেমন আমাদের পে লোড ঐ অবৈধ multibyte অক্ষর উদ্দেশ্যে পলায়নের জন্য একক বাইট পরিণত হওয়ার উপক্রম হয়েছিল এমনকি যদি ক্লায়েন্ট সঠিকভাবে সংযোগ এনকোডিং অবগত করা হয়েছে এবং তাই এই হামলা would এখনও সফল। বাগটি MySQL 4.1.20 , 5.0.22 এবং 5.1.11 এ স্থির করা হয়েছিল ।

তবে সবচেয়ে খারাপ দিকটি হ'ল 5.3.6 পর্যন্ত সিআইপি PDOপ্রকাশ করা হয়নি mysql_set_charset(), সুতরাং পূর্ববর্তী সংস্করণগুলিতে এটি প্রতিটি সম্ভাব্য কমান্ডের জন্য এই আক্রমণটিকে আটকাতে পারে না ! এটি এখন ডিএসএন প্যারামিটার হিসাবে প্রকাশিত হয়েছে , যা পরিবর্তে ব্যবহার করা উচিত SET NAMES...

সেভিং গ্রেস

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

বিকল্পভাবে, আপনি NO_BACKSLASH_ESCAPESএসকিউএল মোড সক্ষম করতে পারেন , যা (অন্যান্য জিনিসগুলির মধ্যে) এর ক্রিয়াকলাপকে পরিবর্তন করে mysql_real_escape_string()। এই মোডে সক্ষম থাকলে, 0x27সঙ্গে প্রতিস্থাপন করা হবে 0x2727বরং 0x5c27পলায়নের প্রক্রিয়া এবং এইভাবে করতে পারবে না প্রবন এনকোডিং যেখানে তারা পূর্বে উপস্থিত করেনি কোনো বৈধ অক্ষর তৈরি (যেমন 0xbf27এখনও 0xbf27ইত্যাদি।) - সার্ভার তাই এখনও অবৈধ হিসাবে স্ট্রিং প্রত্যাখ্যান করবে । তবে, এই এসকিউএল মোড (PDO সহ না হলেও) ব্যবহার করে উত্থাপিত হতে পারে এমন একটি ভিন্ন দুর্বলতার জন্য @ eggyal এর উত্তর দেখুন ।

নিরাপদ উদাহরণ

নিম্নলিখিত উদাহরণগুলি নিরাপদ:

mysql_query('SET NAMES utf8');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

কারণ সার্ভারের প্রত্যাশা utf8...

mysql_set_charset('gbk');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

কারণ আমরা ঠিকমতো অক্ষর সেট করে রেখেছি তাই ক্লায়েন্ট এবং সার্ভারের মিল রয়েছে।

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES gbk');
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

কারণ আমরা অনুকরণীয় প্রস্তুত বিবৃতি বন্ধ করেছি।

$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=gbk', $user, $password);
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

কারণ আমরা চরিত্রটি সঠিকভাবে সেট করেছি।

$mysqli->query('SET NAMES gbk');
$stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$param = "\xbf\x27 OR 1=1 /*";
$stmt->bind_param('s', $param);
$stmt->execute();

কারণ মাইএসকিউএলআই সমস্ত সময় সত্য প্রস্তুত বিবৃতি দেয়।

মোড়ক উম্মচন

আপনি যদি:

  • মাইএসকিউএল এর আধুনিক সংস্করণগুলি (5.1, 5.6, ইত্যাদির শেষের দিকে 5.1) এবং পিডিওর ডিএসএন চরসেট প্যারামিটার (পিএইচপি ≥ 5.3.6 এ) ব্যবহার করুন

অথবা

  • সংযোগ এনকোডিংয়ের জন্য দুর্বল অক্ষর সেট ব্যবহার করবেন না (আপনি কেবল utf8/ latin1/ ascii/ ইত্যাদি ব্যবহার করেন )

অথবা

  • NO_BACKSLASH_ESCAPESএসকিউএল মোড সক্ষম করুন

আপনি 100% নিরাপদ

অন্যথায়, আপনি PDO প্রস্তুত বিবৃতি ব্যবহার করা সত্ত্বেও আপনি দুর্বল হন ...

অভিযোজ্য বস্তু

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


47
এটি সবচেয়ে ভাল উত্তর যা আমি পেয়েছি .. আপনি আরও রেফারেন্সের জন্য একটি লিঙ্ক সরবরাহ করতে পারেন?
স্ট্যাটিক পরিবর্তনশীল

1
@nicogawenda: এটি একটি পৃথক বাগ ছিল। 5.0.22 এর আগে, সংযোগটি mysql_real_escape_stringসঠিকভাবে বিআইজি 5 / জিবিকে সেট করা হয়েছে এমন ক্ষেত্রেগুলি সঠিকভাবে পরিচালনা করবে না। সুতরাং আসলে এমনকি mysql_set_charset()মাইএসকিএল <5.0.22 এ কল করা এই বাগের পক্ষে ঝুঁকিপূর্ণ হবে! সুতরাং না, এই পোস্টটি এখনও 5.0.22 এ প্রযোজ্য (কারণ mysql_real_escape_string কেবলমাত্র কলগুলি থেকে দূরে রয়েছে mysql_set_charset(), যা এই পোস্টটি বাইপাস করার বিষয়ে কথা বলছে) ...
ircmamaxell

1
@ প্রোগফা এটি ব্যবহার করে বা না করে আপনার ব্যবহারকারীর ডেটা সহ কিছু করার আগে সর্বদা আপনার ইনপুটটি সার্ভারে বৈধ করে তোলা উচিত।
টেক

2
দয়া করে মনে রাখবেন NO_BACKSLASH_ESCAPES: নতুন দুর্বলতা পরিচয় করিয়ে দিতে পারেন stackoverflow.com/a/23277864/1014813
lepix

2
আপনি যা চান তার জন্য "ওআর 1 = 1" স্থানধারকটিকে স্লুইভ করুন। হ্যাঁ, এটি নামের কোনও মান সন্ধান করছে, তবে "OR 1 = 1" অংশটি "ব্যবহারকারীদের থেকে" ইউনিয়ন নির্বাচন করুন "কল্পনা করুন। আপনি এখন ক্যোয়ারীটি নিয়ন্ত্রণ করুন, এবং এর মতো এটির অপব্যবহার করতে পারে ...
ইরকমেক্সেল

515

প্রস্তুত বিবৃতি / স্থিতিমাপ প্রশ্নের সাধারণত প্রতিরোধের জন্য যথেষ্ট হয় 1 ম অর্ডার যে বিবৃতি উপর ইনজেকশন * । আপনি যদি আপনার অ্যাপ্লিকেশনের অন্য কোথাও চেক না করা গতিশীল স্কয়ার ব্যবহার করেন তবে আপনি এখনও ২ য় অর্ডার ইনজেকশনের পক্ষে ঝুঁকির মধ্যে রয়েছেন ।

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

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

' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '

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

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


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


6
এটা আকর্ষণীয়. আমি 1 ম অর্ডার বনাম দ্বিতীয় আদেশ সম্পর্কে অবগত ছিলাম না। ২ য় অর্ডার কীভাবে কাজ করে সে সম্পর্কে আপনি আরও কিছুটা ব্যাখ্যা করতে পারেন?
মার্ক বাইক

193
যদি আপনার সমস্ত প্রশ্নগুলি প্যারামিট্রাইজ করা হয় তবে আপনি ২ য় অর্ডার ইঞ্জেকশন থেকেও সুরক্ষিত রয়েছেন। 1 ম অর্ডার ইঞ্জেকশনটি ভুলে যাচ্ছে যে ব্যবহারকারীর ডেটা অবিশ্বাস্য। ২ য় অর্ডার ইঞ্জেকশনটি ভুলে যাচ্ছে যে ডাটাবেস ডেটা অবিশ্বাস্য। (কারণ এটি মূলত ব্যবহারকারী থেকে এসেছে)।
সিজেএম

6
ধন্যবাদ সিজেএম আমি এই নিবন্ধটি দ্বিতীয় আদেশের ইনজেকশনগুলি ব্যাখ্যা করতেও সহায়ক বলে মনে করেছি: কোডপ্রজেক্ট
মার্ক বাইক

49
অই হ্যাঁ. তবে তৃতীয় অর্ডার ইঞ্জেকশন সম্পর্কে কি । তাদের সম্পর্কে সচেতন হতে হবে।
Troelskn

81
@ ট্রয়লস্কন অবশ্যই সেখানেই হবে যেখানে বিকাশকারী অবিশ্বাস্য ডেটার উত্স
মাইকমুরকো

45

না, তারা সবসময় হয় না।

আপনি কি ইউজার ইনপুটটিকে নিজেরাই ক্যোয়ারির মধ্যে রাখার অনুমতি দিচ্ছেন তা নির্ভর করে। উদাহরণ স্বরূপ:

$dbh = new PDO("blahblah");

$tableToUse = $_GET['userTable'];

$stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

এসকিউএল ইনজেকশনগুলির পক্ষে ঝুঁকির মধ্যে পড়ে এবং এই উদাহরণে প্রস্তুত বিবৃতি ব্যবহার করা কার্যকর হবে না, কারণ ব্যবহারকারী ইনপুট ডেটা হিসাবে নয়, সনাক্তকারী হিসাবে ব্যবহৃত হয়। এখানে সঠিক উত্তরটি হ'ল একরকম ফিল্টারিং / বৈধকরণ ব্যবহার করা হবে:

$dbh = new PDO("blahblah");

$tableToUse = $_GET['userTable'];
$allowedTables = array('users','admins','moderators');
if (!in_array($tableToUse,$allowedTables))    
 $tableToUse = 'users';

$stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

দ্রষ্টব্য: আপনি ডিডিএল (ডেটা সংজ্ঞা ভাষা) এর বাইরে চলে যাওয়া ডেটা বাঁধতে PDO ব্যবহার করতে পারবেন না, অর্থাত এটি কাজ করে না:

$stmt = $dbh->prepare('SELECT * FROM foo ORDER BY :userSuppliedData');

উপরোক্ত কাজ না করার কারণটি হ'ল কারণ DESCএবং ডেটাASC নয় । PDO কেবলমাত্র ডেটার জন্য পালাতে পারে । দ্বিতীয়ত, আপনি এর চারপাশে উদ্ধৃতিও রাখতে পারবেন না । একমাত্র উপায় ব্যবহারকারী বাছাই মনোনীত অনুমতি ম্যানুয়ালি ফিল্টার হয় এবং চেক করুন যে এটা হয় এর থেকে বা ।'DESCASC


11
আমি কি এখানে কিছু মিস করছি তবে স্ট্রাইক এর মতো স্ক্যালএলটি এড়াতে প্রস্তুত বিবৃতিগুলির পুরো পয়েন্টটি নয়? Prepare dbh-> প্রস্তুত করার মতো কিছু হবে না ('নির্বাচন করুন * ফর্ম থেকে: টেবিলটি যেখানে ব্যবহারকারীর নাম =: ব্যবহারকারীর নাম'); আপনার সমস্যা কাছাকাছি পেতে?
রব ফরেস্ট

4
@ রবফোরেস্ট হ্যাঁ আপনি নিখোঁজ রয়েছেন :)। আপনি যে তথ্যটি বেঁধে রাখেন তা কেবল ডিডিএল (ডেটা সংজ্ঞা ভাষা) এর জন্য কাজ করে। আপনার সেই উদ্ধৃতিগুলি এবং যথাযথভাবে পালানো দরকার। ক্যোয়ারির অন্যান্য অংশের জন্য উদ্ধৃতি স্থাপন এটিকে উচ্চ সম্ভাবনার সাথে ভেঙে দেয়। উদাহরণস্বরূপ, SELECT * FROM 'table'ভুল হতে পারে যেমনটি হওয়া উচিত SELECT * FROM `table`বা কোনও ব্যাকস্টিক ছাড়াই। তারপর মত কিছু জিনিসের জন্য ORDER BY DESCযেখানে DESCব্যবহারকারীর কাছ থেকে আসে কেবল পলান করা যাবে না। সুতরাং, ব্যবহারিক পরিস্থিতি বরং সীমাহীন।
টাওয়ার

8
আমি অবাক হই যে কীভাবে 6 জন একটি প্রস্তুত বিবৃতিটির সুস্পষ্টভাবে ভুল ব্যবহারের প্রস্তাব দেওয়া একটি মন্তব্যকে আপত্তি জানাতে পারে। এমনকি যদি তারা একবার চেষ্টা করেও ফেলেছিল তবে তারা এখনই আবিষ্কার করে ফেলবে যে টেবিলের নামের পরিবর্তে নামযুক্ত প্যারামিটার ব্যবহার করা কার্যকর হবে না।
ফলিক্স গাগনন-গ্রেনিয়ার

আপনি যদি এটি শিখতে চান তবে এখানে PDO- র একটি দুর্দান্ত টিউটোরিয়াল। a2znotes.blogspot.in/2014/09/intr پيداوار-to
আরএন কুশওয়াহা

11
টেবিলটি ব্যবহার করার জন্য আপনার কখনই কোয়েরি স্ট্রিং / পোষ্ট বডি ব্যবহার করা উচিত নয়। আপনার যদি মডেল না থাকে তবে কমপক্ষে switchটেবিলের নামটি ব্যবহার করতে একটি ব্যবহার করুন ।
ZiggyTheHamster

29

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

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

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


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

29

না এটি যথেষ্ট নয় (কিছু নির্দিষ্ট ক্ষেত্রে)! ডিফল্টরূপে পিডিও মাইএসকিউএল ডেটাবেস ড্রাইভার হিসাবে ব্যবহার করার সময় অনুকরণযুক্ত প্রস্তুত বিবৃতি ব্যবহার করে। মাইএসকিউএল এবং পিডিও ব্যবহার করার সময় আপনার সর্বদা অনুকরণ করা প্রস্তুত বিবৃতিগুলি অক্ষম করা উচিত:

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

আর একটি জিনিস যা সর্বদা করা উচিত এটি ডাটাবেসের সঠিক এনকোডিং সেট করে:

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

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

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


14

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


1

যদি আপনি এইচটিএমএল বা জেএস চেক ব্যবহার করে স্কয়ার ইনজেকশন ফ্রন্ট-এন্ড আটকাতে চান তবে আপনাকে বিবেচনা করতে হবে যে ফ্রন্ট-এন্ড চেকগুলি "বাইপাসেবল"।

আপনি জেএস অক্ষম করতে পারেন বা কোনও ফ্রন্ট-এন্ড ডেভলপমেন্ট সরঞ্জাম (আজকাল ফায়ারফক্স বা ক্রোমের সাথে অন্তর্নির্মিত) দিয়ে কোনও প্যাটার্ন সম্পাদনা করতে পারেন।

সুতরাং, এসকিউএল ইনজেকশন প্রতিরোধ করার জন্য, আপনার নিয়ামকের ভিতরে ইনপুট তারিখ ব্যাকএন্ড স্যানিটাইজ করা ঠিক হবে।

জিইটি এবং ইনপুট মানগুলি স্যানিটাইজ করার জন্য আমি আপনাকে ফিল্টার_ইনপুট () নেটিভ পিএইচপি ফাংশনটি ব্যবহার করার পরামর্শ দিতে চাই।

বুদ্ধিমান ডাটাবেস প্রশ্নের জন্য আপনি যদি সুরক্ষা নিয়ে এগিয়ে যেতে চান তবে আমি আপনাকে ডেটা ফর্ম্যাটটি যাচাই করতে নিয়মিত অভিব্যক্তি ব্যবহার করার পরামর্শ দিতে চাই। preg_match () আপনাকে এই ক্ষেত্রে সাহায্য করবে! তবে যত্ন নিন! রেজেক্স ইঞ্জিন এত হালকা নয়। এটি প্রয়োজনীয় হলেই এটি ব্যবহার করুন, অন্যথায় আপনার অ্যাপ্লিকেশন সম্পাদনা হ্রাস পাবে।

সুরক্ষার একটি ব্যয় আছে, কিন্তু আপনার কার্যকারিতা নষ্ট করবেন না!

সহজ উদাহরণ:

আপনি যদি জিইটি থেকে প্রাপ্ত কোনও মান, দ্বিগুণ চেক করতে চান তবে 99 এর চেয়ে কম যদি (! প্রেগ_ম্যাচ ('/ [0-9] {1,2} /')) {...} এর চেয়ে বেশি হয়

if (isset($value) && intval($value)) <99) {...}

সুতরাং, চূড়ান্ত উত্তরটি হ'ল: "না! পিডিও প্রস্তুত বিবৃতি সমস্ত ধরণের স্কল ইঞ্জেকশন প্রতিরোধ করে না"; এটি অপ্রত্যাশিত মানগুলি প্রতিরোধ করে না, কেবল অপ্রত্যাশিত কনটেন্টেশন


5
আপনি এসকিউএল ইঞ্জেকশনটিকে অন্য কোনও কিছুর সাথে বিভ্রান্ত করছেন যা আপনার উত্তরটিকে পুরোপুরি অপ্রাসঙ্গিক করে তুলেছে
আপনার প্রচলিত সেনস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.