前言

先知上一个大佬挖的洞,也有了简单的分析

https://xianzhi.aliyun.com/forum/topic/2135

我自己复现分析过程,漏洞的原理比较简单,但是漏洞的利用方式对我而言则是一种新的利用方式。本文对分析过程做一个记录。

正文

分析软件运行的流程

拿到一个需要分析的 php 程序,首先看看客户端的 http 请求是如何对应到程序中的代码的。

首先得找一个分析的开始点,就以 触发漏洞 的 请求为示例把。

GET /cash/block-printTradeBlock.html?param=eyJvcmRlckJ5IjoiaWQgbGltaXQgMCwxO3NlbGVjdCBpZigxPTIsMSxzbGVlcCgyKSkjIiB9 HTTP/1.1
Host: hack.ranzhi.top
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=2c17fafndhnfle6j4r9dskopk3; lang=zh-cn; theme=default; rid=kcvhkos22q574sqdjiha39icl5; keepLogin=false; XDEBUG_SESSION=14822
Connection: close

安装系统时我们设置 www 目录为虚拟主机目录, 所以当我们访问 /cash/block-printTradeBlock.html  时,实际上访问的是 www/cash/block-printTradeBlock.html, 但是 cash 目录中并没有相关的文件

不过该目录下有 .htaccess 文件,通过该文件可以重写 url, 根据规则我们知道,如果访问 cash 目录下不存在的文件,会把请求交给 index.php 处理。

.htaccess 文件参考

http://t.cn/REFVyCJ
https://www.zybuluo.com/phper/note/73726

那下面就分析 index.php 即可,下好断点,然后发送数据包

f7 跟进 loader.php, 首先加载了一些基础类。

然后做一些初始化的操作,实例化一些基础对象,后面用来加载程序的主体

然后是设置路由方式

$app->parseRequest();

会对 处理后 url- 分割,第一项作为 module_name 第二项作为 method_name. 以上面的数据包为例。执行完后的结果如下。

此时我们已经设置好了 模块名 和 方法名,  下面回到 loader.php

$common->checkPriv();  # 权限校验
$app->loadModule(); #  加载相关模块的方法

进入 loadModule 方法


public function loadModule()
{
$appName = $this->appName;
$moduleName = $this->moduleName;
$methodName = $this->methodName; /*
* 设置control的类名。
* Set the class name of the control.
**/
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; /*
* 创建control类的实例。
* 根据 `$app->parseRequest()` 设置好的 模块名 实例化对应的类
* Create a instance of the control.
**/
$module = new $className();
$this->control = $module; /*
* 使用反射机制获取函数参数的默认值
* 通过反射获取 函数的参数名称,
* 通过 `php` 的反射机制 , 获取参数名, 并且初始化好
*
* */
$defaultParams = array();
$methodReflect = new reflectionMethod($className, $methodName);
foreach($methodReflect->getParameters() as $param)
{
$name = $param->getName(); $default = '_NOT_SET';
if(isset($paramDefaultValue[$appName][$className][$methodName][$name]))
{
$default = $paramDefaultValue[$appName][$className][$methodName][$name];
}
elseif(isset($paramDefaultValue[$className][$methodName][$name]))
{
$default = $paramDefaultValue[$className][$methodName][$name];
}
elseif($param->isDefaultValueAvailable())
{
$default = $param->getDefaultValue();
} $defaultParams[$name] = $default; # 组成一个由 defaultParams[参数名] = "" 构成的字典
} /**
* 根据PATH_INFO或者GET方式设置请求的参数。
        * 根据请求方式, 从请求数据包中获取需要的参数信息。
*/
if($this->config->requestType != 'GET')
{
$this->setParamsByPathInfo($defaultParams);
}
else
{
$this->setParamsByGET($defaultParams);
}        # 过滤数据
       if($this->config->framework->filterParam == 2)
{
$_GET = validater::filterParam($_GET, 'get');
$_COOKIE = validater::filterParam($_COOKIE, 'cookie');
} /* 调用方法,并传入参数 */
call_user_func_array(array($module, $methodName), $this->params);
return $module;
}

