دريافت Firefoxشما از نسخه ساده رايت کليک استفاده مي نماييد. براي ديدن نسخه پيشرفته رايت کليک، در صورت استفاده از يک مرورگر استاندارد، [ اينجا ]کليک نماييد.

آخرين عناوين ارسالي به انجمن ها
لينک هاي دوستان
به دليل حجم زياد فقط تعدادي به صورت تصادفي نمايش داده شده اند.
SQL Injection و مقابله با آن ...
1 , 2بازديد ها: 8368, پاسخ ها: 17
SQL Injection و مقابله با آن ...
توسط mojtaba در 25 مرداد 1386 - 9:43 ، پست ها: 1007
سلام دوستان،
همون طور که قول داده بودم مي خوام در زمينه SQL Injection (تزريق SQL يا Query) صحبت کنم...

همون طور که مي دونيد Query يک واسطه بين برنامه و DataBase هست ...
و همچنين مي دونيد که براي داشتن برنامه هاي Dynamic بايد Query ها را با توجه به ورودي (هاي) کاربر تغيير بديم ...

فرض کنيد ما يه فرم Login داريم و براي ورود کاربر از قطعه کد زير استفاده مي کنيم:

کد: انتخاب همه
<?php

$Username = $_POST['Username'];
$Password = $_POST['Password'];

$SQL = "SELECT * FROM `users` WHERE `u_name` = '$Username' AND `u_pass` = '$Password'";
$Rslt = mysql_query( $SQL);

if( mysql_num_rows( $Rslt) > 0)
{
   print('welcome to your profile...');

} else {

   die('The specified username and/or password is invalid!');

}

?>


خوب مشاهده مي کنيد که به ظاهر همه چيز مرتبه و کاربر با وارد کردن user و pass خودش مي تونه Login کنه و اگه اشتباه بود نمي تونه...

خوب يه کاربر شيطون اول مي آد يه username که Single Quotation توش هست مثل jo'hn رو امتحان مي کنه تا ببينه که ميتونه از اين روش استفاده ببره يا نه ... خوب بعد از فهميدن ورودي ها رو به اين شکل وارد مي کنه:
کد: انتخاب همه
username: a
password: ' or '1'='1


خوب ببينيم SQL ما به چه شکل در مي آد:

کد: انتخاب همه
SELECT * FROM `users` WHERE `u_name` = 'a' AND `u_pass` = '' or '1'='1'


خوب نتيجه Query رو خودتون مي دونيد ديگه اگه حداقل يک کاربر عضو سايت باشه به راحتي مي تونيم Login کنيم.

حالا به فرض اين که هکر username رو مي دونه

کد: انتخاب همه
username: admin'--
password: 123


خوب SQL:
کد: انتخاب همه
SELECT * FROM `users` WHERE `u_name` = 'admin'--' AND `u_pass` = '123'


همون طور که مي دونيد در MySQL -- علامت Comment هست
البته علامت هاي ديگري مثل /* ... */ و # هم در Mysql هستند...
يعني در واقع Query ما به اين شکل در مي آد:

کد: انتخاب همه
SELECT * FROM `users` WHERE `u_name` = 'admin'


خوب اين هم که بديهيه و Login با موفقيت انجام مي شه.
البته همه چيز به يک Login ختم نمي شه بلکه هکر مي تونه کل اطلاعات مربوط به ساختار و داده هاي DataBase ما رو در بياره ... به اين شکل:
البته به اين شکلي که نوشته شده MySQL خطا نمي ده ولي SQL server و ... خطا مي دن

کد: انتخاب همه
username: ' having 1=1--
password: 123


کد SQL :
کد: انتخاب همه
SELECT * FROM `users` WHERE `u_name` = '' having 1=1--' AND `u_pass` = '123'


پيغام خطايي که SQL server ميده اينه:
کد: انتخاب همه
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'user.u_name' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

