PDA

View Full Version : یک نکته امنیتی در mysqli (عدم مقداردهی مناسب مجموعه نویسه یا کاراکتر)



abolfazl-z
یک شنبه 04 آبان 1393, 18:18 عصر
یک نکته امنیتی که برای charset وجود دارد این هست که اگر charset مورد نظر توسط api های داخلی mysqli مقدار دهی نشود به هیچ عنوان تابع mysqli_real_escape_string عمل نخواهد کرد !


<?php

$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

// Will not affect $mysqli->real_escape_string();
$mysqli->query("SET NAMES utf8");

// Will not affect $mysqli->real_escape_string();
$mysqli->query("SET CHARACTER SET utf8");

// But, this will affect $mysqli->real_escape_string();
$mysqli->set_charset('utf8');

?>

http://php.net/manual/en/mysqli.real-escape-string.php (http://php.net/manual/en/mysqli.real-escape-string.php)
http://php.net/manual/en/mysqlinfo.concepts.charset.php

eshpilen
چهارشنبه 07 آبان 1393, 01:04 صبح
فوق امنیتی؟ فکر نمیکنم!
البته درسته که راه استاندارد و توصیه شدش اینه، ولی اون روش تنظیم از طریق کوئری هم خیلی جاها استفاده میشه و به خودی خودش بطور معمول مشکل امنیتی نداره. میدونستید که تابع mysql_set_charset تازه در PHP 5.2.3 اضافه شد؟ پس قبلش آیا تمام برنامه هایی که نوشته شدن حفرهء امنیتی دارن و قابل هک هستن؟ جواب: خیر!
بنده قبلا درمورد این قضیه تحقیقاتی کرده بودم، و تاجاییکه فهمیدم، مشکل امنیتی فقط با یکسری کاراکترست های خاص بعضی زبانها مثل gbk (چینی) پیش میاد (منبع (http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string/12118602#12118602)). این مشکل با کاراکترست uft-8 پیش نمیاد، و این چیزیه که فکر کنم تقریبا همهء ما استفاده میکنیم! در بقیهء دنیا هم بنظرم دیگه کمتر برنامه نویسی باشه که بیاد و بجای استانداردهای عمومی مثل utf-8 که تمام زبانهای دنیا رو باهاش میشه ساپورت کرد از کاراکترست های اختصاصی قدیمی مثل gbk استفاده کنه.

eshpilen
چهارشنبه 07 آبان 1393, 01:13 صبح
این یک مطلبی بود که کسی توی عمقش نرفت و جزییاتش رو ندیدن، و بخاطر همین خیلی ها جار زدن که بدو بیا mysql_real_escape_string هم دیگه امنیت نداره و هک شد!
ولی عملا این حفره همونطور که گفتم شرایط خاصی میطلبه و تنها با کاراکترست های خاصی پیش میاد که چندان متداول نیستن (مگر واسه امثال همون چینی ها و ژاپنی ها با اون زبانهای عجق وجقشون!).

فرق خبره و متخصص واقعی که میره و تمام جزییات رو میخونه و بررسی و درک میکنه با بقیه علما در همین موارد مشخص میشه :لبخند:
عمرا یک نفر در کل این فروم در طول تاریخش فکر نمیکنم این کار رو کرده بود و اصلا کسی سوادش رو نداشت، ولی بنده در جریان پروژهء سیستم رجیستر و لاگین خودم بهش برخورد کردم و رفتم ته و توش رو درآوردم. سندش هم اینکه برید نگاه کنید توی فایل code_db_object.php پروژم دقیقا کامنت گذاشته بودم و اون منبع رو درج کردم.

(الان باز مهندس شهرکی میاد ابراز انزجار میکنه از این حرف زدن متکبرانه :لبخند:)

eshpilen
چهارشنبه 07 آبان 1393, 01:25 صبح
اگر charset مورد نظر توسط api های داخلی mysqli مقدار دهی نشود به هیچ عنوان تابع mysqli_real_escape_string عمل نخواهد کرد !
چرا عمل میکنه. میتونی تست کنی!
همونطور که گفتم فقط با یکسری کاراکترست های خاص یه حفرهء امنیتی پیش میاد (اونم نه اینکه بطور کلی کار نکنه و هیچ کاراکتر خاصی رو Escape نکنه بلکه از طریق یکسری مقدار خاص میتونن هک کنن).

abolfazl-z
چهارشنبه 07 آبان 1393, 13:04 عصر
در لینک http://php.net/manual/en/mysqli.real-escape-string.php که در پست بالا ویرایش شد بروید.

خودش گفته احتیاط ، امنیتی !

eshpilen
چهارشنبه 07 آبان 1393, 13:12 عصر
نگفتم امنیتی نیست، گفتم فوق امنیتی نیست!
چون بعضیا فکر میکنن و با خوندن این مطالب هم ممکنه باز اینطور القا بشه که اگر این نکته رو ندونید و رعایت نکنید 100% یه حفره امنیتی توی برنامتون باز میشه اندازه دروازه فوتبال! درحالیکه اصلا اینطور نیست و از هر هزارتا برنامه شاید یکیش چنین شرایطی داشته باشه.
همونطور که گفتم شرایط خاصی میخواد که این حفره ایجاد بشه که این شرایط در برنامه های من و شما میشه گفت هیچوقت وجود نداشته و نداره و نخواهد داشت. در سطح دنیا هم مگر فقط واسه همون زبانهای چینی و ژاپنی و چند مورد خاصش کاربرد قابل توجهی داشته بوده باشه که فکر کنم الانم کاربردش نسبت به گذشته خیلی کمتر شده باشه و اکثرا به مرور به utf-8 کوچ کرده باشن. اگر میخواید از این حفره سوء استفاده و سایت هک کنید بنظرم باید برید سراغ چینی ها و چند کشور خاص دیگه، چون اینطوری شانس معقول تری برای پیدا کردن این حفره دارید :چشمک:

abolfazl-z
چهارشنبه 07 آبان 1393, 20:28 عصر
نگفتم امنیتی نیست، گفتم فوق امنیتی نیست!
چون بعضیا فکر میکنن و با خوندن این مطالب هم ممکنه باز اینطور القا بشه که اگر این نکته رو ندونید و رعایت نکنید 100% یه حفره امنیتی توی برنامتون باز میشه اندازه دروازه فوتبال! درحالیکه اصلا اینطور نیست و از هر هزارتا برنامه شاید یکیش چنین شرایطی داشته باشه.
همونطور که گفتم شرایط خاصی میخواد که این حفره ایجاد بشه که این شرایط در برنامه های من و شما میشه گفت هیچوقت وجود نداشته و نداره و نخواهد داشت. در سطح دنیا هم مگر فقط واسه همون زبانهای چینی و ژاپنی و چند مورد خاصش کاربرد قابل توجهی داشته بوده باشه که فکر کنم الانم کاربردش نسبت به گذشته خیلی کمتر شده باشه و اکثرا به مرور به utf-8 کوچ کرده باشن. اگر میخواید از این حفره سوء استفاده و سایت هک کنید بنظرم باید برید سراغ چینی ها و چند کشور خاص دیگه، چون اینطوری شانس معقول تری برای پیدا کردن این حفره دارید :چشمک:


میشه بیشتر توضیح بدهید ؟

eshpilen
چهارشنبه 07 آبان 1393, 23:14 عصر
توضیحش توی این منبع که قبلا گذاشتم هست: http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string/12118602#12118602

همچنین در این منبع: http://www.shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

در هر دوی این منابع اگر دقت کنی به کاراکترست GBK (http://en.wikipedia.org/wiki/GBK) اشاره شده که مال زبان چینی است!

البته GBK رو بعنوان یک مورد مثال انتخاب کرده و چند کاراکترست خاص دیگر هم هستن که میتونن در این حمله مورد استفاده قرار بگیرن.

وقت ندارم همش رو ترجمه کنم اما ترجمه بخشی از منبع اول رو میذارم:


For this attack to work, we need the encoding that the server's expecting on the connection both to encode ' as in ASCII i.e. 0x27 and to have some character whose final byte is an ASCII \ i.e. 0x5c. As it turns out, there are 5 such encodings supported in MySQL 5.6 by default: big5, cp932, gb2312, bgk and sjis. We'll select gbk here.



ترجمه: «برای اینکه این حمله کار کند، ما به انکدینگی که سرور انتظار دارد نیاز داریم که هر دوی این ویژگیها را داشته باشد: کاراکتر کوتیشن تکی را همچون ASCII انکد کند (یعنی 0x27) و کاراکتری داشته باشد که بایت آخر آن یک بک اسلش اسکی باشد. 5 تا از چنان انکدینگ هایی در MySQL 5.6 بطور پیشفرض پشتیبانی میشوند: big5, cp932, gb2312, gbk , sjis. ما در اینجا gbk را انتخاب میکنیم.»

نکته اینکه ظاهرا همهء این کاراکترست ها جز sjis که مال زبان ژاپنی است برای زبان چینی هستن!

تا زمانی که شما از یکی از این انکدینگ ها در برنامه استفاده نکرده باشی و دستوری مثل mysql_query('SET NAMES gbk');‎ در برنامت نداشته باشی، در برابر این حمله مصون هستی. فکر نمیکنم هیچکدام از برنامه نویسان وطنی تاحالا از این کاراکترست ها استفاده کرده باشن؛ بنظرم اگر هم کسی نیاز داشته باشه زبان چینی یا ژاپنی رو ساپورت کنه احتمال زیاد با utf8 کار میکنه.

abolfazl-z
پنج شنبه 08 آبان 1393, 10:33 صبح
حرف شما کاملا متین.

ولی چرا خود مرجع php.net اشاره ایی به این موضوع نکرده ؟

eshpilen
پنج شنبه 08 آبان 1393, 22:39 عصر
سایت PHP راجع به زبان PHP است و مرجع مسائل امنیتی نیست. در زمینهء امنیت خیلی چیزها و جزییات و نیازها هست که در سایت PHP پیدا نمیشه. فقط یکسری موارد عمده و مهم و کلی و نکاتی رو که جا داره و میشه توی صفحات رفرنس و جای دیگه سایتش بهشون اشاره کرد در سایت PHP پیدا میکنید. بحث امنیت جدای از خود زبان و برنامه نویسی عمومیه و تخصص و رفرنس و سایت های مخصوص خودش رو میطلبه. اگر بخوان همهء مسائل امنیتی رو با تمام جزییات در سایت PHP درج کنن که اولا برفرض تخصص و وقتش رو داشته باشن، سایتشون میترکه و خیلی حجیم و پیچیده و سردرگم کننده میشه احتمالا؛ مگر اینکه یک بخش مخصوص امنیتی جداگانه توش بذارن.

اون مطلبی هم که در این مورد گفته خب خیلی کلی و مختصر اشاره کرده و حرف درستی زده و نیاز آنچنانی نبوده که وارد جزییاتش بشه چون چیز مشخص و روشن و ساده ای هست انجامش و اصولیش اونطوره و کافیه برنامه نویسان اون رو رعایت کنن تا ریسک اونطور حملات وجود نداشته باشه. نیازی نداشتن بیش از این وارد جزییاتش بشن و کلی تفسیر و توضیح بنویسن که آخرش هم خیلی از کاربران رو ممکنه گیج سردرگم بکنه (گذشته از اینکه خوندن و فهمیدن اینطور مطالب و جزییات حمله های ظریف امنیتی تخصص و وقت میخواد و فکر نکنید چون سایت PHP است و توسعه دهندگان و برنامه نویسان PHP هستن حالا همچین افرادی همینطوری و به این راحتی بینشون پیدا میشه و دارن اونجا پرسه میزنن و پست میدن توی سایت!). بنده هم چیزی خلاف اون مطلب نگفتم، فقط خواستم توضیح بدم که اون حفره و خطر اونطور و در اون حد که ظاهرا برمیاد و از عنوان و نوشته های پست شما هم برداشت میشه عمومی نیست و درواقع در عمل کمیابه و شرایط خاصی میخواد (البته از دید مثلا یک برنامه نویس چینی توی چین مسلما احتمال خیلی بیشتره!) و حالا اگر کسی تاحالا از اون روش غیرتوصیه شده برای ست کردن انکدینگ کانکشن دیتابیس استفاده کرده فکر نکنه که ای وای فاجعه شده و الان همه برنامه هاش مثل آبکش سوراخ هستن! خواستم بگم نه اتفاقا احتمال اینکه برنامه شما به این خاطر آبکش شده باشه خیلی کمه! ولی همچنان از توصیهء امنیتی و روش و تابع صحیح که در سایت رسمی PHP هم گفته استفاده کنید، چون روش اصولی و بدون هیچ ریسکی اونه و به این شکل برای آینده و اتفاقات پیشبینی نشده و حمله های جدیدی که ممکنه بنوعی کشف بشن و بوجود میان هم خیالتون راحتتره طبیعتا.