0x01 前言
西湖论剑的题目,比赛时没做出来,赛后又花了点时间还是没做出来.最后看了wp,又去复现了下审计过程,学习到很多知识点.
相关工具:
信呼oa v2.3.1题目源码
seay源代码审计系统
phpstudypro
php7.3.4
wind10
vscode
xdebug
0x02 任意php文件包含
代码分析
使用代码审计工具在include/View.php
的第88行
定位到敏感函数include_once
,
回溯文件包含中的变量$mpathname
,
在本文件的第71和72行
发现了变量定义和赋值的操作.
先对第71行
的代码进行分析:
由图 2 可以清楚的看到变量$mpathname
由其他两个变量$tplpaths
和$tplname
决定.回溯这两个变量,分别在本文件的第67行
和第70
行发现最近赋值操作:
$tplpaths = ''.$temppath.''.$d.''.$m.'/';
$tplname .= '.'.$xhrock->tpldom.'';
回溯$temppath
,在66行
找到最近赋值操作
$temppath = ''.ROOT_PATH.'/'.$p.'/';
回溯$p
,在本文件的第4行
:
$p = PROJECT;
到这里大概可以感觉到$tplpaths
的路径是写死了的,所以就暂时放弃变量$tplpaths
去回溯$tplname
.
回溯$xhrock
,在本文件的第37行
发现$xhrock
的定义:
$xhrock = new $clsname();
回溯$clsname
,在本文件第36行
发现定义
$clsname = ''.$m.'ClassAction';
回溯$m
,在第8行
发现最近一次赋值操作:
$m = $rock->get('m', $m);
跟进get()
这个函数,最后发现其核心调用在include/class/rockClass.php
的第105
行,
可以看到这个函数的中的$val
可控.继续跟进jmuncode()
,到本文件的第127行
其函数逻辑大致为对传入的$s
进行合法行检测以及特殊值的一些特殊处理.配合xdebug
测试发现只要$_GET['m']
的值不是一些sql
关键字,$m
的值等于$_GET['m']
.也就是说,这里的变量$m
可以被用户使用$_GET['m']
传参进行控制.也就是$xhrock
是能够进行控制的.
由于$xhrock->tpldom
这种形式是在获取一个成员属性,全局搜索以下tpldom
,在include/Action.php
文件中的第43行
发现定义.
可以看到最后tplname
表示文件的后缀名为html
,没法利用,看来此路不通.
继续对第72行
的代码进行分析:
可以看到第72行代码的形式$mpathname = $xhrock->displayfile;
同样为获取某个类的成员属性,再次全局搜索displayfile
,总共得到14个搜索结果.
每个文件点进去看了一下,在webmain/index/indexAction.php
下发现惊喜!
可以看到这个文件中的$displayfile
是以.php
为后缀的变量,而变量$displayfile
最后可以决定我们文件包含$mpathname
的取值,也就是说这里可能存在一个.php
的文件包含.
继续回溯$surl
,发现其最近赋值在本文件的第250行
$surl = $this->jm->base64decode($this->get('surl'));
跟进get()
,最后同样来到include/class/rockClass.php
的第105
行,和$m
赋值时调用的函数一样,也就意味着这里传入base64decode()
函数的内容可控.
再来分析分析外面的base64decode()
函数,其函数体位于include/chajian/jmChajian.php
的第93行
通过阅读可以发现其逻辑主要是对传入的形参$str
判断是否为空以及进行敏感字符替换,再返回其base64解码的内容.
这里就存在一个很明显的逻辑错误:很明显base64加密后的字符是不存在! . :
,所以对恶意内容进行base64
编码后传入最后是可以被还原的.也就是说这里的$surl
是可以被控制的.
回到include/View.php
的第72行
,看看是否存在一个利用点使之能得到 /webmain/index/indexAction.php
下的indexClassAction->displayfile
.这里需要跟踪的变量是$xhrock
,而前面以及分析过了$xhrock
的构造流程也得出结论$xhrock
部分可控.
这里$xhrock
可控还存在一个前提是存在文件$actfile
,跟踪$actfile
,其定义在此文件下的第30行
:
$actfile = $rock->strformat('?0/?1Action.php',$actpath, $m);
跟进strformat()
方法,来到include/class/rockClass.php
下的第551行
:
发现函数体里调用了stringformat()
方法,继续跟进,到文件的第542行
通过阅读strformat()
以及stingformat()
的代码可以了解到strformat
函数的逻辑为找到$m
操作对应的php文件.而可控变量$displayfile
位于/webmain/index/indexAction.php
中,这里可以构造$m
的值为index
.在回过来看看变量$xhrock
就已经等于new indexClassAction
了.一切都是这么流畅!
在第42行
,发现一个调用成员方法:
$actbstr = $xhrock->$actname();
跟踪$actname
,发现其定义在38行
:
$actname = ''.$a.'Action';
跟踪$a
,
$a = $rock->get('a', $a);
可以看到$a
赋值所使用的方法同变量$m
相同,也就意味着$a
也可控,那我们可以直接给控制$a
为getshtml
.从而实现调用webmain/index/indexAction.php
中indexClassAction
的getshtmlAction()
函数,在配合$surl
可控,就可以实现任意.php文件读取.
漏洞利用
现存在文件phpinfo.php
,内容为:
<?php phpinfo();
与include/View.php
之间的目录关系为
view.php/../../phpinfo.php
先登录进信呼协同办公系统后台,再构造url参数,访问
?m=index&a=getshtml&surl=Li4vLi4vcGhwaW5mbw==
其中,Li4vLi4vcGhwaW5mbw==
为../../phpifo
base64编码后的结果.
可以看到成功包含已知相对路径下的phpinfo.php文件
0x03总结
本次代码审计的流程主要使用敏感函数参数回溯
的方法,通过代码审计工具定位到敏感函数include_once
,回溯敏感函数中关于参数$mpathname
的定义以及赋值的操作.再发现其中涉及到函数以及变量再进行回溯,直到发现漏洞点.这种方法的优点可以通过敏感函数或者敏感关键字快速挖掘到想要的漏洞,但由于没有通读代码,对程序的整体框架了解得不够深入,可能会忽略掉部分逻辑漏洞
其次,再使用敏感函数参数回溯法
的时候,可能在回溯过程中遇到的变量越来越多,我们不可能短时间内对每个变量和每个函数都进行回溯和跟踪,要学会判断在什么暂停回溯当前变量而去回溯其他变量.有时候代码审计的战线可能会拉的很长,我们得时刻专注和记忆过程中遇到的变量,只有清楚每个变量的变化过程才能更好的挖掘漏洞.
以上就是我本次审计过程中的主要思路以及操作流程,可能过程中存在一些欠佳甚至错误的操作.代码审计入门,希望师傅们多多指出不足.