这个漏洞本是2014年时候被人发现的,本着学习的目的,我来做个详细的分析。漏洞虽然很早了,新版的Drupal甚至已经改变了框架的组织方式。但是丝毫不影响对于漏洞的分析。这是一个经典的使用PDO,但是处理不当,导致SQL语句拼接从而导致注入的问题。从这个问题,以及以往我见过的很多的漏洞来看,我不得不说,代码底层做的再安全,过滤的再完全,如果程序员的一个不小心,也将会导致重大安全问题的出现。多少的编码绕过,逻辑漏洞正是不小心带来的问题。

  0x00 注入的定位

  首先我根据网络上已经出现过的EXP,然后进行追踪。无奈,这个框架实在太大,我在跟进的过程中,遇到了诸多的问题,甚至路由模式都没有搞的很明白。然后根据已有的漏洞细节,我迅速定位到了漏洞的发生点。

在文件 \modules\user\user.module 中 有 user_login_authenticate_validate() 函数,代码如下:

function user_login_authenticate_validate($form, &$form_state) {
$password = trim($form_state['values']['pass']);
if (!empty($form_state['values']['name']) && !empty($password)) {
// Do not allow any login from the current user's IP if the limit has been
// reached. Default is 50 failed attempts allowed in one hour. This is
// independent of the per-user limit to catch attempts from one IP to log
// in to many different user accounts. We have a reasonably high limit
// since there may be only one apparent IP for all users at an institution.
if (!flood_is_allowed('failed_login_attempt_ip', variable_get('user_failed_login_ip_limit', 50), variable_get('user_failed_login_ip_window', 3600))) {
$form_state['flood_control_triggered'] = 'ip';
return;
}
$account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $form_state['values']['name']))->fetchObject(); //省略无关代码...

很明显,这里的SQL查询就是漏洞触发现场了,我们跟进db_query这个函数,代码如下:

function db_query($query, array $args = array(), array $options = array()) {
if (empty($options['target'])) {
$options['target'] = 'default';
} return Database::getConnection($options['target'])->query($query, $args, $options);
}

继续跟进query函数:

  public function query($query, array $args = array(), $options = array()) {

    // Use default values if not already set.
$options += $this->defaultOptions(); try {
// We allow either a pre-bound statement object or a literal string.
// In either case, we want to end up with an executed statement object,
// which we pass to PDOStatement::execute.
if ($query instanceof DatabaseStatementInterface) {
$stmt = $query;
$stmt->execute(NULL, $options);
}
else {
$this->expandArguments($query, $args);
$stmt = $this->prepareQuery($query);
$stmt->execute($args, $options);
}
//省略无关代码...

我们知道,如果在PHP连接MySQL数据库中,如果我们使用PDO进行预编译的话,我们的语句是无法改变原有的查询结构的,也就是说,注入的语句,无法进行查询,只能是当做字符串。从而从数据库查询层对注入做了彻底防御。那么这里是怎么产生问题的呢?

0x01 错误的处理导致的安全问题

但是这里有个问题,就是当参数是数组的时候,就会用到expandArguments这个方法,然后这个方法由于处理不当会导致安全问题。

函数代码如下:

  protected function expandArguments(&$query, &$args) {
$modified = FALSE; // If the placeholder value to insert is an array, assume that we need
// to expand it out into a comma-delimited set of placeholders.
foreach (array_filter($args, 'is_array') as $key => $data) {
$new_keys = array();
foreach ($data as $i => $value) {
// This assumes that there are no other placeholders that use the same
// name. For example, if the array placeholder is defined as :example
// and there is already an :example_2 placeholder, this will generate
// a duplicate key. We do not account for that as the calling code
// is already broken if that happens.
$new_keys[$key . '_' . $i] = $value;
} // Update the query with the new placeholders.
// preg_replace is necessary to ensure the replacement does not affect
// placeholders that start with the same exact text. For example, if the
// query contains the placeholders :foo and :foobar, and :foo has an
// array of values, using str_replace would affect both placeholders,
// but using the following preg_replace would only affect :foo because
// it is followed by a non-word character.
$query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query); // Update the args array with the new placeholders.
unset($args[$key]);
$args += $new_keys; $modified = TRUE;
} return $modified;
}

我们再来回顾一下之前的查询语句,

db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $form_state['values']['name']))

这个数组我们是可控的,首先在array_filter之后,使用foreach进行遍历,然后二轮遍历中创建了一个新的数组。接着把$query变量中的键,进行了替换,替换掉以后的内容是之前新数组键用 ', '进行合并成的一个新的字符串。这样我们通过键来进行SQL注入就行的通了。注入语句将会通过拼接进入。

0x03 测试

可以看得很清楚,name数组中的两个键都被拼接进了SQL查询。

0x04 反思