که از اون مي شه اسم Table و اولين فيلد جدول رو به دست آورد...
همين طور که ميبينيد هکر از Error ها خيلي بهره مي بره...
به همين ترتيب مي شه کار هاي ديگه اي هم کرد مثلا:
کد: انتخاب همه
username: '; DROP TABLE `users` --
password: 123

SELECT * FROM `users` WHERE `u_name` = ''; DROP TABLE `users` -- AND `u_pass` = '123'


خوب مي بينيد که اين اصلا خوب نيست...

استفاده از UNION:

کد: انتخاب همه
username: ' UNION select max(`u_name`) from `users` --
password: 123

SELECT * FROM `users` WHERE `u_name` = '' UNION select max(`u_name`) from `users` -- AND `u_pass` = '123'


خطايي که سرور به ما ميده اينه :

کد: انتخاب همه
#1222 - The used SELECT statements have a different number of columns


خوب ما تعداد فيلد هاي SQL برنامه رو نمي دونيم به همين دليل کار خودمون رو با افزودن يک فيلد ديگر در UNION ادامه ميديم:

کد: انتخاب همه
username: ' UNION select max(`u_name`),0 from `users` --
password: 123

SELECT * FROM `users` WHERE `u_name` = '' UNION select max(`u_name`),0 from `users` -- AND `u_pass` = '123'

#1222 - The used SELECT statements have a different number of columns


باز هم همون خطاي قبلي رو ميده ... اين کار رو اين قدر ادامه ميديم تا تعداد فيلد ها رو به دست بياريم.
همچنين با استفاده از اين باگ ميتونيم اعمالي چون Insert, Delete, ... رو هم انجام بديم...
در ضمن فقط فرم Login که نيست هر جايي که با ديتابيس کار کنه ميتونه مورد حمله واقع بشه اما Login حساسيت بيشتري داره...

* * *

خوب حالا چاره چيه ...
اول بريم سراغ Login، کد مربوط به Login رو به اين شکل تغيير مي ديم:


کد: انتخاب همه
<?php

$Username = $_POST['Username'];
$Password = md5( $_POST['Password']);

$Username = strtolower( $Username);
$Username = preg_replace("([^a-z0-9_]*)", '', $Username);

$SQL = "SELECT `u_pass` FROM `users` WHERE `u_name` = '$Username' LIMIT 0,1";
$Rslt = mysql_query( $SQL);

if( mysql_num_rows( $Rslt) == 1 && $Password == mysql_result( $Rslt , 0))
{

   print('welcome to your profile...');

} else {

   die('The specified username and/or password is invalid!');

}

?>


اولا که Password رو حتما Hash کنيد که الگوريتم هاي مختلفي در اين زمينه وجود داره ... البته باز هم محدود به رد کردن يک يا چند بار از md5 نشيد بلکه با چيزهاي ديگري مثل تاريخ عضويت يا کد منحصر به فردي مخلوطش کنيد تا حسابي قرو قاطي بشه ... مثلا اين طوري:

کد: انتخاب همه
$HashedPass = md5( strrev(md5( $Password) . $RegisterDate));

خلاصه يه روال من در آوردي ... که حتي تو هر پروژه اي که مي نويسيد هم عوض بشه.

نکته بعد که خيلي مهمه اينه که نام کاربري فقط همونايي باشه که مي خواييم و ديگه کاراکتر هاي اضافي توش نباشه:

کد: انتخاب همه
$Username = preg_replace("([^a-z0-9_]*)", '', $Username);


که البته موقع ثبت نام کاربر هم Username رو از اين فيلتر رد ميکنيم و بهش ميگيم که از چه چيز هايي مي تونه استفاده کنه.

نکته بعد طرض نوشتن SQL مون هست:
کد: انتخاب همه
SELECT `u_pass` FROM `users` WHERE `u_name` = '$Username' LIMIT 0,1


