PHP_SELF می تواند توسط هکرها مورد استفاده قرار گیرد.
یک هکر می تواند در آدرس بار مرورگرش بعد از آدرس فایل، یک اسلش (/) قرار دهد و سپس دستورات XSS را برای اجرا تایپ کند.
XSS یک نوع قابلیت آسیب پذیری امنیت کامپوتر است. معمولاً در برنامه های کاربردی web بکار می رود. XSS، هکرها را قادر می سازد تا صفحات وب را از طریق تزریق اسکریبت سمت client هک کنند.
دلیل به وجود آمدن این آسیب پذیری عدم اعتبارسنجی ورودیهای کاربر می باشد، و مهاجم می تواند با تزریق اسکریپتهای مخرب در سایت از این آسیب پذیری سو استفاده کند.
فرض کنید، فرم زیر را در یک فایل بنام "test_form.php" داریم:
form method="post" action="<?php echo $_SERVER["PHP_SELF"];?
حالا اگر یک کاربر در آدرس بار مرورگرش "http://www.example.com/test_form.php" را وارد کند، کد بالا بصورت زیر ترجمه خواهد شد:
<form method="post" action="test_form.php">
خوب تا اینجا همه چیز خوب است.
اما درنظر بگیرید که کاربری URL زیر را در آدرس بار وارد کند:
http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E
در این صورت کد بالا بصورت زیر ترجمه خواهد شد:
<form method="post" action="test_form.php"/><script>alert('hacked')</script>
دومین URL، باعث اضافه شدن تگ <script> و یک دستور alert در بین کدهای ما شده است. و زمانی که صفحه لود می شود، کد JavaScript اجرا می شود (کاربر یک جعبه پیغام خواهد دید). این فقط یک مثال ساده و بی ضرر است که نحوه هک کردن متغییر PHP_SELF را نشان می دهد.
توجه داشته باشید که هر کد JavaScript دیگری را می توان در تگ <script> قرار داد...! یک هکر می تواند کاربر را به یک فایل دیگر روی سروری دیگر redirect کند، و از طریق آن فایل، اطلاعات کاربر را ذخیره کند.
با استفاده از تابع ()htmlspecialchars، می توان با هک از طریق "PHP_SELF" مقابله نمود.
کد آن شبیه زیر است:
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
تابع ()htmlspecialchars، کاراکترهای خاص را به HTML entity تبدیل می کند. حالا اگر کاربر بخواهد از متغییر "PHP_SELF" سوء استفاده کند، با نتیجه زیر روبرو خواهد شد:
<form method="post" action="test_form.php/"><script>alert('hacked')</script>">
و از این طریق هیچ آسیبی وارد نخواهد شد...!
اولین کاری که باید انجام دهید این است که تمام متغییرها را به تابع ()htmlspecialchars پاس دهیم.
حالا اگر کاربر تلاش کند که متنی مانند زیر را ارسال کند:
<script>location.href('http://www.hacked.com')</script>
در اینصورت اسکریپت بالا اجرا نخواهد شد، چونکه کاراکترهای خاص در متن بالا به HTML entity معادلاشان تبدیل شده اند:
<script>location.href('http://www.hacked.com')</script>
حالا این کد برای نمایش در یک صفحه یا داخل یک ایمیل، امن شده است.
همچنین ما دو کار دیگر را هنگام ارسال داده ها به سرور انجام می دهیم:
گام بعدی، ایجاد یک تابع، برای انجام تمام کارهای بالاست (بجای اینکه کدهای مربوط به این قسمت را بارها و بارها بنویسیم، مناسب تر است که از یک تابع استفاده کنیم)
ما این تابع را ()test_input می نامیم.
حالا ما می توانیم به ازای هر متغییر POST_$ مقدار آنرا با تابع ()test_input چک کنیم و کد آن شبیه زیر است:
<!DOCTYPE HTML> <html> <head> <style> span{min-width: 200px;float: right;} </style> </head> <body style="direction:rtl;"> <?php $name = $email = $gender = $comment = $website = ""; if ($_SERVER["REQUEST_METHOD"] == "POST") { $name = test_input($_POST["name"]); $email = test_input($_POST["email"]); $website = test_input($_POST["website"]); $comment = test_input($_POST["comment"]); $gender = test_input($_POST["gender"]); } function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; } ?> <h2>مثال اعتبارسنجی فرم ها در PHP</h2> <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> <div><span>نام:</span><input type="text" name="name"></div> <div><span>ایمیل:</span><input type="text" name="email"></div> <div><span>وب سایت:</span><input type="text" name="website"></div> <div><span>توضیحات:</span><textarea name="comment" rows="5" cols="40"></textarea> </div> <div><span>جنسیت:</span> <input type="radio" name="gender" value="female">زن <input type="radio" name="gender" value="male">مرد </div> </div><input type="submit" name="submit" value="ارسال اطلاعات"></div> </form> <?php if (isset($name) || isset($email) || isset($gender) || isset($comment) || isset($website)) { echo "<br /><h2>خروجی کدتان</h2>"; echo "نام :$name"; echo "<br />"; echo "ایمیل: $email"; echo "<br />"; echo "وب سایت: $website"; echo "<br />"; echo "توضیحات: $comment"; echo "<br />"; echo "جنسیت: $gender"; } ?> </body> </html>
خروجی کد بالا:
توجه داشته باشید که در ابتدای اسکریپت، با استفاده از متغییر "REQUEST_METHOD" نحوه ارسال داده های فرم را چک می کنیم. اگر نحوه ی ارسال داده های فرم، از طریق متد "POST" است، اطلاعات فرم پردازش خواهد شد وگرنه با یک صفحه خالی روبرو خواهیم شد.
توجه: برای بار اول که کاربر درخواست مشاهده فایل مثال بالا را به سرور ارسال می کند، بدلیل اینکه متد پیش فرض برای مشاهده صفحات از نوع get است، بنابراین شرط "$_SERVER["REQUEST_METHOD"] == "POST درست نخواهد بود و دستورات داخل شرط اجرا نخواهد شد. اما بعد از اینکه کاربر اطلاعات فرم را پر کرده و روی دکمه ارسال (submit) کلیک کرد، چون ویژگی method فرم را با مقدار "post" تنظیم کرده ایم، شرط ذکر شده درست خواهد بود و دستورات داخل آن اجرا خواهد شد.
اما در مثال بالا، تمام فیلدهای ورودی اختیاری است. حتی اگر کاربر هیچ کدام از فیلدها را پر نکند، اسکریپت بالا باز هم کار خواهد کرد.
function safe_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; }
ساختار کلی:
filter_var(var, filtername, options)
var:نام متغیر
filtername:نام فیلتر مورد استفاده
options:اپشن ها
FILTER_VALIDATE_BOOLEAN | یک مقدار بولی را اعتبارسنجی می کند. |
FILTER_VALIDATE_EMAIL | آدرس ایمیل را اعتبارسنجی می کند. |
FILTER_VALIDATE_FLOAT | یک مقدار اعشاری/float را اعتبارسنجی می کند. |
FILTER_VALIDATE_INT | مقدار عدد صحیح را اعتبارسنجی می کند. |
FILTER_VALIDATE_IP | آدرس IP را اعتبارسنجی می کند. |
FILTER_VALIDATE_REGEXP | یک عبارت باقاعده/Regular expression را اعتبارسنجی می کند. |
FILTER_VALIDATE_URL | یک آدرس URL را اعتبارسنجی می کند. |
FILTER_SANITIZE_EMAIL | تمامی کاراکترهای غیرمجاز را از داخل آدرس ایمیل حذف می کند. |
FILTER_SANITIZE_ENCODED | تمامی کاراکترهای خاص (special character) را حذف کرده یا آن ها را کدگذاری می کند. |
FILTER_SANITIZE_MAGIC_QUOTES | این ثابت معادل فراخوانی تابع addslashes() می باشد و قبل از کاراکترهای ویژه backslash اضافه می نماید. |
FILTER_SANITIZE_NUMBER_FLOAT | تمامی کاراکترها را به استثنای اعداد، +- و .،eE از عدد اعشاری حذف می کند. |
FILTER_SANITIZE_NUMBER_INT | تمامی کاراکترهای غیرمجاز به استثنای اعداد و + - را از عدد صحیح حذف می کند. |
FILTER_SANITIZE_SPECIAL_CHARS | تمامی کاراکترهای خاص را حذف می کند. |
FILTER_SANITIZE_FULL_SPECIAL_CHARS | |
FILTER_SANITIZE_STRING | تمامی تگ ها/کاراکترهای ویژه را از یک رشته حذف می کند. |
FILTER_SANITIZE_STRIPPED | نام دیگری برای ثابت FILTER_SANITIZE_STRING می باشد و عملکردی مشابه آن را ارائه می دهد. |
FILTER_SANITIZE_URL | تمامی کاراکترهای غیرمجاز را از آدرس URL حذف می کند. |
FILTER_UNSAFE_RAW | هیچ کار خاصی انجام نمی دهد ولی این قابلیت را هم دارد که کاراکترهای خاص را رمزگذاری کرده یا آن ها را حذف کند. |
FILTER_CALLBACK | یک تابع اختصاصی و تعریف شده توسط برنامه نویس را جهت فیلتر و اعتبارسنجی داده ها فراخوانی می کند.^ |
مثال:
filter_var($email, FILTER_VALIDATE_EMAIL);
مثال:
function fnValidateNumber($value){ return filter_var($value, FILTER_VALIDATE_INT); }
چک میکند که عدد صحیح باشد.