PHP代码审计实战思路浅析

PHP代码审计实战思路浅析

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

No.1

前言

每一次总结,都可以看作是对前面所学做一次“大扫除”,就像电脑硬盘,只有将那些缓存文件都清掉,才能腾出更多空间来存新的内容。这次的“大扫除”,以为例,以“通读全文”、“敏感函数回溯”、“定向功能点审计”为切入点,重新梳理一遍平时的审计思路。

望大佬们多多指教!

No.2

通读全文

通读全文!从字面意思来看,可以理解成把所有的代码都读一遍,把所有的代码都“读透”。那么问题来了,现在的cms大多数都是参照mvc模式进行开发,一个大的系统被拆分成视图(View)、模型(Model)、控制器()三个部分。这种软件架构虽然能使得程序的结构变得更加直观,但也只能说是逻辑上的直观,因为在使得程序结构变得直观的同时,也增加了系统结构和实现的复杂度,所以在审计这类cms时,很难通过目录结构或者直接搜索危险函数来进行快速审计。原因在于,基于mvc模式开发出来的cms不像面向过程化开发的cms那样,一个目录就是一个功能模块,一个php文件就是一个功能点。基于mvc模式开发的cms,会有一个统一的入口,所有的请求都从该入口进入,然后由框架统一进行调度,且程序中的一些可重用的操作,例如数据库操作、缓存、安全过滤等都会被封装成框架的核心类库PHP代码审计实战思路浅析,需要时再去调框架封装好的方法。如果在没了解程序的结构前PHP代码审计实战思路浅析,就贸然去跟某段代码,很容易迷失在一个个类库的调用链里。

那么,我们在审计这类cms时,首要目的就是,了解程序的基本结构。前面提到,基于mvc模式开发的cms,会有一个统一的入口,所有的请求都从该入口进入。如果我们想读懂这套源码,这个入口倒是个很好的切入点。在正式上手分析前,先来思考下,当一个请求进入这套程序的入口后,程序内部会对它做哪些操作。例如,这个url会怎么解析?程序内部是怎么将url与控制器关联到一起的?实际分析时会经常看到“Demo::test()”这种调用方式,但Demo类并不在这个文件内,而且文件内也没看到或,所以这些在程序内部又是怎么实现的呢?

俗话说,要用魔法来打败魔法。既然这是属于开发的东西,在正式分析前,还得来找开发取一下经。先来看下框架的运行流程。

入口文件,对应着前面说的统一入口,虽然说是统一入口,但实际情况中入口文件可能有多个,前台一个、后台一个、接口一个。入口文件的职责在于,定义一些全局性的常量,加载函数库,加载框架启动类等等。这里的自动加载类,说成类自动加载会更加合适,主要目的是,为了简化类加载的步骤,通常会将类文件的加载操作封装成一个函数或者方法,然后在框架启动前或者在框架启动时,通过r将类加载函数注册到函数队列中,当程序内的代码调用某个类时,php会调用类加载函数,类加载函数就会到正确的地方去把类库文件加载进来;当然也可以不使用r函数来自动调用,而是在需要时手动去调用。再下一步,就是启动框架。框架启动后,可能会去加载一些配置文件,然后去调用路由类来解析请求url,根据解析的结果来调用相应的控制器,最后返回结果。

通常情况下,入口文件的位置在网站的根目录下,一般会命名成index.php、admin.php或者api.php。观察当前项目的目录及文件。

这里的index.php、admin.php、api.php和.php都挺像入口文件的,这里选择先跟进index.php。原因是,一般情况下,前台的入口都叫index.php。

代码很简单,定义了一个常量,然后是加载一个php文件,最后调用类的方法。入口文件、定义常量,那下面的很大可能就是框架启动类了,跟进到//base.php。

往下翻,能看到很多定义常量,还有加载函数库的操作。

继续往下看,就看到了在入口文件中调用的::方法

从注释来看,该方法的作用是初始化应用程序,继续跟进方法。

从注释来看,该方法用于加载系统类,继续跟进方法。

同样,也可以通过注释来了解该方法的作用。

方法用于加载类文件,对应着前面说的类自动加载,找到类加载函数后,继续分析类文件的加载逻辑。从代码中可得知,类库目录在框架目录下的$path目录,也就是/目录下,类文件名为“类名.class.php”,如果$path参数为空,则默认到//libs/目录下去加载类文件,然后根据$参数来决定是否实例化该类。前面的方法在调用时,传入的$path参数是空的,且$=1,也就是说,//libs/目录下放的是系统类php代码审计视频教程,且加载系统类库时会自动实例化该类。除了,还有和,三者的底层都是调用了,区别在于传入的$path不同。

除了加载类库的,还有加载函数库的,和加载配置文件的。

通过对类加载方法、函数库加载方法、配置文件加载方法的分析,就能找出程序的基本目录结构。

回到前面用来初始化应用程序的方法。

