آموزش های این وب سایت به صورت رایگان در دسترس است. اطلاعات بیشتر
بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]

هک به روش sql injection و نحوه ی جلوگیری از آن - مرجع کامل

مجتبی یگانه  12 سال پیش  11 سال پیش
+27 0

چرا اغلب برنامه های ما  به روش SQL Injection ، یا نفوذ از طریق پایگاه داده ، آسیب پذیر هستند ، و چطور این مشکل رو حل کنیم ؟

0 0
مرسی ALU واقعا زحمت کشیدی (12 سال پیش)
 برای این سوال 7 پاسخ وجود دارد.
پاسخ به سوال 
مجتبی یگانه  12 سال پیش
+13 0

من قبلا به چند تا از دوستان قول داده بودم و حالا به قولم عمل میکنم و توضیح نسبتا کاملی در این مورد میدم

در حالت کلی ، این باگ مربوط به php هست ،  برای درک بیشتر ، این نوع حمله رو روی سرور لوکال خودم پیاده کردم

در تصویر زیر حالت عادی استفاده از فایل php یا وبسرویس رو توسط یک کاربر عادی می بینیم

اما اگر کاربر ما ، یه کم شیطنت به خرج بده ، متوجه خطا میشه مثل تصویر زیر که این کار با اضافه کردن '  (تک کوتیشن ) انجام میشه

مثل تصویر زیر ، یه در واقع این ساده ترین روش برای تشخیص این باگ هست

 این که چه اتفاقی میوفته که باعث ایجاد یک خطای sql میشه رو باید توی کد php  من برسی کرد

(وقتی پاسخ طولانی بشه ، متن رو نشون نمیده پس چند قسمت میکنم)

پاسخ به سوال 
مجتبی یگانه  12 سال پیش
+11 0

<?php
if(isset($_GET['id']))
{  $c
 mysql_select_db("test");
 $command = mysql_query("SELECT * FROM test Where id =".$_GET['id'],$conn);
 
 
 
 if($command){
 
  while($row=mysql_fetch_array($command))
  {
   echo"<pre>";
   echo "ID   => ".$row['id']."<br>";
   echo "Name => ".$row['name']."<br>";
   echo "Age  => ".$row['age']."<br>";
   echo"</pre>";
  }

 }
 else{
  echo mysql_error();
 }
}
?>

در کد بالا ، اول چک میشه ببینه ، آیا کاربر متغییر id رو با URL (آدرس صفحه) فرستاده یا نه ، اگه نه کد هیچی نشون نمیده ، اگه فرستاده باشه که میره و اون ایدی رو در دیتابیس با کوئری زیر چک می کنه

SELECT * FROM test Where id =1 '

چون ما هیچ کار امنیتی خاصی روی ورودی انجام نمیدیم ، تک کوتیشن هم وارد دستور میشه ، و چون استفاده بی مورد هست ، یعنی بسته هم نشده ، یک خطا Sql ایجاد میکنه و باعث میشه ما بفهمیم این صفحه آسیب پذیر هست ،  خطراطی که توی این حالت ممکنه ما رو تهدید کنه عبارتند از :

  • خطر دسترسی به همه ی اطلاعات جدول ها
  • خطر دسترسی به همه ی اطلاعات سایر جدول ها ( و سایر دیتابیس ها در صورتی که کد نویسی افتضاح باشه :| )
  • خطر دسترسی به سایت به عنوان مدیر ( وقتی username password رو داشته باشه ، دیگه کاری نداره ، البته پسورد معمولا با md5 وSHA1 و .. کد میشه ولی با یه ابررایانه میشه ، پیداش کرد ، یا اگر ساده باشه که دیگه راحت تر)
  • خطر ویرایش اطلاعات
  • خطر پاک کردن اطلاعات
  • خطر پاک کردن جدول
  • خطر پاک کردن دیتابیس
  • و... (خیلی چیزایی که من نمیدونم یا حضور ذهن ندارم :|  )

تو این شرایط هر انسان عاقلی قبل از کدنویسی سمت سرور و دیتابیس ، باید کد سمت سرورش رو امن کنه

در ادامه یک نمونه نفوذ ساختگی رو سرور لوکال خودم پیاده میکنم

پاسخ به سوال 
مجتبی یگانه  12 سال پیش
+12 0

در تصویر زیر ، تونستم ورژن ، نام کاربری ، و نام دیتابیس روبدست بیارم که اطلاعات پایه برای این نوع نفود هست

