PDA

View Full Version : یک نکته مهم درمورد SQL Injection و mysql_real_escape_string



eshpilen
جمعه 05 خرداد 1391, 19:24 عصر
من خودم چون از یک کلاس و تابعی که خودش این موارد رو هندل میکنه استفاده میکنم، دیگه این مسئله زیاد جلوی چشمم نیست و وقتی افراد از SQL Injection و mysql_real_escape_string صحبت میکنن حضور ذهن ندارم تا این نکته رو بهشون یادآوری کنم. ولی الان به ذهنم اومد و گفتم شاید خیلی مبتدی ها این قضیه رو نمیدونن یا به راحتی ازش غفلت میکنن.

اون نکته چیه؟

نکته اینه که تابع mysql_real_escape_string برای Escape کردن داده های رشته ای که موقع درج در کوئری توی کوتیشن میذاریم کارایی داره. اما درمورد داده های عددی که در کوتیشن نمیذاریم امنیت نمیده.

مثلا:


<?php

mysql_connect('', 'root', '');

$input='4 or 1=1';

echo mysql_real_escape_string($input);

?>

خروجیش:

4 or 1=1

فرض کنید متغییر input ورودی کاربر هست که حالا از طریق GET یا POST دریافت شده.
اینجا با وارد شدن عبارت 4 or 1=1 با اینکه ما اون رو از mysql_real_escape_string عبور دادیم اما مشاهده میکنید که رشتهء ورودی عملا هیچ تغییری نکرده و بنابراین اگر ما ورودی کاربر رو همینطور در یک کوئری ترکیب کنیم، عبارت وارد شده بعنوان دستورات SQL تفسیر و اجرا میشه.

مثلا کوئری:


select * from table1 where id=$input

عملا تبدیل میشه به:


select * from table1 where id=4 or 1=1

که مسلما اون چیزی نیست که ما میخوایم.

خلاصه این نکته رو باید همیشه مد نظر داشته باشید.

البته میتونید بجاش همیشه از یک تابعی مثل این استفاده کنید:


function quote_smart($value) {

if(is_numeric($value)) return $value;

if(get_magic_quotes_gpc()) $value = stripslashes($value);
return "'" .mysql_real_escape_string($value) . "'";

}

این تابع اول بررسی میکنه که آیا مقدار وارد شده یک عدد است و اگر عدد بود همونطور دست نخورده اون رو برمیگردونه، ولی اگر عدد نبود اون رو بوسیلهء mysql_real_escape_string اسکیپ میکنه. ضمنا دوتا کار مفید دیگه هم انجام میده:
1- اگر magic_quotes_gpc روشن باشه اثر اون رو خنثی میکنه تا رشتهء ورودی Escape مضاعف نشه.
2- بعد از Escape کردن ورودی اون رو داخل کوتیشن هم قرار میده و برمیگردونه؛ یعنی خروجی این تابع برای درج در کوئری آماده است و دیگه لازم نیست و نباید شما اون رو داخل کوتیشن بذارید.

حالا همون مثال رو با این تابع جدید بررسی میکنیم:


<?php

function quote_smart($value) {

if(is_numeric($value)) return $value;

if(get_magic_quotes_gpc()) $value = stripslashes($value);
return "'" .mysql_real_escape_string($value) . "'";

}

mysql_connect('', 'root', '');

$input='4 or 1=1';

echo quote_smart($input);

?>

خروجیش:

'4 or 1=1'

حالا مشاهده میفرمایید که درسته رشتهء ورودی ما تغییری نکرده، اما چون توسط این تابع در کوتیشن قرار گرفته دیگه بعنوان دستور SQL تفسیر نمیشه و نهایتا منجر به یک خطای سینتاکس MySQL میشه و نه چیز دیگه. یعنی خطری برای سایت نداره.

البته بنده نمیگم که این تابع لزوما برای هر کاری مناسبه و روشهای دیگر یا دستی خودتون رو بکار نبرید، ولی این تابع حداقل برای منکه کار رو خیلی راحت کرده تاحالا. ضمنا این تابع رو خودم ننوشتم و از منبع دیگری برداشت کرده بودم. البته برای کار خودم مقداری تغییر درش داده بودم و مثلا چون magic_quotes_gpc رو خودم در جای دیگری برای تمام داده های GPC (به معنای GET, POST و COOKIE) خنثی میکنم اون خط if(get_magic_quotes_gpc()) رو درش حذف کرده بودم.

