安恒月赛wp(持续更新)

安恒月赛题

题目:简历来了

image.png

image.png

简单提交之后得到源码

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 <?php
require_once('init.php');
header("Content-type: text/html; charset=utf-8");
if(isset($_POST['submit'])){
if(!z_validate_captcha()){
die('验证码错误');
}
$email = isset($_POST['email'])?trim($_POST['email']):'';
$url = isset($_POST['url'])?trim($_POST['url']):'';
$file = isset($_FILES['file'])?$_FILES['file']:false;
if($email == false || $url == false || $file == false){
die('Invalid Input');
}

if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
die('Invalid Email');
}

if(!filter_var($url, FILTER_VALIDATE_URL) || (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0)){
die('Invalid URL');
}

if($file['error'] || $file['size'] > 1024*1024 || !is_uploaded_file($file['tmp_name'])){
die('Invalid File');
}

$ext = getExt($file['name']);

if(!in_array($ext, array('.jpg','.jpeg', '.png', '.docx', '.doc'))){
die('Invalid File Type');
}

$file_checked = false;
if(in_array($ext, array('.jpg','.jpeg', '.png'))){
$finfo = finfo_open(FILEINFO_MIME);
if (!$finfo) {
die("Opening fileinfo database failed");
}
$mime = finfo_file($finfo, $file["tmp_name"]);
finfo_close($finfo);
if($mime == false){
die('Invalid Filename');
}
$arr = explode(';', $mime);
$mime = $arr[0];
if($mime == false || !in_array($mime, array('image/gif', 'image/jpeg', 'image/jpg', 'image/png', 'application/octet-stream'))){
die('Invalid Filename');
}else{
$file_checked = true;
}
}elseif(in_array($ext, array('.docx', '.doc'))){
$finfo = finfo_open(FILEINFO_MIME);
if (!$finfo) {
die("Opening fileinfo database failed");
}
$mime = finfo_file($finfo, $file["tmp_name"]);
finfo_close($finfo);
if($mime == false){
die('Invalid Filename');
}
$arr = explode(';', $mime);
$mime = $arr[0];
if($mime == false || !in_array($mime, array('application/msword','application/word', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))){
die('Invalid Filename');
}else{
$file_checked = true;
}
}

if($file_checked !== true){
die('Invalid File Type');
}

$filename = './upload/'.md5(mt_rand().microtime()).$ext;

move_uploaded_file($file["tmp_name"], $filename);

if(!file_exists($filename)){
echo '上传失败';
}else{
save_resume($email, $url, $filename);
echo "<br/>提交成功:";
echo "<br/>邮箱:".htmlspecialchars($email);
echo "<br/>个人网站:".htmlspecialchars($url);
echo "<br/>简历地址:".htmlspecialchars($filename);
echo "<br/><br/><br/>";
}
}

show_source(__FILE__);

仔细阅读源码,可以看到使用了白名单限制上传文件后缀名及MIME类型。
还有,当提交个人网站之后,后台会访问这个个人网站。
image.png
通过扫描发现有以下目录

1
2
3
4
5
6
7
http://101.71.29.5:10003/index.html
http://101.71.29.5:10003/index.php 传简历的地方
http://101.71.29.5:10003/hint.php
http://101.71.29.5:10003/admin/
http://101.71.29.5:10003/upload/
http://101.71.29.5:10003/flag.php
http://101.71.29.5:10003/submit.php

访问http://101.71.29.5:10003/admin/显示只有管理员权限才能看到flag。

到这里题目所能获取的信息到此结束,下一步是最难想(看wp)

这道题主要利用了github的CSRF项目:https://github.com/nccgroup/CrossSiteContentHijacking
参考链接:Flash跨域数据劫持漏洞,一大波网站受影响

原理分析

很多上传文件的后端逻辑在实现时,仅仅验证了文件后缀名和Content-Type,没有对上传文件的内容进行验证。通常情况下这样的处理逻辑仅仅是不严谨,不会造成太大的安全隐患。但经过笔者测试,发现object标签在包含flash文件时没有对嵌入的文件后缀进行判断。也就是说,只要文件内容包含了正常的flash文件代码,就能够被object标签成功加载并执行。而ActionScript中又提供了多种API能够让Flash发送网络请求。这样如果能够将任意后缀的Flash文件上传到目标域中,就能够在攻击者可控的域下让受害者访问一个精心构造的恶意页面,来对目标域进行跨域的数据劫持,获取受害者当前Session下的CSRF Token,以受害者的身份打开目标域的任何特权页面,进行特权操作。

flash文件有三种文件头:CWS FWS ZWS【最新的】
由于ZWS是新兴的文件格式,PHP暂不支持。

在php中,当解析cws,fws格式的文件的时候,会解析成 application/x-shockwave-flash;
但是当解析 zws 格式的文件时候,会解析成 application/octet-stream从而绕过MIME限制。

(这里我提出疑问,根据源码,php解析MIME类型是根据$mime = finfo_file($finfo, $file[“tmp_name”]);上传的文件应该是test.jpg,解析之后的MIME类型不应该是image/jpg)

拿flag思路:

已知后台会带着管理员的cookie打开flag页面,先上传一个swf(修改后缀为jpg,为了绕过),而后在个人网站上利用项目中的exp生成对应的url,后台在访问次url时,会打开此图像并加载object标签内嵌的flash,flash会利用CSRF打开 http://101.71.29.5:10001/admin/,并讲访问的内容打回到自己的服务器上。

具体过程

下载项目中的文件,将ContentHijacking.swf文件头改为ZWS然后后缀改为jpg上传到服务器,记录文件路径。

然后在ContentHijackingLoader.html125行加上你vps的地址,保存传到你的vps上。
image.png

在你的vps上打开ContentHijackingLoader.html,第一个填写开始时候上传的jpg文件地址,下面填写要攻击的URL地址。然后生成payload。

image.png

把payload写进个人网站提交,后台爬虫会访问这个payload。然后在你的vps日志里面就能看到打回来http://101.71.29.5:10001/admin/中的flag
image.png

-------------本文结束感谢您的阅读-------------