该函数的流程为

  • 根据 $app->parseRequest() 设置好的 模块名 实例化对应的类
  • 通过 php 的反射机制 , 获取方法参数名, 并且初始化好
  • 根据请求方式, 从请求包中获取需要的参数信息到 $defaultParams
  • 过滤数据
  • 调用方法,并传入参数

    看一看设置参数的方式

按照 -  分割 url格式为

module_name-method_name-param1-param2

所以在该程序中 wwwapp 目录是相互对应的。

当我们请求

/dir_name/module_name-method_name-param-...-paramN.html

最后会调用 app 目录下 module_name 中的 control.php

module_name->method_name(param1,....,paramN)

比如

/cash/block-printTradeBlock.html

实际就是调用 app 目录下 cash 中的 control.php

block->printTradeBlock()

SQL 注入分析

漏洞出现在 lib/base/dao/dao.class.php

这里只对 $order 部分进行了校验, 而没有对 limit 后面的部分进行校验。

看到 printTradeBlock

$this->processParams() 中设置好 $this->params

可以看到 $this->params 就是 json_decode(base64_decode($_GET['param']))

然后又会调用

orderBy($this->params->orderBy)

所以我们可以控制 limit 后面的部分, SQL注入

这套程序中还会执行 sql 语句,用的是 Pdo用的是 $pdo->query(), 这个函数可以一次执行多条 sql 语句。

  /**
* 执行SQL语句,返回PDOStatement结果集。
* Query the sql, return the statement object.
*
* @access public
* @return object the PDOStatement object.
*/
public function query($sql = '')
{
/* 如果有错误,返回一个空的PDOStatement对象,确保后续方法能够执行。*/
/* If any error, return an empty statement object to make sure the remain method to execute. */
if(!empty(dao::$errors)) return new PDOStatement(); if($sql)
{
$sql = trim($sql);
$sqlMethod = strtolower(substr($sql, 0, strpos($sql, ' ')));
$this->setMethod($sqlMethod);
$this->sqlobj = new sql();
$this->sqlobj->sql = $sql;
}
else
{
$sql = $this->processSQL(); // 大概就是获取 sql 语句
}
$key = md5($sql); try
{
$method = $this->method;
$this->reset(); if($this->slaveDBH and $method == 'select')
{
if(isset(dao::$cache[$key])) return dao::$cache[$key];
$result = $this->slaveDBH->query($sql);
dao::$cache[$key] = $result;
return $result;
}
else
{
if($this->method == 'select')
{
if(isset(dao::$cache[$key])) return dao::$cache[$key];
$result = $this->slaveDBH->query($sql);
dao::$cache[$key] = $result;
return $result;
} return $this->dbh->query($sql);
}
}
catch (PDOException $e)
{
$this->sqlError($e);
}
}

这样我们的利用方式就简单了。

  • 闭合 limit 语句,用 ;  连接多条语句
  • 没有回显, 使用 时间盲注

poc

任意文件下载 && 任意文件删除

由于可以一次执行多条 sql 语句 ,我们实质上已经可以控制数据库了。

app/sys/file/control.php ,有两个函数  deletedownload, 分别用于删除文件和下载文件。

以  delete 为例

$this->file->getById($fileID)  时间就是在 表前缀sys_file 中查找对应 id 相对应的 路径。

利用 sql 注入修改为目标路径(用 ../ 进行目录跳转),然后选择相应 id 即可删除指定文件。下载文件也是类似。

getshell

删除 my.php 后 会要求我们重新安装系统。

在重装系统的最后一步,会直接使用 POST 中的值,来设置 my.php 的内容,同时 , 访问 install.php 时,是不会调用参数过滤的函数的

所以可以注入 php 代码,getshell