خلاصه حواستون به داده های عددی که داخل کوتیشن قرار نمیگیرن باشه. mysql_real_escape_string وقتی اثر میکنه که داده ها در کوئری در کوتیشن محصور بشن.

البته شما میتونید داده های عددی رو بصورت جداگانه ولیدیت کنید. یعنی قبل از درج در کوئری چک کنید که دقیقا فرمت یک عدد رو داشته باشن و هیچ چیز دیگری درشون نباشه. همونطور که در این تابع quote_smart مشاهده میکنید میشه با تابع is_numeric این مسئله رو براحتی چک کرد. البته این تابع اعداد اعشاری رو هم قبول میکنه، ولی بهرحال یک عدد اعشاری هم خطر SQL Injection نداره.

ضمنا فراموش نکنید SQL Injection فقط بخشی و یک نوع از ملاحظات امنیتی هر برنامه ای است. خیلی چیزها هست که به منطق و جزییات خود برنامه برمیگرده و برنامه نویس خودش شخصا میتونه تشخیص بده و هندل کنه. مثلا یه وقتی هست باید چک کنید که ورودی وارد شده علاوه بر اینکه یک عدد هست باید در محدودهء خاصی باشه یا از بین چند عدد خاص باشه یا کاربر جاری اجازهء دسترسی رو داشته باشه و غیره. اینا کار خودش شما هست و هیچ تابعی علم غیب نداره و این کارها رو نمیتونه بصورت خودکار برای شما انجام بده.

lady64
جمعه 05 خرداد 1391, 19:53 عصر
ممنون از مطلب خوبتون . چند سوال در این راستا :
1. شما میفرمائید برای داده های عددی که در کوتیشن نمیذاریم امنیت نمیده.(mysql_real_escape_string) . این درست که برای داده های عددی کوتیشن نمیزاریم ولی اگر هم بزاریم خطایی صورت نمیگیره . میخوام بدونم کوتیشن گذاشتن برای داده های عددی که خطا هم نمیده از لحاظ منطقی و اجرایی چه ایرادی داره ؟
2. از این توابع امنیتی فقط در مواقع درج در پایگاه استفاده میشه یا برای select ، update و .. هم استفاده میشه ؟ ( البته بنظرم باید استفاده بشه ، جهت اطمینان !!)
3. این توابع فقط برای داده هایی که از کاربر دریافت میشن استفاده میشه ؟
4. اگر متغیری قرار نباشه در کوئری قرار بگیره نیازی به استفاده از توابع امنیتی هست ؟ مثلا دریافت بوسیله ی get برای حرکت بین صفحات

eshpilen
جمعه 05 خرداد 1391, 20:21 عصر
ممنون از مطلب خوبتون . چند سوال در این راستا :
1. شما میفرمائید برای داده های عددی که در کوتیشن نمیذاریم امنیت نمیده.(mysql_real_escape_string) . این درست که برای داده های عددی کوتیشن نمیزاریم ولی اگر هم بزاریم خطایی صورت نمیگیره . میخوام بدونم کوتیشن گذاشتن برای داده های عددی که خطا هم نمیده از لحاظ منطقی و اجرایی چه ایرادی داره ؟

اتفاقا بنده هم این مورد کوتیشن گذاشتن برای داده های عددی مد نظرم بود و میخواستم مطرح کنم، ولی دیگه حس و حالش نبود و تست و اینا باید میکردم.
بله اینم میشه که همیشه حتی برای داده های عددی هم کوتیشن بذارید. ولی خب این یه مقدار استاندارد و جالب شاید نباشه. مثلا همون تابعی که بنده گذاشتم خودش بصورت خودکار چنین کاری انجام نمیده. یعنی میخوام بگم لزوما همهء افراد و همهء کدها همیشه از این رفتار تبعیت نمیکنن و اون رو درنظر نمیگیرن و این میتونه مشکل سازگاری و امنیتی ایجاد کنه در موارد مختلف بخصوص وقتی کدهای مختلف با هم ترکیب میشن. بنابراین بنظرم بهتره یک روش منعطف تر و مستحکم تر و سازگارتری داشته باشیم که کمترین وابستگی و ابهام و امکان خطا رو داشته باشه.