همون طور که مي بينيد فقط Password کاربر از ديتابيس بيرون کشيده شده (البته توي برنامه هاي واقعي چيزاي ديگه اي هم هست که مي خونيم) ... بعد هم به شرط SQL دقت کنيد که فقط username رو مورد بررسي قرار مي ده همچنين به LIMIT 0,1 هم دقت کنيد که فقط يه رکورد رو بيرون مي کشيم.

نکته خيلي مهم اينجاست که Password رو خود ما چک مي کنيم و اونو به دست SQL نمي سپاريم :

کد: انتخاب همه
if( mysql_num_rows( $Rslt) == 1 && $Password == mysql_result( $Rslt , 0))


يعني اگه به هر شکل هکر بتواند SQL رو هم دور بزنه، اين جا رو نمي تونه دور بزنه...

---

نکات ديگه اي هم هست که براي جاهاي ديگه استفاده مي شه و اون اينه که کاراکتر هاي اضافي رو از طريق استفاده از تابع زير از ورودي هامون حذف کنيم:

کد: انتخاب همه
function EscapeString( $str , $Conn = 0)
{
   if(function_exists('mysql_real_escape_string') && $Conn) {

      return mysql_real_escape_string( $str, $Conn );

   } else {

      return mysql_escape_string( $str );
   }
}


نکته بسيار مهم ديگه اينه که براي ديتابيسمون دوتا user بسازيم، يکي فقط مي تونه SELECT رو انجام بده و ديگري فقط SELECT, UPDATE, INSERT, LOCK TABLE رو بتونه انجام بده، و موقعي که مي خواهيم Query فقط خوندن رو اجرا کنيم با user اولي به ديتابيس Connect مي شيم، که اگه هکر بتونه چيزي رو هم تزريق کنه که توي اطلاعات ما تغيير ايجاد کنه، خود DBMS اجازه همچين کاري رو نده ... در ضمن به user هاي ديتابيس دسترسي هاي خطر ناکي چون DROP TABLE, ALTER , ... رو نديم.

يک نکته مهم ديگه اينه که مثلا در فيلد هايي که int هستند و بر اساس اين فيلد جستجو انجام ميدين ورودي GET يا POST رو چک کنيد که حتما همون چيزي باشه که بايد باشه مثلا اگه قراره int باشه اون رو از تابع intval رد کنيد مثال:

کد: انتخاب همه
$NewsID = intval( $_GET[ 'ID' ]);
$SQL = "SELECT * FROM `news` WHERE `ID` = $NewsID LIMIT 0,1";


و نکته بسيار مهم آخر اينه که نگذاريد کسي خطاهاي برنامه شما را ببيند (حتي اطلاعات سرور و زبان برنامه نويسي رو هم مخفي کنيد خيلي خوبه)، چون همين خطاها هستند که به هکر ها اطلاعات ميدن ... براي اين کار بعد از اين که کل پروژه ساخته شد و خواستيد اون رو publish کنيد بالاي يکي از فايل هايي که توي همه فايل هاي برنامه include مي شه تابع زير رو به اين شکل صدا بزنيد:

کد: انتخاب همه
error_reporting( 0);


