Web
upload.php之任意文件上传
1 | if (isset($_FILES['file'])) { |
利用了pathinfo()函数,$extension里存放了文件的后缀名,$name里存放了文件名
然后用了一个自己定义的clean_img_name()
函数1
2
3
4
5
6
7
8
9
10
11function clean_img_name($text) {
$text = getDef('GSUPLOADSLC',true) ? strip_tags(lowercase($text)) : strip_tags($text);
$code_entities_match = array(' ?',' ','--','"','!','#','$','%','^','&','*','(',')','+','{','}','|',':','"','<','>','?','[',']','\\',';',"'",',','/','*','+','~','`','=');
$code_entities_replace = array('','-','-','','','','','','','','','','','','','','','','','','','','','','');
$text = str_replace($code_entities_match, $code_entities_replace, $text);
$text = urlencode($text);
$text = str_replace('--','-',$text);
$text = str_replace('%40','@',$text); // ensure @ is not encoded
$text = rtrim($text, "-");
return $text;
}
首先这个过滤,使用了strip_tags()函数,剥去文件名中的 HTML、XML 以及 PHP 的标签。
然后进行了str_replace()函数替换,去除各种符号,替换为空格或者-
再对文件名进行了url编码,再把”—“替换为-,”%40”替换为@
然后使用了rtrim()函数,移除”-“右侧的空白字符或其他预定义字符
然后把文件后缀和处理过的文件名拼接,再拼上路径
最后检查是否有重写,也就是这个文件是否存在
如果存在就在文件名前面加个’个数-‘
然后是检查文件是否安全1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16if (validate_safe_file($_FILES["file"]["tmp_name"][$i], $_FILES["file"]["name"][$i])) {
move_uploaded_file($_FILES["file"]["tmp_name"][$i], $file_loc);
if (defined('GSCHMOD')) {
chmod($file_loc, GSCHMOD);
} else {
chmod($file_loc, 0644);
}
exec_action('file-uploaded');
// generate thumbnail
require_once('inc/imagemanipulation.php');
genStdThumb($subFolder,$base);
$messages[] = i18n_r('FILE_SUCCESS_MSG').': <a href="'. $SITEURL .'data/uploads/'.$subFolder.$base.'">'. $SITEURL .'data/uploads/'.$subFolder.$base.'</a>';
} else {
$messages[] = $_FILES["file"]["name"][$i] .' - '.i18n_r('ERROR_UPLOAD');
}
这里使用了自己写的validate_safe_file()
函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function validate_safe_file($file, $name, $mime = null){
global $mime_type_blacklist, $mime_type_whitelist;
include(GSADMININCPATH.'configuration.php');
$file_extension = lowercase(pathinfo($name,PATHINFO_EXTENSION));
if ($mime && $mime_type_whitelist && in_arrayi($mime, $mime_type_whitelist)) {
return true;
}
if ($mime && in_arrayi($mime, $mime_type_blacklist)) {
return false;
} else {
return true;
}
}
这里用到了全局变量:
$mime_type_blacklist:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$mime_type_blacklist = array(
# HTML may contain cookie-stealing JavaScript and web bugs
'text/html', 'text/javascript', 'text/x-javascript', 'application/x-shellscript',
# PHP scripts may execute arbitrary code on the server
'application/x-php', 'text/x-php',
# Other types that may be interpreted by some servers
'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh',
# Client-side hazards on Internet Explorer
'text/scriptlet', 'application/x-msdownload',
# Windows metafile, client-side vulnerability on some systems
'application/x-msmetafile',
# MS Office OpenXML and other Open Package Conventions files are zip files
# and thus blacklisted just as other zip files
'application/x-opc+zip'
);
但是,不管他的安全函数写的多好……有一个严重的逻辑问题,他的mine初始是Null……然而他调用的时候并没有改变它:validate_safe_file($_FILES["file"]["tmp_name"][$i], $_FILES["file"]["name"][$i])
直接导致1
2
3
4
5
6
7
8
9if ($mime && $mime_type_whitelist && in_arrayi($mime, $mime_type_whitelist)) {
return true;
}
if ($mime && in_arrayi($mime, $mime_type_blacklist)) {
return false;
} else {
return true;
}
这一块成了摆设,两个if都直接过不了,直接到了else,return了true,构成了任意文件上传,黑名单成为了摆设
backups/admin.xml.bak
这个文件里直接存放了管理员的账号和密码1
2<?xml version="1.0" encoding="UTF-8"?>
<item><USR>admin</USR><NAME/><PWD>qweasd</PWD><EMAIL>123@eee.com</EMAIL><HTMLEDITOR>1</HTMLEDITOR><TIMEZONE/><LANG>en_US</LANG></item>
可见账号是admin,密码是qweasd
download.php任意文件下载
1 |
|
在download.php文件里,我没有找到有关确认登录的函数,例如login_cookie_check();这相当危险,直接构成了任意文件下载
settings.php任意更改管理员密码
同样没有login_cookie_check(),十分危险
存在任意更改密码问题
直接访问settings.php发现username不能写入1
2
3<div class="leftsec">
<p><label for="user" ><?php i18n('LABEL_USERNAME');?>:</label><input class="text" id="user" name="user" type="text" readonly value="<?php if(isset($USR1)) { echo $USR1; } else { echo $USR; } ?>" /></p>
</div>
发现只是前端限制,加了个readonly,然后后端传入当前的登录用户名
……我们可以前端随意更改用户名
然后他直接接受了我们post的用户名1
2
3if(isset($_POST['user'])) {
$USR = strtolower($_POST['user']);
}
然后对于密码,直接输入新密码即可:1
2
3
4
5
6
7
8
9
10if(isset($_POST['sitepwd'])) { $pwd1 = $_POST['sitepwd']; }
if(isset($_POST['sitepwd_confirm'])) { $pwd2 = $_POST['sitepwd_confirm']; }
if ($pwd1 != $pwd2 && $pwd2 != '') {
#passwords do not match
$error = i18n_r('PASSWORD_NO_MATCH');
} else {
# password cannot be null
if ( $pwd1 != '' && $pwd2 != '') {
$PASSWD = $pwd1;
}
然后$PASSWD就成了我们需要的密码,$USR也成了我们需要的用户名
然后他直接执行了插入:1
2
3
4
5
6
7
8
9
10createBak($file, GSUSERSPATH, GSBACKUSERSPATH);
if (file_exists(GSUSERSPATH . _id($USR).'.xml.reset')) { unlink(GSUSERSPATH . _id($USR).'.xml.reset'); }
$xml = new SimpleXMLExtended('<?xml version="1.0" encoding="UTF-8"?><item></item>');
$xml->addChild('USR', $USR);
$xml->addChild('NAME', var_out($NAME));
$xml->addChild('PWD', $PASSWD);
$xml->addChild('EMAIL', var_out($EMAIL,'email'));
$xml->addChild('HTMLEDITOR', $HTMLEDITOR);
$xml->addChild('TIMEZONE', $TIMEZONE);
$xml->addChild('LANG', $LANG);
如果有重复,就直接重置……导致我们可以轻易的改掉管理员的密码,或者是自己添加用户进去
Babyblog
这里用到了MVC的架构,使用了laravel框架。
乍一看文件内容很多……但是我还是只主要看了controllers的代码,毕竟这一块和逻辑牵涉比较多
这里就没有一一看过去了,选择了PostsController.php,也是漏洞比较明显的一个文件
uploadImage()
首先还是上传图片函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public function uploadImage()
{
$data = [
'success' => false,
'msg' => 'Failed!',
'file_path' => ''
];
if ($file = Input::file('upload_file'))
{
$fileName = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension() ?: 'png';
$folderName = '/uploads/images/' . date("Ym", time()) .'/'.date("d", time()) .'/'. Auth::user()->id;
$destinationPath = public_path() . $folderName;
$safeName = str_random(10).'.'.$extension;
$file->move($destinationPath, $safeName);
$data['file_path'] = $folderName .'/'. $safeName;
$data['msg'] = "Succeeded!";
$data['success'] = true;
}
return $data;
}
判断文件的唯一方式就是检测文件后缀名是否为png……可以说很爆笑了,在图片里插个小马他也不知道
但是唯一有点特别的就是,存放的文件夹用了时间戳,文件名用了随机数
然而,他后面却把这个路径回显了出来,我就看不太懂了……估计是故意留的坑,这样一来,前面的时间戳和随机数还有什么意义……直接就是图片小马,按给的路径连接就好
resolveImage()
1 | public function resolveImage() |
这个函数也是很爆笑了……存在SSRF攻击。服务端并未对资源地址进行限制,导致的可以探测服务器内网或任意本地文件读取。
值得注意的是,他还特意加了一个@mkdir($destinationPath, 0755, true);
其中0755的意思是:
目录的创建者在目录中:可写、可读、可执行
同组或其他人其他人,不可写、可读、可执行。
等于这个代码明摆着告诉你,这个路径可执行…………………………简直是找打