2. از این توابع امنیتی فقط در مواقع درج در پایگاه استفاده میشه یا برای select ، update و .. هم استفاده میشه ؟ ( البته بنظرم باید استفاده بشه ، جهت اطمینان !!)هر وقت داده هایی که ممکنه توشون چیزهای خطرناک باشه رو میخواین در یک کوئری بکار ببرید. فرقی نمیکنه کوئری select باشه یا insert و غیره.


3. این توابع فقط برای داده هایی که از کاربر دریافت میشن استفاده میشه ؟هر داده ای که امکان داره کاراکترها یا عبارات خطرناک یا مشکل زا درش باشه.
از سمت کلاینت که هرچیزی میاد جزو این داده های غیرقابل اعتماده. GET POST COOKIE UserAgent و حتی هدرهای HTTP. همشون قابل جعل هستن. تقریبا هرچیزی که منشاء اون کلاینت است و اونجا تولید میشه.

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

ضمنا هروقت صحبت از استفاده از چیزهایی مثل mysql_real_escape_string میشه منظور فقط جلوگیری از چیزهای خطرناک و عمدی نیست، خیلی وقتا داده ها بصورت طبیعی یا تصادفی ممکنه حاوی کاراکترها و عبارات خاصی باشن که همینطوری اگر در کوئری درج کنید ایجاد مشکل سینتاکس میکنن یا در بعضی موارد گرچه کم احتمال ممکنه باعث تغییر تصادفی کوئری و ایجاد خسارت بشن.


4. اگر متغیری قرار نباشه در کوئری قرار بگیره نیازی به استفاده از توابع امنیتی هست ؟ مثلا دریافت بوسیله ی get برای حرکت بین صفحات
تابع mysql_real_escape_string فقط برای درج در کوئری هاست. اگر نمیخواید در کوئری درج کنید نیازی به استفاده از این تابع هم نیست. اما این به این معنا نیست که ملاحظات امنیتی دیگری بسته به برنامه و شرایط ممکن نیست وجود داشته باشن و همینطوری هر داده ای رو باید پذیرفت و بر طبق اون عمل کرد.

مثلا حرکت بین صفحات اگر بعضی صفحات محرمانه هستن یا عملیات خاصی انجام میدن که فقط افراد خاصی باید مجاز به انجام اونها باشن، طبیعتا قبل از اجرای اونها داده های ورودی و کاربر باید ولیدیت و احراز هویت بشن.
یک وقت هست شاید من بر اساس id خاصی که در URL میاد فایل خاصی رو Delete یا Overwrite میکنم؛ در این موارد نباید همینطور هر id ای رو از هرکسی قبول کرد.
خلاصه موارد امنیتی چیزی نیست که یکسری فرمول کلی و کلیشه ای محدود داشته باشه. امنیت یعنی در هرموردی فکر کنی چطور ممکنه اون سیستم مورد سوء استفادهء عمدی و غیرعمدی قرار بگیره. ضمنا اصول حرفه ایش هم اینه که نباید از «امنیت از طریق تیرگی» بعنوان یک راهکار اصلی امنیت استفاده بشه. یعنی باید فرض رو بر این گذاشت که یک هکر با انگیزه و با سواد و مصمم که وقت و ابزار و منابع کافی در دسترس داره و کدمنبع برنامهء ما رو هم داره و تمام الگوریتم و روش کار و جزییات اون رو عمیقا میدونه و درک کرده میخواد به سیستم حمله کنه. چه با قصد سرقت اطلاعات و چه با قصد تخریب و مشکل آفرینی و غیره.
البته اهمیت هر موردی خب طبیعتا به پارامترهای دیگر سیستم و اهمیت و ارزش اون هم برمیگرده و نباید روی همه چیز به یک حد وسواس داشت و هزینه کرد. ولی نباید در این مورد خوشبینی و فرضهای بی پایه داشت و مثلا فرض کنیم که چنین افرادی نیستن و نخواهند بود. بلکه باید بدترین شرایط رو هم درحال و آینده پیشبینی کرد و مد نظر داشت حتی الامکان با منابعی که داریم. طبیعتا به محتملترین و مهمترین موارد اولویت داده میشه. یعنی مواردی که مثلا درصورت وقوع خسارت اونها بیشتره یا مواردی که احتمال وقوع و انگیزهء ارتکاب اونها زیاده، افراد زیادی منابع و امکان پرداختن به اون حمله ها رو دارن و غیره.

