西湖论剑-信呼oa审计复盘
字数 1565 2025-08-25 22:59:10
信呼OA系统文件包含漏洞审计与利用分析
0x01 前言
本文详细分析信呼OA系统v2.3.1版本中存在的任意文件包含漏洞,通过代码审计方法定位漏洞点,并给出完整的利用过程。该漏洞允许攻击者在服务器上包含任意PHP文件,可能导致远程代码执行。
环境准备
- 信呼OA v2.3.1源码
- 代码审计工具:Seay源代码审计系统
- 测试环境:
- PHPStudy Pro
- PHP 7.3.4
- Windows 10
- 调试工具:
- VSCode
- Xdebug
0x02 任意PHP文件包含漏洞分析
漏洞定位
通过代码审计工具在include/View.php第88行定位到敏感函数include_once:
include_once($mpathname);
变量回溯分析
$mpathname变量分析
$mpathname由以下两种方式赋值:
- 第一种赋值方式(第71行):
$mpathname = ''.$tplpaths.''.$tplname.'';
$tplpaths:固定路径结构,难以利用$tplname:最终为.html后缀,无法包含PHP文件
- 第二种赋值方式(第72行):
$mpathname = $xhrock->displayfile;
此方式更有可能被利用,因为displayfile可能指向PHP文件。
$xhrock对象分析
$xhrock对象实例化过程:
$xhrock = new $clsname(); // 第37行
$clsname = ''.$m.'ClassAction'; // 第36行
$m = $rock->get('m', $m); // 第8行
$m参数通过$_GET['m']可控,经过get()方法处理后返回原始值(除非包含SQL关键字)。
displayfile成员属性分析
全局搜索displayfile,在webmain/index/indexAction.php中发现关键代码:
$this->displayfile = ''.$this->jm->getpath(''.$surl.'').'.php';
其中:
$surl来自:
$surl = $this->jm->base64decode($this->get('surl'));
get()方法允许通过$_GET['surl']控制输入base64decode()函数仅替换特定字符后解码,不影响恶意内容
调用链构造
要触发漏洞需要:
- 设置
m=index,使$xhrock成为indexClassAction实例 - 设置
a=getshtml,调用getshtmlAction()方法 - 通过
surl参数传递恶意路径(base64编码)
漏洞利用
假设存在phpinfo.php文件,内容为<?php phpinfo(); ?>,与include/View.php的相对路径为view.php/../../phpinfo.php。
利用步骤:
- 登录系统后台
- 构造URL:
?m=index&a=getshtml&surl=Li4vLi4vcGhwaW5mbw==
其中Li4vLi4vcGhwaW5mbw==是../../phpinfo的base64编码
效果:成功包含并执行phpinfo.php文件
0x03 审计方法与总结
代码审计方法
- 敏感函数定位:通过
include_once等危险函数快速定位潜在漏洞点 - 变量回溯:从敏感函数参数出发,逆向追踪变量赋值过程
- 调用链分析:理解对象实例化和方法调用关系
- 可控性判断:识别用户可控的输入点
审计经验
-
变量回溯策略:
- 当遇到多个变量时,优先分析最有可能被利用的路径
- 对固定路径或难以利用的变量可暂时搁置
- 注意类成员属性和方法的全局搜索
-
调试技巧:
- 使用Xdebug逐步跟踪变量变化
- 配合代码审计工具提高效率
- 重点关注用户输入到敏感函数的完整路径
-
漏洞挖掘要点:
- 关注文件包含后缀限制
- 注意编码/解码函数的过滤逻辑
- 分析类实例化的可控性
防御建议
- 对文件包含操作进行严格的白名单限制
- 避免用户输入直接参与文件路径拼接
- 对包含操作添加后缀限制
- 加强基础安全函数的过滤逻辑
附录:关键代码片段
- 文件包含点(
include/View.php):
include_once($mpathname);
- 可控参数获取(
include/class/rockClass.php):
public function get($na, $dev='')
{
$val = isset($_GET[$na]) ? $_GET[$na] : $dev;
return $this->jmuncode($val);
}
- base64解码函数(
include/chajian/jmChajian.php):
public function base64decode($str)
{
if(isempt($str))return '';
$str = str_replace(array('!','.',':',' '), array('+','=','&','/'), $str);
return base64_decode($str);
}
- 关键利用点(
webmain/index/indexAction.php):
$this->displayfile = ''.$this->jm->getpath(''.$surl.'').'.php';