得到题目输入1,返回一个数组

    又是堆叠注入([SUCTF 2019]EasySQL) - 图1

    不由得让我想起春秋战役里面的堆叠注入

    经过尝试(‘),(“)都被过滤了

    简单试一试输入,发现有三种回显,分别位’nonono’,空以及返回array

    在这里,很多都被返回了nonono,我想应该是被过滤了,但是太多我们都不可能一一尝试,所以跑一下字典

    又是堆叠注入([SUCTF 2019]EasySQL) - 图2

    很明显,507的应该是被过滤的字符。由于和春秋战役太相似,春秋战役直接给我来了个正则很长。这咋办。

    所以我们试试堆叠注入

    又是堆叠注入([SUCTF 2019]EasySQL) - 图3

    果然返回来了,那无疑是堆叠注入了

    但是。接下来有个头疼的地方了,flag这个被过滤了

    怎么爆字段。发现有源码:

    1. <?php
    2. session_start();
    3. include_once "config.php";
    4. $post = array();
    5. $get = array();
    6. global $MysqlLink;
    7. //GetPara();
    8. $MysqlLink = mysqli_connect("localhost",$datauser,$datapass);
    9. if(!$MysqlLink){
    10. die("Mysql Connect Error!");
    11. }
    12. $selectDB = mysqli_select_db($MysqlLink,$dataName);
    13. if(!$selectDB){
    14. die("Choose Database Error!");
    15. }
    16. foreach ($_POST as $k=>$v){
    17. if(!empty($v)&&is_string($v)){
    18. $post[$k] = trim(addslashes($v));
    19. }
    20. }
    21. foreach ($_GET as $k=>$v){
    22. }
    23. }
    24. //die();
    25. ?>
    26. <html>
    27. <head>
    28. </head>
    29. <body>
    30. <a> Give me your flag, I will tell you if the flag is right. </ a>
    31. <form action="" method="post">
    32. <input type="text" name="query">
    33. <input type="submit">
    34. </form>
    35. </body>
    36. </html>
    37. <?php
    38. if(isset($post['query'])){
    39. $BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile|readfile|where|from|union|update|delete|if|sleep|extractvalue|updatexml|or|and|&|\"";
    40. //var_dump(preg_match("/{$BlackList}/is",$post['query']));
    41. if(preg_match("/{$BlackList}/is",$post['query'])){
    42. //echo $post['query'];
    43. die("Nonono.");
    44. }
    45. if(strlen($post['query'])>40){
    46. die("Too long.");
    47. }
    48. $sql = "select ".$post['query']."||flag from Flag";
    49. mysqli_multi_query($MysqlLink,$sql);
    50. do{
    51. if($res = mysqli_store_result($MysqlLink)){
    52. while($row = mysqli_fetch_row($res)){
    53. print_r($row);
    54. }
    55. }
    56. }while(@mysqli_next_result($MysqlLink));
    57. }
    58. ?>

    看到mysql_multi_query(),可以堆叠注入

    又是堆叠注入([SUCTF 2019]EasySQL) - 图4

    那确实,但是他妈的被过滤了咋整

    我们发现,查询语句为

    又是堆叠注入([SUCTF 2019]EasySQL) - 图5

    通过堆叠注入sql_mode的值为PIPES_AS_CONCAT

    又是堆叠注入([SUCTF 2019]EasySQL) - 图6

    又是堆叠注入([SUCTF 2019]EasySQL) - 图7

    这里解释一下PIPES_AS_CONCAT

    又是堆叠注入([SUCTF 2019]EasySQL) - 图8

    这句话sql语句的意思是开启mysql中支持管道符来进行字符串的拼接操作

    简单准备的原始数据表:

    又是堆叠注入([SUCTF 2019]EasySQL) - 图9

    没有开启这个模式的时候

    又是堆叠注入([SUCTF 2019]EasySQL) - 图10

    开启了这个模式后

    又是堆叠注入([SUCTF 2019]EasySQL) - 图11

    可以从上图看到,数据表中的数据被带出来了,下面这张图更清晰

    又是堆叠注入([SUCTF 2019]EasySQL) - 图12

    从而将 || 视为字符串的连接操作符而非或运算符,所以构造出来

    只输入数字进行查询是因为,执行数字时有回显,判断是执行成功的,查询字符串则会报错,一般来说php会设置默认不显示报错信息,因此使用数字查询开启这个模式来手动构造注入漏洞

    这样在进行查询的时候将||运算符当成连接符成这样的语句
    select 1,flag from Flag