然之协同系统6.4.1 SQL注入导致getshell的更多相关文章

  1. 然之协同系统6.4.1 SQL注入之exp编写

    前言 前面已经说明了 漏洞成因,这里介绍一下 exp 的编写. 正文 为了 getshell 或者是 任意文件下载, 我们需要修改 数据库中的 前缀sys_file 表, 所以我们的利用方式如下 使用 ...

  2. 一次SQL注入导致的"越权"

    原文来自SecIN社区-作者:tkswifty 相关背景   在实际的业务开发中,SQL交互往往是业务系统中不可或缺的一项.在Java中提供了类似Mybatis.Hibernate.SpringDat ...

  3. SQL注入到getshell

    SQL注入到getshell 通过本地 pikachu来复现  前提: 1.存在SQL注入漏洞 2.web目录具有写入权限 3.找到网站的绝对路径 4.secure_file_priv没有具体值(se ...

  4. [代码审计]某租车系统JAVA代码审计[前台sql注入]

    0x00 前言 艰难徘徊这么久,终于迈出第一步,畏畏缩缩是阻碍大多数人前进的绊脚石,共勉. 系统是租车系统,这个系统是Adog师傅之前发在freebuf(http://www.freebuf.com/ ...

  5. [漏洞案例]thinkcmf 2.x从sql注入到getshell实战

    0X00 前言 这个案例是某项目的漏洞,涉及敏感的地方将会打码. 很久没更新博客了,放一篇上来除除草,新的一年会有所转变,以后会有更多领域的研究. 下面是正文 0X01 正文 某厂商某个网站用的是th ...

  6. ZZZPHP1.61 代码审计-从SQL注入到Getshell

    近期有很多小伙伴在后台留言想看关于代码审计的文章,其实有关审计的文章网上资源是比较多的,但是从代码审计开始到结束的这类文章却少之甚少. 今天要讲解的ZZZPHP1.61这套审计漏洞比较多,SQL注入漏 ...

  7. sql参数化防止sql注入导致的暴露数据库问题

    #转载请联系 假如你在京东工作,你要做的任务就是做一个商品搜索的东西供用户使用. 然后你写出了这么一个程序的雏形. import pymysql def main(): conn = pymysql. ...

  8. 卧槽,sql注入竟然把我们的系统搞挂了

    前言 最近我在整理安全漏洞相关问题,准备在公司做一次分享.恰好,这段时间团队发现了一个sql注入漏洞:在一个公共的分页功能中,排序字段作为入参,前端页面可以自定义.在分页sql的mybatis map ...

  9. 了解SQL注入攻击

    SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,这是SQL注入的标准释义. 随着B/S模式被广泛的应用,用这种模式编写应用程序的程序员也越来越多,但由于开发人员的水 ...

随机推荐

  1. axiso 生产环境跨域配置(可用)

    1.npm install axios 后 在main.js中import import Axios from 'axios'Vue.prototype.$http = Axios 2.请求配置 th ...

  2. 求幂大法,矩阵快速幂,快速幂模板题--hdu4549

    hdu-4549 求幂大法.矩阵快速幂.快速幂 题目 M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 ...

  3. java transient 和Volatile关键字

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...

  4. 关于Java的权限修饰符(public,private,protected,默认friendly)

    以前对访问修饰符总是模棱两可,让自己仔细解释也是经常说不很清楚.这次要彻底的搞清楚. 现在总结如下: 一.概括总结 各个访问修饰符对不同包及其子类,非子类的访问权限 Java访问权限修饰符包含四个:p ...

  5. Map集合的四种遍历方式(转载)

    import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class TestMap { pu ...

  6. C# 多线程系列之异步回调(委托)

    本文参考自C#基础:线程之异步回调(委托),纯属读书笔记 在解析异步回调之前,先看同步回调的执行过程,以及代码原理. 1.线程的同步执行 同步执行:在主线程执行的时候,主线程调用一个其它方法,此时主线 ...

  7. Go语言学习笔记二: 变量

    Go语言学习笔记二: 变量 今天又学了一招如何查看go的版本的命令:go version.另外上一个笔记中的代码还可以使用go run hello.go来运行,只是这种方式不会生成exe文件. 定义变 ...

  8. 有关索引的DMV

    转自:http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html#commentform 有关索引的DMV 1.查看那些被大量更新, ...

  9. R语言 删除变量rm函数

    变量可以通过使用 rm()函数来删除.下面我们删除变量var.3.然后再打印变量时出现异常错误. rm(var.3) print(var.3) 当上面的代码执行时,它产生以下结果: [1] " ...

  10. 注解完成spring json返回数据格式配置

    import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.module.Simp ...