Unique
جمعه 05 خرداد 1391, 20:56 عصر
حیفم اومد حالا که eshpilen انقدر زحمت کشیده من چیزی به این مطالب اضافه نکنم .
مواقعی که دارین یک مقدار عددی را توی اسکریپت ها استفاده میکنید اولا حتما با استفاده از توابعی مثل is_numeric یا بهتره از ctype_digit استفاده کنید.
بعدش هم میتونید از sprintf استفاده کنید که حتی اگه عددی بودنش هم چک نشده باشه sql injectionرا از بین میبره :


sprintf("select * from table1 where id='%d'",$input);

colors
جمعه 05 خرداد 1391, 21:06 عصر
درود

ممنون از eshpilen (http://barnamenevis.org/member.php?148005-eshpilen) عزیز

من قبلا تو چندتا از پروژهام از تابع زیر استفاده کردم. به نظرت چطوره؟


function Safe($str){
$str = htmlspecialchars(trim($str));
if(! get_magic_quotes_gpc() ) {
$str = addslashes($str);
}
return mysql_real_escape_string(stripslashes($str));
}

eshpilen
جمعه 05 خرداد 1391, 21:08 عصر
امنیت چیزیه که در هر خط و هر کاراکتر کد باید درنظر داشت و گهگاه تحلیل و بررسی و تحقیق و تست بیشتری هم کرد. حداقل برای برنامه های اینترنت که اینطوره. میگم اینترنت، نه فقط وب. تازه حتی برنامه های شبکه ای هم باید امن باشن. تنها برنامه های دسکتاپ که ارتباطات اینترنتی و شبکه ای ندارن مسائل امنیتی خیلی کمتری دارن.
و کلا وب درکل بیشترین مسائل امنیتی رو داره.
کوچکترین کاری که میخواید بکنید ممکنه مسائل امنیتی داشته باشه.
و هیچوقت نباید پیشفرض هایی داشته باشید که بی اساس هستن یا در کنترل شما نیستن.

مثلا فرض کنید شما در سایت و برنامهء خودتون میاید و از سایت بنده مطالبی رو میخونید، مثلا یک اطلاعاتی هست که میخواید در سایت خودتون به نحوی نمایش بدید یا در دیتابیس هم ممکنه ذخیره کنید و غیره. خبر، اطلاعات فنی، شناسه های خاص، هرچیزی خلاصه. شما میاید سورس صفحهء منو با توابع PHP میگیرید و اطلاعات خاصی رو بر اساس تگها و مشخصه های خاصی جدا میکنید.
در این مورد شما باید فرض کنید که بنده متوجه این کار شما شدم و بنوعی سعی کردم چیزهای خاصی رو عمدا در سورس صفحهء خودم قرار بدم تا موقعی که شما اونا رو خوندید و وارد سایت خودتون کردید یک حمله صورت بگیره یا دچار مشکل بشید. مثلا شاید عمدا کد HTML و جاوااسکریپتی رو درج کنم که درج اون در سایت شما باعث حملهء XSS به کاربران شما بشه، یا کد SQL ای رو طوری قرار دادم که وقتی شما اطلاعات سایت بنده رو در کوئری های خودتون وارد میکنید دچار حملهء SQL Injection بشید.
ممکنه شما مثلا یک چیزی به سادگی مقدار name یک تگ a رو بر اساس معیار خاصی بصورت خودکار میخونید برای لینک دادن به یک مطلبی در سایت بنده.
مثلا:

<a name="article1"></a>
و اون عبارت article1 رو در دیتابیس درج میکنید یا در لینکهای خودتون به سایت بنده و خلاصه باهاش یک کاری میکنید!
حالا شما از کجا میتونید مطمئن باشید که بنده بجای چیزهای بی خطری مثل article1 یک کد خطرناک نمیذارم؟
شاید یک عبارت درج کنم برای حملهء XSS یا SQL Injection به شما یا حتی هر سایت ناشناسی که احتمال میدم اون اطلاعات رو بخونن و استفاده کنن.
بنابراین دیتای سایت بنده برای شما و دیگران در حکم دادهء غیرقابل اعتماد است.

خلاصه امنیت یعنی همین. یعنی کوچکترین جزییات از دستت در نره و همهء شرایط و موارد رو درنظر بگیری.
برای داشتن دانش و بینش و توانایی کافی در این زمینه هم راهی نیست جز مطالعه و تحلیل و تفکر و تجربهء کافی. هرچی بیشتر مطالعه کنی و بدونی چطوری چرا چه حمله هایی صورت میگیرن، مکانیزم اونها رو خوب درک کنی، امنیت بیشتر در وجودت نهادینه میشه و بینش امنیتی کم کم میشه جزیی از وجود و دید همیشگی شما. باید هرکد و سیستم و الگوریتمی که مینویسی مسائل و ظرایف امنیتی اون رو خودت ببینی و پیشبینی کنی. لزوما برای همه چیز منابع و راهنمایی خارجی وجود نداره.

حالا خیلی افراد در مرحلهء اول هنوز طرز کار و علت استفاده توابع امنیتی که استفاده میکنن رو کامل و دقیق درک نکردن. درحالیکه این پایهء اولیه و حداقلی امنیته. تازه شروعشه. وقتی نمیدونن هرچیزی چرا چه کاری انجام میده، طبیعتا نمیتونن با سرعت بهینه و بدون محدودیت در دانش و بینش و توانایی امنیتی پیشرفت کنن.
یک برنامه نویس باید تمام جزییات رو بدونه. درمورد چیزهایی که خیلی پیچیده و حجیم هستن هم حداقل اصول و مفاهیم پایه و طرز کار کلی اونا رو خوب بدونه و درک کرده باشه. نه اینکه فقط از یکسری کد و توابع آماده بصورت کلیشه ای استفاده کنه.
البته منظورم برنامه نویس واقعی و قوی و دارای توانایی امنیتی بالاست.
طبیعتا خیلی افراد در این دسته نیستن و شاید اصولا نیازی هم نمیبینن یا حالش رو ندارن. برای پول کافی درآوردن و حتی مورد توجه و تمجید واقع شدن لزوما نیازی نیست این همه زحمت کشید و این قدر دانش و توانایی داشت. نه؟

eshpilen
جمعه 05 خرداد 1391, 21:43 عصر
درود

ممنون از eshpilen (http://barnamenevis.org/member.php?148005-eshpilen) عزیز

من قبلا تو چندتا از پروژهام از تابع زیر استفاده کردم. به نظرت چطوره؟


function Safe($str){
$str = htmlspecialchars(trim($str));
if(! get_magic_quotes_gpc() ) {
$str = addslashes($str);
}
return mysql_real_escape_string(stripslashes($str));
}

htmlspecialchars رو اینطوری استفاده کنید:

htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
البته انکدینگ مورد استفاده شما هم روی UTF-8 باشه دیگه.
بعد از نظر پرفورمنس هم بنظرم کد شما بهینه نیست. هرچند من خودم روی پرفورمنس وسواس ندارم ولی این مورد واضحا بیهوده هست که وقتی magic_quotes_gpc خاموشه بیاید خودتون addslashes کنید و دوباره در خط بعد با stripslashes اون رو خنثی کنید. بجاش بیاید و وقتی magic_quotes_gpc روشنه فقط یک مرحله stripslashes کنید (در کد تابع quote_smart که گذاشتم میتونید مشابهش رو ببینید).

eshpilen
جمعه 05 خرداد 1391, 21:53 عصر
راستی اینم کپی این تاپیک در فروم ایران پی اچ پی: تاپیک
(http://forum.iranphp.org/Thread-%DB%8C%DA%A9-%D9%86%DA%A9%D8%AA%D9%87-%D9%85%D9%87%D9%85-%D8%AF%D8%B1%D9%85%D9%88%D8%B1%D8%AF-SQL-Injection-%D9%88-mysql-real-escape-string) توش بروبچ چند روش دیگه رو مطرح کردن که شاید بهتر باشه. هدف بنده از این مطلب بیشتر فقط هشدار دادن راجع به این نکته بود که تابع mysql_real_escape_string روی داده هایی که قراره عدد باشن و در کوتیشن درج نمیشن تاثیری نداره.

eshpilen
جمعه 05 خرداد 1391, 22:17 عصر
الان به این عبارت برخوردم در یک منبعی:
all input is evil, until proven otherwise
میتونیم ترجمه کنیم به: تمام ورودیها خطرناکند، مگر اینکه خلاف آن ثابت شود!

eshpilen
یک شنبه 14 خرداد 1391, 12:37 عصر
بنظرم یک نکته مهم شد دو نکته مهم!

در صفحهء نمایش اکانتهای سیستم رجیستر و لاگین خودم امکان مرتب کردن بر اساس ستون رو گذاشتم. اسم هر ستون بصورت یک لینک است که وقتی کاربر روش کلیک میکنه اسم ستونی که نتایج باید بر اساس اون مرتب بشن در Query string پاس میشه و همون اسم هست که در کوئری بعد از order by درج میشه.
مثل این:

admin-accounts.php?per_page=10&page=1&sort_by=username&sort_dir=asc
که نهایتا وارد کوئری میشه:

$sort_by=$_GET['sort_by'];
$query="select * from `accounts` ... order by `$sort_by` ...";

خب ما طبیعتا نباید این پارامتر رو که از سمت کلاینت دریافت میشه بدون ولیدیت/پاکسازی/Escape کردن مستقیما در کوئری درج کنیم، وگرنه میتونه منجر به SQL Injection بشه.
اما نکته اینه که mysql_real_escape_string درمورد identifier ها قابل استفاده نیست. منظور از identifier همون اسم ستون و اینطور چیزهاست (یعنی داده نیست و اسم متغییر و اسم ستون و این حرفهاست).
یعنی این کد به ما امنیت نمیده:


$sort_by=$_GET['sort_by'];
$sort_by=mysql_real_escape_string($sort_by);
$query="select * from `accounts` ... order by `$sort_by` ...";

مثلا ما اسم ستونها رو بین backquote/Backtick میذاریم، و mysql_real_escape_string هم که با Backtick اصلا کاری نداره و اون رو Escape نمیکنه.
پس باید چکار کنیم؟
بنده قبلا در یک منبع امنیتی معتبر یادم هست در مورد استفاده از داده های غیرقابل اعتماد در identifier چیزهایی خونده بودم و توی اون منبع گفته بود که ایمن کردن این مورد خیلی ظریف و مشکله و بهتره کلا طرفش نرید!! حالا من نمیدونم دقیقا دلیلش چیه، چون توضیح زیادی نداده بود، ولی در پروژه خودم سعی کردم به این توصیه عمل کنم؛ بخاطر همین از یک روش امن تری برای ولیدیت کردن اینطور پارامترها استفاده کردم.
اینم اون روشی که بکار بردم:

if(isset($_GET['sort_by']) and
in_array($_GET['sort_by'], array('uid', 'auto', 'username', 'email', 'gender', 'banned')))
$sort_by=$_GET['sort_by'];
else $sort_by='auto';
در این روش همونطور که ملاحظه میفرمایید، بجای اینکه سعی کنیم کاراکترهای خطرناک داده های ورودی رو Escape یا حذف کنیم، چک میکنیم که دادهء ورودی برابر یکی از اعضای یک گروه محدود از عبارات (در اینجا اسم ستونها) باشه. درواقع این یک روش white list است که امنیت بالایی داره، بخصوص که هیچ کاراکتر و عبارت خاص و خطرناکی بین اعضای لیست ما وجود نداره.

اگر شما هم اطلاعات، تجربه، یا ایده ای در این مورد دارید بگید.

راستی جالب نیست که MySQL تابعی برای امن کردن identifier ها نداره؟
شاید فکر کنید این کار به سادگی اینه که چیزهایی مثل backquote رو در داده های ورودی حذف کنیم، و خودمون میتونیم تابع و روشی برای این کار بسازیم، اما من فکر میکنم ریسک این کارها خیلی زیاد باشه، چون اون منبع معتبری که خوندم (فکر میکنم owasp.org بود) به صراحت خلاف این رو گفته بود و در این مورد واقعا هشدار داده بود؛ بنابراین من عاقلانه دیدم که شخصا امن ترین روشی رو که بلدم و به ذهنم میرسه استفاده کنم. دیگه از اون روشی که گذاشتم امن تر سراغ ندارم. یعنی شما چک میکنید که داده های ورودی یکی از اعضای یک white list باشن و نه چیزی غیر از اون. لیست سفید که خودش یکی از امن ترین روشهاست، و از طرف دیگر چون در اعضای این لیست سفید بخصوص هیچ کاراکتر و عبارت خطرناک و مشکوکی نداریم دیگه میشه گفت که 99% خیالمون میتونه راحت باشه که نکتهء دیگری در کار نیست.