53

PHP代码审计实战思路浅析

 5 years ago
source link: http://4hou.win/wordpress/?p=25530&%3Butm_source=tuicool&%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

*本文原创作者:wnltc0,本文属FreeBuf原创奖励计划,未经许可禁止转载

战略性的思考而非战术

对于面向过程写法的程序来说,最快的审计方法可能时直接丢seay审计系统里,但对于基于mvc模式的程序来说,你直接丢seay审计系统的话,那不是给自己找麻烦吗?

像面向过程写法的程序,可以找下它的公共函数文件有啥可以利用的不,然后就是丢seay审计系统。

而对于基于mvc写法的程序来说,跟读他的入口文件,了解整个程序的运行流程跟目录结构,之后再深入去了解它的核心类库,如果核心类库存在漏洞的话,那在这套程序中找出个漏洞的希望那不是一般的大啊!了解了整个框架运行流程后,也没从核心类库中发现什么可利用的点的话,这时就可以从功能点入手了(这时可以把源码丢进seay源代码审计系统了)。

一套组合拳打下了后还是没找到漏洞咋办?没事,换套程序继续。如果换了n套程序都找不出来,那就换个人吧……

实战环节

目标:某开源cms(icms)
环境:win+phpstudy+sublime

大概目录结构长这样

├── app       应用
├── cache     缓存
├── core      icms程序入口
├── iPHP      iphp框架文件
├── public    公共资源
├── res       用户资源
└── template  模板

打开index.php

E3A7zeZ.jpg!web

发现载入了一个icms.php,然后调用了iCMS::run()方法(如果你第一反应是以为iCMS.php是个类文件,那你后面的审计估计有点难受。)

跟进iCMS.php

iqqeiy7.jpg!web

该处载入了配置跟框架文件,继续跟进iPHP.php

j6zEbu3.jpg!web

载入几个框架文件,然后调用iPHP::bootstrap()方法,这回差不多了,继续跟进iPHP::bootstrap()

Qb2uMve.jpg!web

该处做了些环境配置,然后就是调用核心的iWAF、iSecurity类来一下全局过滤(iWAF这些先跟),看到这可有有的小伙伴又有疑惑了,iWAF什么时候加载进来了啊?

看到48行的spl_autoload_register函数了没,再具体点,看到56行那个autoload了没

AFJfemI.jpg!web 这也没看到哪有include、require之类的啊,怎么加载进来的?别急,继续跟进57行的self::auto_require

BryAFrr.jpg!web 没错就是这了,不过代码太长了就不贴了,大概就是判断传来的类名中是否有Admincp或者App,如果没有就加载app/xx/xx.class.php,如果有Admincp则加载app/xx/xx.Admincp.php,如果有App则加载app/xx/xx.app.php,如果有Func则加载app/xx/xx.func.php,如果以上都不满足则去iPHP/core/下找

VjEfUzz.jpg!web

ZjMVFrE.jpg!web iPHP::bootstrap()大概知道它干了什么了,再回头去看看iCMS::init()

viIjem6.jpg!web 大概就是初始化配置信息,继续往回看,跟进iCMS::run()

2i2yq2E.jpg!web 继续跟进iPHP::run

ieUJBrr.jpg!web (代码有点长)大概就是从post或get获取应用名,加载类跟实例化类,调用方法等

划重点了(后面会用到),这里的文件名格式是xx.app.php,类名是xxApp,其实整套程序并不止index.php这一个入口文件,还有admincp.php、user.php等,其中加载的文件名格式跟类名都是不一样的,比如:访问index.php加载的是xx.app.php的xxApp类,访问admincp.php加载的xx.admincp.php的xxAdmincp类

跟完入口文件后,对整个框架是怎么运行的,都有了个大概的了解,接下来可以去深入了解了

我跟啊跟,发现核心类中的iHttp类的remote方法有点意思,在iPHP/core/iHttp.class.php 130行

IZfYzq7.jpg!web

QNJjEry.jpg!web

remote方法封装了curl,用来获取远程页面内容,整个方法并没有对url进行任何限制或过滤,如果调用这个方法前也没用对url进行限制的话,那ssrf就跑不了了

全局搜索下看哪调用了这个方法,而remote是个静态方法,调用格式为iHttp::remote,所以直接搜这个就可以了

bU36jaB.jpg!web

我想找前台的漏洞,so,直接看哪个的文件名格式类似xx.app.php就好啦

找啊找,仅发现前台只有一处调用了该方法

322QviQ.jpg!web

找到之后,跟进去看看

fyeq6fN.jpg!web 把$avatar传了进去,继续往上翻翻,看有没有啥过滤

ZfEji2Y.jpg!web 一直往上翻,只看到这句

会不会在iSecurity::escapeStr这做了限制呢?继续跟进去看看

y2muqiA.jpg!web

貌似没有对url做限制!!!

再往上翻翻,看看是哪个方法

INFf22f.jpg!web 这回稳了,手动构造数据包

7ZFbEfZ.jpg!web 解释下个字段:

secode为验证码,可从 http://127.0.0.1/icms/public/api.php?app=public&do=seccode 获得,验证码信息存在cookie里,只要cookie不变,验证码就可一直用。

username跟nickname每次请求都要改变,avatar为传入的url,这个漏洞还有两处有点蛋疼的地方,第一,username跟nickname每次都要改变,而且这些值都是会存进数据库的;第二,这里的ssrf是没有回显。

使用dict来举个例子,访问一个未开启端口时如下

YnEv2ee.jpg!web 访问一个开启的端口时如下

z6Vr6jM.jpg!web

如果上述说的都做完还没发现漏洞,那可以尝试丢到seay源代码审计系统,或者根据功能点进行审计,找找逻辑漏洞

如果做完上述操作后再用软件来辅助,会轻松的多,比如,seay源代码审计系统扫出来如下

NNf6fqE.jpg!web

拿第二条距离,漏洞描述是referer伪造会引起sql,点击瞅瞅

iiEryqZ.jpg!web 看到referer先进入了iSecurity::escapeStr,然后再进入iDB::insert,通过前面的审计我知道 iSecurity::escapeStr对单引号等做了过滤,所以普通的sql注入是没希望了,只能看看还有没有其他方式能结合利用(我记得这是有注入的……)

如果我是一上来就用软件的话,那我现在可能还在一步一步的追一个函数,这样会增加不少功夫

本文到这就结束了,emmm!

*本文原创作者:wnltc0,本文属FreeBuf原创奖励计划,未经许可禁止转载


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK