文章总结: 本文对ModStartCMS-7.2.0进行代码审计,发现两个高危漏洞:前台任意文件上传漏洞允许通过远程拉取图片功能上传恶意文件;前台RCE漏洞利用phar反序列化通过file_exists函数触发命令执行。文档详细描述了漏洞复现步骤、调用链分析和修复建议,强调需升级到最新版本。 综合评分: 85 文章分类: 代码审计,漏洞分析,WEB安全,红队,实战经验
在相同游览器访问http://localhost:19980/页面,选择并上传laravel5_exp.jpg文件。

漏洞审计
调用链:
Member/Web/Controller/MemberProfileController.php avatar 54行 Member/Api/Controller/MemberProfileController.php avatar 83行 vendor/modstart/modstart/src/Core/Util/FileUtil.php savePathToLocalTemp 606行 vendor/modstart/modstart/src/Core/Util/FileUtil.php file_exists 608行
从路由文件Member/Api/routes.php中可以找到路由/member_profile/avatar对应的MemberProfileController.php中的avatar函数。
跟进后来到Member/Api/Controller/MemberProfileController.php的avatar函数中进行处理。通过改变传入type参数的值来进入到savePathToLocalTemp函数中去。
传入的路径会先通过file_exists函数进行判断,这个函数可以触发phar协议,执行反序列化,造成命令执行。
0x05 认识 Phar 元数据自动反序列化
Phar (PHp ARchive) 文件是一种使用单一文件格式(类似于 JAR 文件在 Java 生态系统中的工作方式)分发 PHP 应用程序和库的方法。从结构上讲,它们只是存档(带有可选的 gzip 压缩或基于 zip 的 tar 文件)。
安全研究员Sam Thomas分享了议题 It’s a PHP unserialization vulnerability Jim, but not as we know it
实际上在PHP 8.0之前,当使用Phar流包装器时,它会自动尝试反序列化Phar元数据。即在对Phar文件进行任何文件操作时会将文件中的meta-data进行反序列化。
PHP8.0 后的变化
在php-src/ext/phar/phar.c中我们可以找到meta-data处理的函数phar_metadata_tracker_unserialize_or_copy。在PHP 8.1中,流包装器函数不再尝试自动反序列化元数据。只有显式调用Phar::getMetadata和PharFileInfo::getMetadata方法时才会尝试反序列化Phar元数据。观察代码,这里增加了options,它的内容是在Phar文件定义的。
$phar = new Phar('path/to/phar.phar');$phar->getMetadata(['allowed_classes' => []]);
具体处理函数php_unserialize_with_options可以在php-src/ext/standard/var.c中找到。
首先检查allowed_classes是否为数组、布尔值或未设置。如果是数组或布尔值,它会创建一个哈希表class_hash来存储允许的类。然后,它遍历allowed_classes数组,将类名添加到class_hash中。最终,class_hash会被传递给php_var_unserialize_set_allowed_classes函数,这将限制在反序列化时允许的类。这样,通过设置allowed_classes选项,代码实现了对允许的类进行限制。
if (options != NULL) { zval *classes, *max_depth; classes = zend_hash_str_find_deref(options, "allowed_classes", sizeof("allowed_classes")-1); if (classes && Z_TYPE_P(classes) != IS_ARRAY && Z_TYPE_P(classes) != IS_TRUE && Z_TYPE_P(classes) != IS_FALSE) { zend_type_error("%s(): Option \"allowed_classes\" must be of type array|bool, %s given", function_name, zend_zval_value_name(classes)); goto cleanup; } if(classes && (Z_TYPE_P(classes) == IS_ARRAY || !zend_is_true(classes))) { ALLOC_HASHTABLE(class_hash); zend_hash_init(class_hash, (Z_TYPE_P(classes) == IS_ARRAY) ? zend_hash_num_elements(Z_ARRVAL_P(classes)) : 0, NULL, NULL, 0); } if(class_hash && Z_TYPE_P(classes) == IS_ARRAY) { // 处理 allowed_classes 选项 } // 处理 max_depth 选项}
从下面代码看,尽管我们不传递options保持为NULL一样可以进入到php_var_unserialize函数中去。这种代码属于向后兼容性。
在php-src/ext/phar/phar_object.c我们可以了解到,Phar::getMetadataC 扩展宏定义。
这里逻辑做了两部分工作:1、获取 metadata tracker
tracker = &phar_obj->archive->metadata_tracker;
通过phar_obj对象获取 Phar 归档对象,然后获取与该归档对象关联的metadata tracker。metadata_tracker负责跟踪归档的元数据信息。2、检查是否有数据并获取数据
if (phar_metadata_tracker_has_data(tracker, phar_obj->archive->is_persistent)) { phar_metadata_tracker_unserialize_or_copy(tracker, return_value, phar_obj->archive->is_persistent, unserialize_options, "Phar::getMetadata");}
检查metadata tracker是否包含数据,如果是,则调用phar_metadata_tracker_unserialize_or_copy函数,该函数用于将元数据反序列化或复制到return_value中。is_persistent参数表示是否是持久化的 Phar 归档。在文件php-src/ext/phar/phar_object.stub.php中可以找到对应接口定义
public function getMetadata(array $unserializeOptions = []): mixed {}
以下列举出能触发 phar 反序列化的函数:
copy file_exists file_get_contents file_put_contents file fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype fopen is_dir is_executable is_file is_link is_readable is_writable lstat mkdir parse_ini_file readfile rename rmdir stat touch unlink getimagesize fstatfseek opendir require_once include_oncerequire include scandir highlight_file
除了上述代码,还有其他函数需要我们去发现。
参考文章:PHP 8.0: phar:// stream wrapper no longer unserializes meta data automaticallyPHP: rfc:phar_stop_autoloading_metadataExploiting PHP Phar Deserialization Vulnerabilities: Part 1
0x06 总结
Phar 反序列化在非常多的地方可以实现攻击,它的灵活性让PHP感到头疼。因为他尽管在文件上传后缀限制的情况下,依旧可以实现反序列化攻击。这项技术在18年提出,可开发人员对其了解甚少,对它的过滤几乎没有,并且这几年来都提出绕过简单防御的可能性。虽然在CTF中Web题目已经不屑于出该类型的题目,但它依旧值得我们去了解以及学习。
原文链接:https://forum.butian.net/share/2676
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:只会看监控的实习生 en0th en0th《ModStartCMS-7.2.0 代码审计》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论