کدی که برای این کار استفاده کردم ، بر میگرده به ترکیب دستور انتخاب (union select) که در قسمت url در تصویر میتونید ببینید 

(البته قبلش باید یک سری کار ها انجام بشه ، مثلا اینکه جدول چند تا ستون داره و چه ستون هایی در صفحه چاپ میشه ، که چون مبحث ما هک نیست ، نیازی به توضیحش نمی بینم ، ولی خوب واضحه دیگه)

اینم یه نمونه از اون چیزایی که گفته بودم :|  ، نمایش تمام اطلاعات دیتابیس ،

توجه کنید که در طول این آموزش ، کد php به هیچ وجه تغییری نکرده ، و فقط url های ورودی متفاوت است ، و می تونید ، خودتون سورس php رو امتحان کنید

پاسخ به سوال 
مجتبی یگانه  12 سال پیش
+12 0

نحوه ی امن کردن سورس php

استفاده از توابع و روش ها  بر حسب نوع ورودی و میزان احتمال نفود انجام میگیرد ، پس شما باید بر اساس توضیحات این ، چند مورد رو انتخاب کنید تا کدتون امن بشه

  1. کست کردن به int برای ورودی های عددی
  2. عوض کردن نوع داده برای ورودی های عددی با دستور ctype_int()    z
  3. استفاده از mysql_real_escape_string که روش پیشنهادی خود PHP.net هست ، به نظر خودشون کامله ، اما نقظه ی ضعفی رو مقدار های منظقی داره که خودشونم قبول نمیکنن :|  ، برای امن کردن کامل مقدار های عددی کافیه از یک کست به int بعد از استفاده از این تابع استفاده کنید
  4. تابع های دیگه ای هم مثله addslash , str_replace هم هست ، اما دیگه با وجود mysql_real_escape_string الزامی برای استفاده ازش نیست  ، به هر حال برای جامع بودن نمونه سورسش رو میزارم
  5. این مورد رو در نظر داشته باشید که استفاده از REQUEST به جای POST ,GET کاری ناشیانه ست ،
  6. اشتباه بیشتر افراد این هست ، که متد POST ، آسیب پذیر نیست که یک عقیده ی اشتباه رایج هست ، حتی داده هایی که در دیتابیس هستند ، میتونن باعث ایجاد این نوع حملات بشن
  7. قرار دادن دو تک کوتیشن قبل از متغییر در کوئری ، باعث امن تر شدن کد میشه ، که در کد اصلاح شده ، تغییر اعمال شده
$id=$_GET['id'];

$casted  = (int) $id;
$ctype = ctype_digit($id);
$realScape = mysql_real_escape_string($id);
$replaced = str_replace("'","''",$id);
$slashes = addslashes($id);

و در نهایت باید ، کد اول خودم رو امن کنم ، کد امن شده به این شکل خواهد بود ، قسمت های جدید در کد مشخص شده اند

         // در این کد استفاده از 
// mysql_real_scape_string
// و کست به اینت کافی بود ، چرا که ورودی عددی است $id=$_GET['id']; echo "id befor escape is :".$id."
"; $id=mysql_real_escape_string($id); echo "id after real escape is :".$id."
"; $id=(int)$id; echo "id after cast to int is ; ".$id."
";
$query="SELECT * FROM test Where id = ' " . $id . " ' "; // مورد هفتم رعایت شده است
//////////////////////// end of new codes /////////////////////////
$command = mysql_query($query,$conn); if($command){ while($row=mysql_fetch_array($command)) { echo"<pre>"; echo "ID => ".$row['id']."<br>"; echo "Name => ".$row['name']."<br>"; echo "Age => ".$row['age']."<br>"; echo"</pre>"; } } else{ echo mysql_error(); } } ?>

در نهایت هم تصویر از خروجی امن شده ، با همون url ای که باعث شد ، همه ی اطلاعات به نمایش در بیان میزارم ، که بعد از اسکیپ و گرفتن مقدار عددی ، فقط مقدار عددی رو میگیره که یک هست ، در نتیجه ، فقط آیتم اول نمایش داده میشه