با آرزوي موفقيت و سربلندي براي همه شما عزيزان. :wink:
[ تبليغات ] سیستم دامنه رایگاناین سیستم به شما این امکان را می دهد که به کاربران وب، دامنه رایگان ارایه دهید. در واقع کاربران بوسیله این سیستم می توانند برای وب سایت ها...
تشكر ...
توسط ghasem در 25 مرداد 1386 - 11:42 ، پست ها: 45
سلام مجتبي جان ...
خسته نباشي عزيز ... از اين كه با اين همه كاري كه داري وقت ميزاري و مقاله هاي پر كاربرد و زيبا براي ما تهيه مي كني ممنونم ... :kuss:
موفق و مويد باشي ... :D
توسط mojtaba در 25 مرداد 1386 - 16:59 ، پست ها: 1007
سلام،
ممنونم قاسم جان...
ان شاء ا... شما هم موفق و پيروز باشيد. :wink:
توسط mahdi در 26 مرداد 1386 - 6:28 ، پست ها: 770
جالب بود ممنون... :wink:
توسط mahdi در 10 شهريور 1386 - 11:55 ، پست ها: 770
من نمي‏دونم وقتي داشتم سايتم را مي‏نوشتم اول كار با easyphp شروع كرده بودم و مشكلاتي هم داشت ولي وقتي با xampp شروع به كار كردم، مشكلات رفع شد و Bugي در كدهايم نبود، چند روز پيش كه برنامه easyphp را دانلود كردم و به كار انداختم براي برنامم همين bug ايجاد شد، حالا نمي‏دونم توي تنظيمات INI برنامه xampp، PHP جه چيزي بود كه من به اين مشكل دچار نشده بود :?: :idea:
توسط pooyamb در 21 خرداد 1387 - 12:06 ، پست ها: 27
به نظرتون با اين روش ميشه به سايت a n g e l bu x. co m هم نفوذ کرد آخه تو اين سايت زماني که مي خواي o ffer ها رو چک کني يه ارور sql ميده و از راه get ميشه به sql اون چيزي افزود.اول ثبت نام کنيد بعد بريد به اين آدرس: :x :evil: :evil: :evil: :evil:
http: //ww w.a ng elb ux.c om/o ff ers.php?or der=All&so rt= 2
فاصله گذاشتم تا با سرچ اين صفحه پيدا نشه؟
لينک رفرالم نذاشتم که کسب درآمد نباشه
توسط mojtaba در 21 خرداد 1387 - 21:56 ، پست ها: 1007
سلام،
من بررسي کردم قبل از Single Quote ها يه \ مي ذاره. ولي در مورد قابل نفوذ بودنش چيزي نمي گم.
موفق باشيد. :wink:
توسط pooyamb در 21 خرداد 1387 - 22:16 ، پست ها: 27
احتمال زيادي مي دم که قابل نفوذ باشه کدش بايد اين طوري باشه:
کد: انتخاب همه
SELECT ................. WHERE `???` = $_GET[order] ORDER BY of_made DESC

خوب مي شه اون مقدار رو دور زد ولي توي اين قضيه به مشکل مي خوره که اون order by رو نمي شه به شکل کامنت در آورد. :( :(
اگه شما مقدار order رو اول بديد مثلا :
کد: انتخاب همه
asd   ;%20DROP%20TABLE%20`users`%20 --
:( :(
اون مقداري که بايد به صورت order بگيره رو دور زديد ولي order و ادامش رو نمي دونم چرا مثل کامنت نمي کنه حالا رفاقتي يه کمکي بکنيد ديگه 8)
توسط mojtaba در 22 خرداد 1387 - 20:49 ، پست ها: 1007
سلام،
خوب توي SQL server همين -- Comment هست ديگه... که گذاشتي.
ديگه من چي بگم . . . :roll:
شما براي نفوذ بايد خيلي حوصله داشته باشي و همه راهي رو امتحان کني. در ضمن چون اين سايت php هست، خود php بعضي از راه ها رو بسته. 8)

موفق باشي :wink:
ويرايش و حذف ديتا بيس
توسط shafiei7 در 10 شهريور 1387 - 15:52 ، پست ها: 3
سلام دوست عزيز، لطفا نحوه جلوگيري از ويرايش و حذف اطلاعات ديتابيس رو هم توضيح بديد چون سايت من چند مدت پيش توسط يك هكر كليه اطلاعات ديتا بيس حذف گرديد نميدونم چطور اين كارو انجام داده او ميخواست اخاذي كنه و ميگفت بايد براي من رايگان تبليغ كني وگرنه اطلاعات ديتا بيس رو حذف ميكنم.
توسط mojtaba در 11 شهريور 1387 - 4:56 ، پست ها: 1007
سلام،
اگه حمله ي اون از طريق SQL Injetion بوده، خوب همين روش هاي پيشگيري رو که گفته شد رو استفاده کنيد.
شما بايد تمام ورودي هاي کابر رو چک کنيد.

موفق باشي. :wink:
Re: SQL Injection و مقابله با آن ...
توسط javadt در 24 شهريور 1389 - 10:30 ، پست ها: 4
تشكر از مجتبي جان بابت اين مطلب بسيار خوب
آقا يك سوال ما اگر ورودي هاي كاربرمون رو توسط دو تابع زير فيلتر كنيم كافي؟
با تشكر
کد: انتخاب همه
$user=stripcslashes($user);
$pass=stripcslashes($pass);
$user=mysql_real_escape_string($user);
$pass=mysql_real_escape_string($pass);
Re: SQL Injection و مقابله با آن ...
توسط rsh_eboy در 24 شهريور 1389 - 19:51 ، پست ها: 541
با اجازتون مجتبي سرش شلوغه من جواب بدم !
خير ! زيادهست ! :shock:
يعني تابع mysql_real_escape_string مياد و خوش چك مي كنه ببينه اگه تونست stripcslashes رو اجرا كنه اول اين تابع رو روش اجرا مي كنه و بعد اثر خودش رو ميذاره
پس شما يك مرحله اضافه هم داريد :D
البته توجه داشته باشيد كه اين فيلتر mysql_real_escape_string باعث ميشه خط جديد يا همون /n يا /r/n هم فيلتر بشه
اما كدهاي html رو هم بايد در اكثر مواقع فيلتر كنيد و نذاريد اجرا بشند...
Re: SQL Injection و مقابله با آن ...
توسط javadt در 24 شهريور 1389 - 21:24 ، پست ها: 4
rsh_eboy نوشته:با اجازتون مجتبي سرش شلوغه من جواب بدم !
خير ! زيادهست ! :shock:
يعني تابع mysql_real_escape_string مياد و خوش چك مي كنه ببينه اگه تونست stripcslashes رو اجرا كنه اول اين تابع رو روش اجرا مي كنه و بعد اثر خودش رو ميذاره
پس شما يك مرحله اضافه هم داريد :D
البته توجه داشته باشيد كه اين فيلتر mysql_real_escape_string باعث ميشه خط جديد يا همون /n يا /r/n هم فيلتر بشه
اما كدهاي html رو هم بايد در اكثر مواقع فيلتر كنيد و نذاريد اجرا بشند...


خوب ميشه بفرماييد چي كار بايد بكنم؟
من تازه كارم
Re: SQL Injection و مقابله با آن ...
توسط rsh_eboy در 26 شهريور 1389 - 23:36 ، پست ها: 541
من خودم از اين تابع استفاده مي كنم و اونطور كه مطابق ميلم بود نوشتمش! يعني من ميخواستم خط جديد رو داشته باشم
البته نه <br>

کد: انتخاب همه
function safe($value,$type='0'){
$value = trim($value);
$value = str_replace("|nline|","",$value);
$value = str_replace("|rnline|","",$value);
$value = str_replace("\r\n","|rnline|",$value);
$value = str_replace("\n","|nline|",$value);
$value = mysql_real_escape_string( $value );
$value = str_replace("|nline|","\n",$value);
$value = str_replace("|rnline|","\r\n",$value);
if($type != '1')
{
$value      = htmlspecialchars($value);
$value      = strip_tags($value);
$value       = str_replace(array("<",">","'","&#1740;","&amp;","&#1756;"),array("&lt;","&gt;","&#39;","&#1610;","&","&#1610;"),$value);
}
return $value;
}

1 , 2
صفحه اصليرايت کليکانجمن هاپروژه هاCopyright © 2005-2009 RightClick.ir All rights reserved.