Monday, April 29, 2013

Харуул занги 2-р үе Vulnerability

Уг бүлэгт нийт 4-н даалгавартай бөгөөд харин тэмцээний явцад 3 нь л нээгдсэн юм.

1. Харуул (100 оноо)
Харуул даалгавар бүрэн эхээрээ байхгүй бөгөөд гол санаа нь доорх код дээр энгийн sql injection маягийн зүйл хийнэ. Уг нь маш хялбархан даалгавар. Даанч тэр үедээ гүйцэтгэж чадаагүй л юм даа.
<?php
include('conn.php');
$flag = '...';
$admin = false;
$pass = false;
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$result = mysql_query("select * from members where username like '".real_escape_string($_POST['user'])."';");
if (!$result)
{
echo('Алдаа!');
return;
}
else
{
while ($row = mysql_fetch_assoc($result))
{
if ($row['username'] == 'admin')
{
$admin = true;
}
if ($row['userpass'] == $_POST['pass'])
{
$pass = true;
}
}
}

if ($admin && $pass)
{
echo $flag;
}
}
?>

//_______________________________________________________________________//
SOLUTION:
Уг даалгавар дээр шинээр хэрэглэгч үүсгэх боломжтой байсан бөгөөд хэрэв $row['username'] == 'admin' болон if ($row['userpass'] == $_POST['pass']) шалгалтыг давахад флаг маань гараад ирнэ. Шинээр хэрэглэгч үүсгэх боломжтой тул  if ($row['userpass'] == $_POST['pass']) үүнийг давах нь үүсгэсэн хэрэглэгчийнхээ нэр, нууц үгээр нэвтрэхэд л хангалттай юм. Харин  if ($row['username'] == 'admin') үүнийг давахын тулд дараах аргыг хэрэглэе.
Post-р дамжиж ирсэн өгөгдлийг real_escape_string($_POST['user']) гэж ашиглаж байгаа бөгөөд query дээрээ like ашигласан байна. real_escape_string функц нь \x00, \n, \r, \, ', ", \x1a тэмдэгтуудэд л  slash(\) нэмж өгдөг бөгөөд %-г хэвээр нь үлдээх юм. Үүнийг нь ашиглавал LIKE-р нөхцөл шалгаж байгаа тул admit гэсэн хэрэглэгч үүсгээд нэвтрэхдээ хэрэглэгчийн нэр дээ admi% гэж бичээд нууц үг дээр admit-н нууц үгийг бичихэд хангалттай.
//_______________________________________________________________________//

2. Татар (200 оноо)


3. Өэлүн (300 оноо)
Мөн л даалгавар бүтнээрээ байхгүй бөгөөд гол санаа нь:
if (strcmp($arg1, "arg1value1")==0){
if (strcmp($arg2, "arg2value1")==0){
if (strcasecmp($arg1, "arg1value2")==0){
if (strcasecmp($arg2, "arg2value2")==0){
if ($arg1==arg2){
echo $flag;
}
}
}
}

}
дээрх кодонд bypass хийх хэрэгтэй. $arg1 болон $arg2 нь GET-р дамжуулагдсан хувьсагчууд.

//_________________________________________________________________________//
SOLUTION:
Дээрх бүх нөхцөл шалгалтууд(IF)-г даваад буюу бүх бүгдийг нь true буцаалгаж л чадвал flag-аа буюу оноогоо олоод авчихна. Гол асуудал нь PHP дээрх 1 хувьсагч (дан ганц PHP ч бус бусад бүх хэлүүд) 2 тэс өөр утгатай нэгэн зэрэг тэнцүү байх боломжгүй юм.
Иймд харьцуулж буй 2 хувьсагчаа GET-р дамжуулж авч байгаа бөгөөд string дамжуулбал эхний 2 л нөхцөлийг биелүүлээд цааш явахгүй нь тодорхой. Тиймээс string биш өөр зүйл дамжуулж байж л болох юм. Тэр нь массив.
Учир юунд вэ гэвэл PHP-н strcmp функцэд аргументууд нь string байх ёстой бөгөөд бусад төрөл ороод ирвэл шууд NULL утга буцаах бөгөөд харьцуулахдаа === биш == гэж харьцуулсан тул тэр нь 0-тэй тэнцдэг.
Уг тохиолдолд test.php?arg1[]=abc&arg2[]=abc ингэж буюу массив дамжуулж өгч дуудахад bypass хийх юм.
//_________________________________________________________________________//

No comments:

Post a Comment