这里是挺有意思,也很常见的一个问题。我在开头的引言中也说了。本来是做好了处理的,但是却使用了拼接,导致可控的外部数据进入了SQL查询。类似这样的问题还很常见,当然了,这也为自己挖洞提供了思路,在挖洞越来越困难的当下,挖洞思路的变化显得十分重要了。

  

Drupal V7.3.1 框架处理不当导致SQL注入的更多相关文章

  1. 管中窥豹——框架下的SQL注入 Java篇

    管中窥豹--框架下的SQL注入 Java篇 背景 SQL注入漏洞应该算是很有年代感的漏洞了,但是现在依然活跃在各大漏洞榜单中,究其原因还是数据和代码的问题. SQL 语句在DBMS系统中作为表达式被解 ...

  2. 最新版SEMCMS_PHP_3.5 过滤不严导致sql注入

    一.漏洞分析 在分析过程中看到网上已经有人发现semcms V2.4存在过滤不严导致sql注入的漏洞,不知道咋还没改,而且最新版过滤的关键字更少了. 首先查看首页文件index.php的代码 < ...

  3. 浅析PHP框架Laravel最新SQL注入漏洞

    PHP知名开发框架Laravel,之前在官方博客通报了一个高危SQL注入漏洞,这里简单分析下. 首先,这个漏洞属于网站coding写法不规范,官方给了提示: 但官方还是做了修补,升级最新版本V5.8. ...

  4. dedecms SESSION变量覆盖导致SQL注入漏洞修补方案

    dedecms的/plus/advancedsearch.php中,直接从$_SESSION[$sqlhash]获取值作为$query带入SQL查询,这个漏洞的利用前提是session.auto_st ...

  5. 代码审计-Thinkphp3框架EXP表达式SQL注入

    最近看java框架源码也是看的有点头疼,好多还要复习熟悉 还有好多事没做...慢慢熬. 网上好像还没有特别详细的分析 我来误人子弟吧. 0x01 tp3 中的exp表达式 查询表达式的使用格式: $m ...

  6. yii框架各种防止sql注入,xss攻击,csrf攻击

    PHP中常用到的方法有: /*  防sql注入,xss攻击  (1)*/    function actionClean($str)    {        $str=trim($str);      ...

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

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

  8. 【漏洞复现】CVE-2022–21661 WordPress核心框架WP_Query SQL注入漏洞原理分析与复现

    影响版本 wordpress < 5.8.3 分析 参考:https://blog.csdn.net/qq_46717339/article/details/122431779 在 5.8.3 ...

  9. Java SQL注入学习笔记

    1 简介 文章主要内容包括: Java 持久层技术/框架简单介绍 不同场景/框架下易导致 SQL 注入的写法 如何避免和修复 SQL 注入 2 JDBC 介绍 JDBC: 全称 Java Databa ...

随机推荐

  1. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  2. SLAM拾萃(2):doxygen

    今天给大家介绍一下doxygen.这个工具由来已久了,至少08年左右就已经在用了,但是目前还没见到好的介绍.我个人觉得这是个很简单易用的工具,但是为什么看了别人介绍反而觉得复杂了……所以趁着今天比较闲 ...

  3. 打开Android Studio时报Unable to access Android SDK add-on list

    第一次安装Android studio时候弹出unable to access android sdk add-on list原因是你电脑没有SDK而且你下载的android studio又是不带SD ...

  4. 数据结构(c语言版)文摘

    第一章  绪论 数据结构:是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科. 数据:是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理 ...

  5. apicloud 和 微信小程序,你会用哪 个?

    微信 小程序开始火了,app跨平台的革命再次高涨,不得不说,不用再担心android和ios双版本开发成本,及h5的开发 和apicloud一样,不需要关注平台问题,只需要关注前端js.css就能大a ...

  6. 超详细JSON解析步骤

    JSON简介 JAVAScript Object Notation是一种轻量级的数据交换格式 具有良好的可读和便于快速编写的特性. 业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了 ...

  7. FNDLOAD Commands to Download Different Seed Data Types. (DOC ID 274667.1)

    In this Document Goal Solution References Applies to: Oracle Application Object Library - Version 11 ...

  8. FMX.Platform.TApplicationEvent

    FMX.Platform.TApplicationEvent http://docwiki.embarcadero.com/Libraries/Seattle/en/FMX.Platform.TApp ...

  9. [转]解决Mysql InnoDB: Failing assertion: ret || !assert_on_error问题

    国庆回来后,发现mysql停止服务了,没办法继续启动了.查看日志,看到: 131008 09:56:03 mysqld_safe Starting mysqld daemon with databas ...

  10. aspnetPage分页控件

    项目里面有一个分页,刚好知道了aspnetPage分页控件,现在就把实现步骤和代码贴出来分享一下,如有错误欢迎指正. http://www.webdiyer.com  该控件原网址.里面文档 1.首先 ...