声明:该公众号文章来自作者日常学习分享,未经授权,严禁转载,如需转载,请留言。 警告:请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 |
文章内容首发于公众号,更多内容请关注公众号:零信任地带
目录
内容提要
分享自己PHP代码审计的学习笔记,案例来自CNVD。
一、CNVD详情
参考链接:
https://www.cnvd.org.cn/flaw/show/CNVD-2017-07389
二、初步PHP代码审计
(1)环境搭建
-工具:phpstudy(PHP5.5.9)、burpsuite
-审计源码:BEESCMS
(2)定位文件上传点
(3)浏览器定位PHP文件
(4)定位PHP代码
详解:该代码为文件上传的核心代码,其中调用了up_img()函数。下面是对代码的逐行解释。 |
if (isset($_FILES['up'])) {
// 检查是否有文件通过 HTTP POST 方法上传,并且是 'up' 这个 input name 的文件。
if (is_uploaded_file($_FILES['up']['tmp_name'])) {
// 检查上传的文件是否确实存在于服务器上的临时目录中。
if ($up_type == 'pic') {
// 如果上传类型是图片,则进行以下操作:
$is_thumb = empty($_POST['thumb']) ? 0 : $_POST['thumb'];
// 如果 $_POST['thumb'] 未设置,则默认为 0;否则,使用其值。这表示是否需要生成缩略图。
$thumb_width = empty($_POST['thumb_width']) ? $_sys['thump_width'] : intval($_POST['thumb_width']);
$thumb_height = empty($_POST['thumb_height']) ? $_sys['thump_height'] : intval($_POST['thumb_height']);
// 设置缩略图宽度和高度,如果没有通过表单传递,就使用系统默认值。
$logo = 0; // 默认值,未在代码中进一步使用,可能用于标识是否添加水印等操作。
$is_up_size = $_sys['upload_size'] * 1000 * 1000;
// 将最大上传大小从 MB 转换为字节。
$value_arr = up_img($_FILES['up'], $is_up_size, array('image/gif', 'image/jpeg', 'image/png', 'image/jpg', 'image/bmp', 'image/pjpeg'), $is_thumb, $thumb_width, $thumb_height, $logo);
// 调用 up_img 函数处理上传的图片,包括尺寸检查、格式验证、缩略图生成等。
$pic = $value_arr['pic'];
// 获取上传后的图片路径。
if (!empty($value_arr['thumb'])) {
$pic = $value_arr['thumb'];
}
// 如果生成了缩略图,使用缩略图的路径替换原始图片路径。
$str = "<script type=\"text/javascript\">$(self.parent.document).find('#{$get}').val('{$pic}');self.parent.tb_remove();</script>";
// 构建 JavaScript 字符串,用于将图片路径填充到页面中的特定输入框,并关闭弹出窗口。
echo $str;
// 输出 JavaScript 字符串。
exit; // 结束脚本执行。
} // 图片上传结束
} else {
die('没有上传文件或文件大小超过服务器限制大小<a href="javascript:history.back(1);">返回重新上传</a>');
// 如果文件没有正确上传,输出错误信息并终止脚本。
}
}
浏览器中提交的时候POST参数:
up_img()函数核心代码: |
三、详细PHP代码审计
下面对PHP代码详细分析,共4个主要函数。
-
isset()
isset() 函数用于检测变量是否已设置并且非NULL。 |
-
$_FILES
$_FILES 数组通常用于收集通过 HTTP POST 方法上传的文件信息。 当你在HTML表单中使用 <input type="file" name="up"> 这样的输入字段时,用户可以选择一个或多个文件来上传。当表单提交时,这些文件的信息会被封装在 $_FILES 数组中,其中每个上传的文件都会有一个与之关联的数组,这个数组包含了文件的详细信息,如文件名、文件类型、文件大小、文件的临时存储位置等。 例如,对于一个名为 'up' 的文件输入字段,$_FILES['up'] 将包含类似这样的结构: |
例子:
$_FILES['up'] = array(
'name' => 'example.jpg',
'type' => 'image/jpeg',
'tmp_name' => '/tmp/phpXXXXX', // 临时文件路径
'error' => UPLOAD_ERR_OK,
'size' => 32873 // 文件大小(字节)
);
-
is_uploaded_file
检查指定文件是否是通过 HTTP POST 上传。 若文件是通过 HTTP POST 上传,返回 TRUE。 |
-
自定义函数:up_img()
判断MIME类型是否为图片类型 |
$file_type=$file['type'];
if(!in_array(strtolower($file_type),$type)){
msg('上传图片格式不正确');
四、漏洞复现
(1)拦包将MIME类型修改
(2)成功上传
(3)成功访问
成功访问php文件,后续可getshell
五、总结
(1)漏洞原因:文件上传时,只靠MIME值限制,而该值可以被修改。
(2)漏洞危害:任意文件上传,可被完全控制。
(3)修复方法:增加文件头判断、文件后缀名限制。
感谢观看:如果觉得对您有帮助,请关注公众号,更多内容首发于公众号:零信任地带 |