اینم سورس ساخت جدول برای دوستانی که میخوان تست کنن ، این کد رو بعد از ساخت دیتابیسی به نام test در قسمت sql اجرا کنید

 CREATE TABLE IF NOT EXISTS `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(60) CHARACTER SET utf8 NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci;
0 0
تشکر از توضیحات کاملت (12 سال پیش)
0 0
خیلی خوب بود ،لطفا به اموزشتون ادامه بدید (12 سال پیش)
+1 0
توضیحات برای دیباگ این نو حمله کافیه ، و بیشتر از این ، اونم به فارسی ، گیرتون نمیاد ، به نظرم جزو معدود توضیحات کامل توی نت هستش ، اما اگر منظورتون حمله ی دیگه ای هست ، توی برنامه نویسی اندروید خیلی پیش نمیاد ، مگر اینکه کاربر از یه کلاینت جعلی ، استفاده کنه ، در این مورد هم نسخه های جدید php امن شدن ، وحای نگرانی ، برای موقعیت فعلی ما به عنوان یه برنامه نویس جاوا نیست (12 سال پیش)
0 0
[اسپم] نیستی؟! من این هم خوشبختی محاله! محاله! :D ||(جنبه داشته باش)|| زود برگرد. (12 سال پیش)
0 0
:)) ، اگه نت گیر بیاد از راه دور هندل میکنم :) ، خوش باشید (12 سال پیش)
0 0
ممنون بابت توضیحات خوبت، اتفاقا امروز داشتم به همین موضوع فکر میکردم :) (12 سال پیش)
0 0
خیلی خوب بود ، منابع آموزشی خوبی هم اگر در همین مورد سراغ دارید به ته آموزش اضافه کنید ، بحث امنیت و... (12 سال پیش)
0 0
خیلی خوب بود ، منابع آموزشی خوبی هم اگر در همین مورد سراغ دارید به ته آموزش اضافه کنید ، بحث امنیت و... یه پیشنهاد برای استاد :) یه ویدیو هم در همین مورد امنیت برنامه در اندروید و ارتباطات بین سرور و کلاینت تهیه کنید . با تشکر (12 سال پیش)
0 0
دمت گرم . توضیحات خیلی خیلی خوبی بود. (12 سال پیش)
0 0
جالب بود فقط چند سوال فنی (12 سال پیش)
پاسخ به سوال 
imanbenoit  12 سال پیش
0 0

مهندس جان  سلام

1- اگه  طرف  از متد post استفاده کنه  بازم با این injection  میشه بهش  وارد شد؟؟؟

2-  اگه ما بعنوان برنامه نویس بیاییم  و  نام فیلد های  دیتا بیس مون رو  یه چیز مشخص نزاریم  مثلا   بجای ID بنویسم Somarende

بازم   کسی  میتونه بیاد یه دستور بنویسه و اطلاعات مارو بخونه؟؟؟

چون توی عکس های اولی که گذاشتین طرف اسم یکی از فیلد ID رو نوشته  بعد وارد شده خب اگه ما ایدی نداشت باشیم  اون از کجا میخاد چیزی رو بخونه؟؟

پاسخ به سوال 
مجتبی یگانه  12 سال پیش
+5 0

در پاسخ به سوال imanbenoit 

  1.  تو متن گفتم ، sql Injection به نحوه ی دریافت ورودی ربطی نداره ، یعنی حتی داده ای که در دیتابیس ذخیره شده ، بسیار زیاد در برابر نفوذ به این روش آسیب پذیره ، و دقیقا نکته ای هست که بسیاری از افراد رعایت نمی کنن و سایتشون از این جهت آسیب پذیره ، متد های زیادی از این نوع حمله وجود داره ، که حمله از طریق داده های ذخیره شده در دیتابیس یکی از اونهاست 
  2. خوب فرض رو بر این بگیریم که داده های ورودی در فیلد هایی با اسم های غیر مرتبط هست ، حالا امکانش هست هک بشیم ؟ بله ، چطوری !

 2-1 وقتی سایت آسیب پذیر باشه ، امکان فیلتر و جست و جو بین نام جدول ها ، و پیدا کردن نام ستون ها ، از طریق روش های مختلفی هست ، حتی جست و جو بین نام ستون ها با دستوری مثل like 'admin' z

 2-2 فرض رو بر این بگیریم ، شما همه ی داده ها رو پست می کنید و از روش get استفاده نمی کنید (که عملا غیر منطقی هست و کار برنامه نویسی رو خیلی وقت ها سخت تر و سخت تر میکنه ) ، ابزار هایی مثل پلاگین های فایرفاکس هستند که فقط کلیدی که به صفحه پست شده رو برمیگردونه ، پس اینم قابل نفوذ با یک اپلیکیشن مثلا تحت جاوا هست که مقدار  و کلید ها رو  به صفحه پست کنیم

3.  اگر ما ایدی نداشتیم ، از کجا می خواد چیزی رو بخونه ؟؟ 

- واضح هست که این نوع استفاده ضروریه ، حتی توی همین صفحه در قسمت URL  یک ایدی با مقدار 1136 get میشه (احتمالا ، ممکنه منم اشتباه کنم دیگه D: )  ، اما علت اینکه چرا مثل کدی که من نوشتم نیست چیه ؟  در واقه این صفحه میتونست کدی مثل این داشته باشه  

question ?questi>

اما به دلیل اینکه رو امنیت uncocoder مانور های خوبی داده شده ، با یک کد htaccess در php ایجاد یک ساختار دلخواه ممکنه ، که در واقع میشه این  

answers.uncocoder.com/question/1136

که با یک مرحله ی انحرافی ، عنوان صفحه به url اضافه میشه ،  پس عملا همیشه راه نفوذ اون شکلی نیست که تو عکس هست :|

0 0
میشه یه کلاس جامع php هم بزارید ... من یکی حاضرم 50 هزار تومن پول بدم واسه اموزشهاش (12 سال پیش)
0 0
آقا مجتبی دمت گرم فوق العاده بود :) من هم حاضرم در کلاس با هر هزینه ای که باشه شرکت کنم . (11 سال پیش)
پاسخ به سوال 
کاشی زاده  11 سال پیش
+6 0

روشی امن ، سریع و آسان برای ارتباط با دیتابیس 

خُب دوستانی که میترسن سرورشون دچار حملات اینجکشن بشه ، راه های مختلفی برای مبارزه باهاش وجود داره .

یکی از راه های جلوگیری از اینجکشن طبق گفته های عزیزان استفاده از کست اینتیجر هست .

این راه جلو اینجکشن رو میگیره ولی پروژه شما رو کثیف میکنه اصطلاحا dirty code و از پروژه شما یه جور اسپاگتی میسازه.

راه بهتر استفاده از پروسیجر (Stored Procuder) هست .

پروسیجر (Stored Procuder) چیست ؟

به طور خلاصه Stored Procuder یک قسمت از بانک های اطلاعاتی sql server هست که در اون میشه دستورات select,insert,delete و... را در اون نوشت و با استفاده از پارامتر های ورودی یا خروجی می شه اطلاعاتی از اون گرفت یا به آن داد.

مزایای استفاده از پروسیجر چیست ؟

*- با استفاده از Stored Procuder می توانیم به میزان قابل ملاحضه ای Performance و بازدهی Query ها را بیشتر کنیم، با اولین باری که یک Procedure اجرا می شود، MySql یک Execution Plan (نقشه ی اجرایی) برای آن ایجاد می کند و در اجراهای بعدی با استفاده از همان EP اقدام به اجرای Stored Procuderمی نماید و در نتیجه بازدهی و سرعت Query بالاتر می رود.

*- استفاده از SP علاوه بر اینکه در نگهداری و ارائه ی داده های دیتابیس به ما کمک می کند، لازمه برنامه نویسی چند لایه (Multi-Tier Programming) نیز محسوب می شود. Stored Procuder های دیتابیس لایه دیتا (Data Layer) در برنامه نویسی سه لایه (three-tier programming) می باشد.

*- درصد امنیت داده ها در کار با دیتابیس بیشتر می شود، زیرا MySql این امکان را دارد تا برای هر SP تنظمیات امنیتی (Security Setting) جداگانه در نظر بگیریم.

*- کوئری های نوشته شده در php از نظر امنیتی ضعیف بوده و سایت را در برابر حملات موسوم به SQL Injection Attack آسیب پذیر می کنند.

*- استفاده از SP و جدا کردن SQL Logic از کد php باعث می شود تا مدیریت کدها راحت تر باشد، قطعا فراخوانی یک StoredProcedure بسیار راحتر و منطقی تر از ایجاد کوئری با چسباندن چندین String بهم می باشد.

 

خوب موارد بالا به صورت کتابی بود که از یک سایت ترجمه شده بود .

ولی به صورت خودمونی بخوایم بگیم میشه این :

شما با استفاده از پروسیجر سرعت انجام عملیات در وب سرویس رو بالا میبرید و مشکل اینجکشن رو هم حل میکنید .

حالا اینکه این پروسیجر چطوری اینکارا رو میکنه و چطوری میشه استفاده کرد رو براتون تو تاپیک مجزا میذارم

 

تاپیک ساخته شد : لینک 


پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .