سلام به همه دوستان
مدتی بود که مطلبی ارسال نکرده بودم این شد که تصمیم گرفتم برای دوست داران زبان PHP این مطلب بسیار مهمو بذارم توصیه میکنم کسایی که واقعا میخوان یاد بگیرن فقط به خوندن همین بسنده نکنن.
دوستان اموزشهایی که در پایین قرار میگیره ازسایت iran-eng.com و barnamenevis.org برداشته شدهاما اونجا چند تا پست بود و سوال و جواب وجود داشت و بهم ریخته بود ما اینجا از اون پست ها مطالب مفیدش رو برداشتیم و اینجا متمرکز کردیم تا گیج کننده نباشه.
موفق باشید.
خب یکی از مهمترین مسائل امنیتی در مورد اشتباهات رایج و ساده در کد نویسی هستش
یکی از قسمت های مهم که مورد حمله قرار میگره پایگاه های SQL هست که به SQL Injection معروف هست.
در یک مثال ساده ممکن هست در یک اسکریپ PHP از کاربر نام کاربری و رمزعبور درخواست بشه و سرور نسبت به صحیح بودن این امر DBMS مراجعه کنه نمونه کد:
[SQL]
SELECT * FROM users WHERE name='$username' AND pass='$password';
[/SQL]
اگر فردی به جای رمز عبور عبارت زیر رو وارد کنه :
[SQL]' OR '1'='1 [/SQL]
حاصل Query تبدیل به کد زیر میشه و به پایگاه داده ارسال میشه:
[SQL]SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1'; [/SQL]
با استفاده از خاصیت دستور منطقی OR و بدون تصدیق نام کاربری و رمز عبور صلاحیت اعمال میشه
برای حل این مشکل از تابع( ) addslashes استفاده میشه که قبل کوتیشن( ' )ها برش ایجاد میکنه (علامت بک اسلش()میذاره)
پس برای بهینه سازی نام کاربری و رمز عبور از کد زیر استفاده میکنیم:
$username = addslashes($_POST["username"]);
$password = addslashes($_POST["password"]);
نمونه مثال برای توابع stripslashes و addslashes:
$str = "Is your name O'reilly?";
// Outputs: Is your name O\'reilly?
echo addslashes($str);
$str = "Is your name O\'reilly?";
// Outputs: Is your name O'reilly?
echo stripslashes($str);
اما این به تنظیمات PHP شما هم بستگی داره. با فعال کردن magic_quotes_gpc در PHP.ini میتونید addslashes رو برای تمامی مقدارهای گرفته شده از GET و POST یا کوکی ها به صورت خودکار اعمال کنید.
با استفاده از از تابع () stripslashes همچنین میتونید در صورت نیاز برش ها رو از مقادیر حذف کنید.
در این کد با بررسی مقدار magic_quotes_gpc عمل حذف برش درون مقادیر اعمال میشه
if (get_magic_quotes_gpc()){
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
در واقع کد فوق این رو میگه که اگر مقدار تابع مورد نظر true باشه ( خروجی تابع فوق زمانی که مقدار get_magic_quotes_gpc در فایل پیکربندی on باشه ، true خواهد بود ) پس بهتر هست که slash های مقدار گرفته شده رو با تابع stripslashes حذف کنیم . چون در ادامه قرار هست با تابع addslashes به مقدار گرفته شده ، slash اضافه کنیم چرا که اگه این کار انجام نشه در واقع ما به مقدارمون 2 بار backslash اضافه کردیم . البته این ایرادی نیست ( البته در این مواقع ) چون ما میخوایم که در هر صورت query خودمون رو نا مفهوم کنیم برای mysql اما مواقعی که مثلا خودمون به عنوان admin از پایگاه خروجی بگیریم و یا صفحه ای داشته باشیم که بخواد خروجی ای از بانک رو به کاربر نشون بده که دارای کاراکتر خاص باشه ، اونوقت هست که به مشکل برمیخوریم. مثال برای مقدار O'reilly
<?php
echo get_magic_quotes_gpc(); // 1
echo $_POST['lastname']; // O\'reilly
echo addslashes($_POST['lastname']); // O\\\'reilly
if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST['lastname']);
} else {
$lastname = $_POST['lastname'];
}
echo $lastname; // O\'reilly
$sql = "INSERT INTO lastnames (lastname) VALUES ('$lastname')";
?>
اگر بخوایم از تابع addslshes استفاده کنیم باید قبلش چک کنیم که get_magic_quotes_gpc فعال هست یا نه که اگر نبود addslash انجام بدیم. اما اگر میخوایم که تحت هر شرایطی از تابع addslashes استفاده کنیم پس بهتره بعد از چک کردن اگر مقدار مقدار on بود ابتدا stripslashes رو صدا بزنیم و بعد addslashesh که این هم توضیح داده شد.
اما چیزی که هست اینکه این تابع Addslashes در کل برای این هست که اگر یک زمانی شما خواستین مقادیر حاصل از فرمی رو یا خروجی حاصل از پایگاهتون رو که کاراکترهای خاص مثل ' یا '' دارن توی صفحه چاپ کنید به مشکل بر نخورید . برای همین از این تابع استفاده میکنیم که php خودش قبل از کاراکترهای خاص یه backslash اضافه کنه تا مشکلی برای پردازش اونها پیش نیاد ( برای php نه mysql )
تابعی که در php برای این کار ایجاد شده و خود manuel php هم سفارش میکنه ، تابع mysql_real_escape_string هست که این تابع هم همون کار فیلتر کردن کاراکترهای خاص رو انجام میده اما قبلش یادتون باشه که چک کنید اگر مقدار get_magic_quotes_gpc ، on بود دیگه دوباره کاری نشه .
اینهم مثالش که با پارامترهای ورودی اون آشا بشین :
<?php
if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) {
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password');
if(!is_resource($link)) {
echo "Failed to connect to the server\n";
// ... log the error properly
} else {
// Reverse magic_quotes_gpc effects on those vars if ON.
if(get_magic_quotes_gpc()) {
$product_name = stripslashes($_POST['product_name']);
$product_description = stripslashes($_POST['product_description']);
} else {
$product_name = $_POST['product_name'];
$product_description = $_POST['product_description'];
}
// Make a safe query
$query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', '%d')",
mysql_real_escape_string($product_name, $link),
mysql_real_escape_string($product_description, $link),
$_POST['user_id']);
mysql_query($query, $link);
if (mysql_affected_rows($link) > 0) {
echo "Product inserted\n";
}
}
} else {
echo "Fill the form properly\n";
}
?>