跟进到类

回顾前面提到的框架运行流程,从入口文件,到类自动加载,到启动框架,框架启动后,下一步就是路由解析,那param类很大可能就是路由类,继续跟进param类。

在param类的构造方法中会使用封装后的函数对$_POST、$_GET、$数组进行转义。再往后就是调用、、方法解析路由,获取模块、控制器和方法名。

方法获取m参数的值作为模块名,同理,则是获取c参数的值,则是获取a参数的值。同时还会调用方法对传入的值做过滤。

路由解析完后,再下一步就是加载控制器。

继续跟进init方法。

继续跟进方法。

方法先到“///模块名/”目录下加载控制器文件,然后实例化并返回对象。

init方法通过方法获取到控制器实例后,通过方法来执行具体的动作,最后返回结果,请求结束。

No.3

敏感函数回溯

当输入的数据,被当作代码去执行,或者会改变原本设定好的代码逻辑,就可能产生漏洞。拿SQL注入来说,当外部输入的数据被带到数据中执行,并且能通过构造特殊的内容来修改原有的SQL语句结构,就会产生SQL注入。如果我们想挖掘SQL注入漏洞,就应该把关注点放在数据库查询操作上,而PHP中能执行SQL语句的函数有、等,这些函数就可以称为敏感函数。从代码中找到这些敏感函数的调用位置,然后去回溯其参数来源,如果来源可控,就存在漏洞。同理,如果想找代码执行漏洞,可以去找能执行代码的函数,例如、eval、等;如果想找命令执行,就去找能执行系统命令的函数,例如、、popen等。通常的做法有,使用编辑器进行全文检索敏感函数的函数名,然后人工一个个去回溯参数来源,还可以使用一些代码审计工具来进行扫描分析,然后再手动去验证。为了节省时间,一般会先工具扫描一遍,快速找出那些比较明显的漏洞。

扫描结果里的代码注入看到倒是很吸引人,那就先从它入手。从代码来看,很明显的一个eval代码注入。这段代码存在于///libs//.func.php,从文件名和文件路径来看,函数位于系统函数库中。从左下角的调用链来看,在////admin/.php文件中调用了,/目录下的结构于上面的分析的一样,根据上面的分析结果,可得知,.php是一个控制类文件。跟进到.php的94行。

在92行的位置,将函数的返回结果赋值给$res,观察左下角的调用链,发现最后调用了fread函数,同时结合传入给函数的参数名推测,该函数应该是用来发起http请求的,后续跟进分析,得到的结果也是。那方法的作用应该发起一个请求,将请求结果转换成数组,然后遍历输出。如果能控制响应结果,就能形成代码执行漏洞,而控制了请求url,就能控制响应的结果。

继续分析,在88行的位置,将 $

‘url’

. $

‘’

赋值给$url。

在87行,将函数的返回结果赋值给$。$appid由get传入,可控。如果的返回结果可控,就有希望实现代码执行。跟进,根据前面的分析,知道在框架启动前会加载系统的函数库,所以可以到系统函数库中寻找函数。

先是加载配置文件,然后调用::(),配置文件内容如下。

跟进::

跟进方法

跟进load方法

load方法根据传入的缓存配置信息来决定是加载文件缓存还是,而默认情况是加载文件缓存。回到前面的函数php代码审计视频教程,获取到缓存类的实例后,调用该类的get方法。

默认情况下使用文件缓存,所以该方法应该是位于类。

从get方法内的代码来看,缓存文件的路径在//模块名/$type/下,默认情况下通过引入并将结果复制给$data返回。

回到.php的方法。

87行,将的返回结果赋值给$,的调用链如下。

$的内容如下:

既然$来源于缓存文件,那如果能找到写入缓存的点,没准就能控制缓存的内容,配合前面的方法实现代码执行。找到写入缓存的方法为set,文件路径拼接跟get差不多。

通过回溯set方法的调用链即可找出写入缓存的点。

最后在控制器的add方法中找到写入缓存的点。

在类的add方法,39行处,将url写入数据库,回溯$url的来源,发现在26行处通过post传入。

确定url可控,接下来开始构造利用链。

漏洞利用过程:

1.访问,登录。

2.访问。

3.填入应用地址,既url,点提交,即可将url写入缓存。

添加成功后跳转回应用管理页面

在编辑按钮的请求url中可以得到刚刚添加的appid。

1.服务器启动一个php的,并创建一个evil.php,内容如下:

2.访问即可触发代码执行。

No.4

定向功能点审计

