EasySQL

<?php
    
    if (isset($_POST['query'])) {
        $BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile|readfile|where|from|union|update|delete|if|sleep|extractvalue|updatexml|or|and|&|\"";
        //var_dump(preg_match("/{$BlackList}/is", $_POST['query']));
        if (preg_match("/{$BlackList}/is", $_POST['query'])) {
            //echo $_POST['query'];
            die("Nonono.");
        }
        if (strlen($_POST['query']) > 40) {
            die("Too long.");
        }
        $sql = "select " . $_POST['query']."||flag from flag";
        mysqli_multi_query($MysqlLink, $sql);
        do{
            if ($res = mysqli_store_rersult($MysqlLink)) {
                while ($row = mysql_fetch_row($res)) {
                    print_r($row);
                }
            }
        } while (@mysqli_next_result($MysqlLink));
        
    }      
    
?>

重点其实就是这句SQL语句:

$sql = "select " . $_POST['query']."||flag from flag";

这跟以前做的SQL注入的洞有根本的不同:没用双引号或者单引号闭合,甚至都不需要手动闭合。我在测试的时候就没有发现这个问题,一直是拿单引号去闭合的。

知道了源码其实就很好做,直接:

*, 1

返回flag全部值完事,可能是出题人没有过滤*吧。

预期解:

SET sql_mode=PIPES_AS_CONCAT;

sql_mode 变量以前没有听过,通过设置 sql_mode 的值,可以设计不同程度的数据校验,从而绕过WAF。

sql_mode=PIPES_AS_CONCAT 时,|| 的作用由 or 变成了 concat,相当于字符串连接。

用这样的语句:

1, SET sql_mode=PIPES_AS_CONCAT, SELECT 1

就可以完成注入了。

Last updated