PDA

View Full Version : راهنمایی جهت رفع مشکل سایت در برابر sql injection



esmaeeiilzadeh
دوشنبه 20 خرداد 1398, 14:58 عصر
سلام دوستان.وقت بخیر
من یک سایتی نوشتم که داخل صفحات از get و post استفاده میکنم. به عنوان مثالی یکی از صفحاتم به این صورت هست. www.domain.comblog.php?id=1
حالا وقتی که این id رو میگیرم و از طریق php میفرستم به فانکشنی که باهاش از دیتابیس فراخونی میکنم ولی قبلش میام با یک فانکشن دیگه که نوشتم اون مقدار id رو چک میکنم. به این صورت:
به عنوان مثال این قسمت select من هست


select * fron tbl_blog where id={$database->escape_value($id)}


حالا با تابع escape_value هم که داخل کلاس database هست میام همون مقدار id رو چک میکنم به این صورت عمل میکنه
public function escape_value($value) {
if ($this->real_escape_string_exists) {
if ($this->magic_quotes_active) {
$value = stripslashes($value);
}
$value = mysqli_real_escape_string($this->connection, $value);
} else {
if (!$this->magic_quotes_active) {
$value = addslashes($value);
}
}
return $value;
}



ولی باز با این حال مشکل sql injection دارم و یک هکری هم به ما پیام داد که دسترسی به دیتابیس های ما وجود داره و با sqlmap لیست دیتابیس های مارو فرستاده بود.
من چطوری میتونم جلوی این مشکل رو بگیرم. ممنون میشم راهنمایی بفرمایین.

peymang
دوشنبه 20 خرداد 1398, 17:06 عصر
از pdo یا mysqli استفاده کن مثل روشی که در لینک زیر هست
https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php


یا از کوئری بیلدر ها اگه می خواین خیلی سبک باشه:
مثل https://github.com/usmanhalalit/pixie


یا می توانید از orm های php استفاده کنید. داخل اونها موارد امنیتی که شامل sql injection میشه رو در نظر گرفتن
مثل : https://github.com/gabordemooij/redbean


یا از یک فریمورک که این قابلیت ها داخلش موجود باشه مثل لاراول

ali_sed
سه شنبه 21 خرداد 1398, 10:07 صبح
سلام

مطمئن شوید که real_escape_string_exists حتما true باشد و در صورتی که وجود ندارد با توجه به مشکلات امنیتی برنامه خطای فتال دهد نه اینکه به راحتی متغیر را بدون تغییری برگرداند.


مقدار را حتما در داخل "" قرار دهید.


select * fron tbl_blog where id="{$database->escape_value($id)}"


برای مقادیر عددی حتما از عدد بودن آن مطمئن شوید مثلا با عبارت $id = (int) $id;

esmaeeiilzadeh
سه شنبه 21 خرداد 1398, 14:43 عصر
سلام

مطمئن شوید که real_escape_string_exists حتما true باشد و در صورتی که وجود ندارد با توجه به مشکلات امنیتی برنامه خطای فتال دهد نه اینکه به راحتی متغیر را بدون تغییری برگرداند.


مقدار را حتما در داخل "" قرار دهید.


select * fron tbl_blog where id="{$database->escape_value($id)}"


برای مقادیر عددی حتما از عدد بودن آن مطمئن شوید مثلا با عبارت $id = (int) $id;


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


$value = stripslashes($value); $value = addslashes($value); $value = htmlentities($value); $value = mysqli_real_escape_string($this->connection, $value); return $value;

esmaeeiilzadeh
سه شنبه 21 خرداد 1398, 14:47 عصر
از pdo یا mysqli استفاده کن مثل روشی که در لینک زیر هست
https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php


یا از کوئری بیلدر ها اگه می خواین خیلی سبک باشه:
مثل https://github.com/usmanhalalit/pixie


یا می توانید از orm های php استفاده کنید. داخل اونها موارد امنیتی که شامل sql injection میشه رو در نظر گرفتن
مثل : https://github.com/gabordemooij/redbean


یا از یک فریمورک که این قابلیت ها داخلش موجود باشه مثل لاراول


الان از همین mysqli دارم استفاده میکنم
اگر بخوام از pdo استفاده کنم تمام کدهای کوِئری هام باید تغییر کنه یا فقط نوع کانکشن تغییر میکنه؟

ali_sed
سه شنبه 21 خرداد 1398, 17:09 عصر
ممنون از شما بابت راهنمایی
خب چطوری متوجه بشم که
real_escape_string_exists فعال هست و اگر نیست اررور بده؟
اینطوری هم اومدم فانکشنم رو تغییر دادم ولی باز چک کردم همچنان injection وجود داره


$value = stripslashes($value); $value = addslashes($value); $value = htmlentities($value); $value = mysqli_real_escape_string($this->connection, $value); return $value;

بر چه مبنایی می گید sql injection رخ داده لطفا کوئری های خود را لاگ کنید و کوئری مشکل دار را ارسال کنید. فقط از همین mysqli_real_escape_string استفاده کنید و بقیه را حذف کنید.

esmaeeiilzadeh
چهارشنبه 22 خرداد 1398, 08:00 صبح
بر چه مبنایی می گید sql injection رخ داده لطفا کوئری های خود را لاگ کنید و کوئری مشکل دار را ارسال کنید. فقط از همین mysqli_real_escape_string استفاده کنید و بقیه را حذف کنید.

چند روز قبل یک هکر کلاه سفید بهمون پیام داد که دسترسی به دیتابیس سایت ما وجود داره. بعد هم اومد یک عکس از دیتابیس های ما رو که با sqlmap بدست آورده بود برامون فرستاد.
بعد من هم خودم اومدم با Acunetix هم تست کردم که گفت injection وجود داره.
تمام صفحه های که مثل این بارگذاری میشه رو گفت injection هست. www.domain.com/blog.php?id=1 (http://www.domain.comblog.php/?id=1)

بعد من با این فانکشن هم از دیتابیس فراخونی میکنم.

public static function find_post_by_id($blog_id = 0) {

global $database;

$result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE
blog_id={$database->escape_value($blog_id)} LIMIT 1");

return !empty($result_array) ? array_shift($result_array) : false;
}

ali_sed
چهارشنبه 22 خرداد 1398, 09:34 صبح
$id = (int) $id; استفاده کن بعد تست بگیر. در ضمن گفتم که مقدار را بین گیومه قرار بده:



$blog_id = (int) $blog_id;
$result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE
;blog_id=\"{$database->escape_value($blog_id)}\" LIMIT 1");

esmaeeiilzadeh
چهارشنبه 22 خرداد 1398, 10:03 صبح
$id = (int) $id; استفاده کن بعد تست بگیر. در ضمن گفتم که مقدار را بین گیومه قرار بده:



$blog_id = (int) $blog_id;
$result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE
;blog_id=\"{$database->escape_value($blog_id)}\" LIMIT 1");



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

الان برای این از (int) $id استفاده کردیم. برای اون هایی که کاراکتر هستن چطور؟
مثلا یک فرم دارم طرف مشخصات و آدرس و این چیزارو میزنه. خب داخل اون باکس ها هم میشه کد تزریق کرد دیگه. اونارو چطوری کنترل کنم؟