定向功能点审计感觉更像是黑盒白盒的结合体,通过去浏览网站的功能,对可能存在问题的功能点的代码进行审计,检查是否存在问题。例如,发表留言、发送站内信这些功能,比较容易产生跨站脚本漏洞,审计时可以优先关注php代码中,数据在输入输出时是否有被html编码,如果没有,那就看下,有没有xss代码过滤,如果两者都没有,那很大可能就存在xss,如果有xss过滤,则可以通过分析过滤了那些特殊字符或关键字,如果能找到没有过滤的关键字,就能绕过过滤。前面分析框架运行流程时,对控制器和模型的存放位置,以及调用方式都有所了解,但mvc,除了m和c,还有个v。视图解析,这个贯穿全局的功能,一般情况下是不太容易出问题,但如果存在二次解析,那出现漏洞的概率就要高上不少。

如果不清楚哪个是模板解析类,可以选取一个功能点作为切入点,一步步定位到模板解析类,例如,首页。

其他代码不是我们的关注点,函数是获取缓存的,seo怎么看也不像视图解析的,直接到系统函数库找函数。

无关紧要的代码先忽略,优先找跟模板加载有关的代码。

在456行的位置,将类加载进来。然后到///下找模板文件,推测这里存的应该是编译后的模板文件。

如果$存在则返回$的路径给函数进行包含。

如果$不存在,则调用$->方法进行编译生成$文件,然后再包含,跟进方法。

从代码中可得知,16-34行的主要作用是到///模块/目录下读取模板文件。

然后调用方法解析模板内容,将解析后的结果写入模板缓存。继续跟进方法。

解析规则如上图,直接解析成php代码的不在关注范围内,原因是,通常情况下,这些标签内容都是不可控的。模板内容不可控的情况下,一般会把注意力放在,那些将解析后的结果交给其他方法再进行一次处理的的解析规则上。

例如91行,93行。91行将从模板中匹配到交给$this->进行处理,但$this->方法仅仅是将传入的内容再转义一下,没什么特别的地方,继续看93行处的self::方法。

从注释来看,会对前面解析到的内容再进行一次解析,同时还会在解析后的代码前面加入一段“死亡代码“。

当$op为block时,会生成以下代码。最后将二次解析后的代码写入模板缓存,然后在访问相关页面时去包含。

当上述生成的模板缓存被包含时,会去调用应用类的方法,跟进->方法。

该方法根据传入的参数到数据库中查询php代码审计视频教程,然后将查询结果转换成变量,然后走到,也就是前面那个代码注入的点,但这里存在漏洞的点不是这,原因在于,$data是从模板中提取出来的,而模板的内容我们是不可控的,继续往下走,进到$方法。

如果$变量不为空,则将$的内容写入///block/$id.php

如果$的值为空,则根据$id到数据库中取出字段的内容,并写入///block/$id.php文件中,如果能同时控制$id和$,或者能控制数据库中的内容,就可以构造一个恶意文件,然后利用上面的pc标签解析功能包含该文件,实现代码执行。

回到前面的模板解析步骤,分析具体的解析规则。

通过分析上面的正则可得知,pc标签的格式应该为{pc:xxxxx}。

在self::方法中将$data按照116行的正则再进行一次提取,将提取的结果通过循环,写到$datas数组中。所以,pc标签的格式应该为{pc:xx xx=xx}。

当$op等于block时,将前面提取的$datas传入方法,转成array(key=>value)这种格式,然后生成以下代码。所以,如果想进入以下分支,pc标签的格式应该为{pc:block xx=xx}。

继续跟进$->tag方法。

发现会将$data

‘pos’

带入数据库查询,如果结果为空,就不会进入到包含点。所以,pc标签的格式应该为{pc:block pos=xx},通过搜索pc标签找到相关触发点。

根据前面的分析,可得知,触发点在link模块下,在link模块的index控制器中找到的方法。

但仅有触发点还不够,前面提到,被包含的文件的内容从数据库中获取,所以还需要找到一个讲恶意代码写入数据库的点,或者找一处调用了->方法的点,但id和参数需可控。如果想找写入数据库的点,可以优先到与类位于同一个模块的类下找。

经过一番寻找,发现add方法有写入数据库的操作,但并没有发现写入字段的代码。除了插入数据库,还可以找找更新数据库的点。

发现在方法中执行了操作,还会将写入数据库,同时还是从post传入。146行处虽然有调用方法,但$id并不可控,原因是,在128行将id带入到数据库中查询,如果查询结果为空,则不会进入到下面的操作。而id在数据库中是递增的,未必能控制在

1、2、3

中。

但可以先利用add方法添加一条记录,然后利用将恶意代码写入数据库,最后通过访问相关页面触发pc标签解析,生成并包含恶意文件。

漏洞利用思路:

漏洞触发流程:

漏洞利用过程:

先向数据库中添加一条记录,pos的值须在中,type的值为2,登录后自动生成,需替换成当前登录用户的。

URL:

POST:=&name=bb&type=2

然后更新数据库记录将恶意代码写入数据库,从上一条请求的放回结果中获取id。

URL:

POST: =&=php ();?>

访问触发pc标签解析,包含恶意文件。

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » PHP代码审计实战思路浅析

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们