*本文原创作者:ForrestX386,本文属FreeBuf原创奖励计划,未经许可禁止转载
严正声明:本文仅限于技术讨论与学术学习研究之用,严禁用于其他用途(特别是非法用途,比如非授权攻击之类),否则自行承担后果,一切与作者和平台无关,如有发现不妥之处,请及时联系作者和平台。
0x00 前言
给开发的同学们进行不定期的安全培训是安全建设中不可缺少的一环,也是非常重要的一环。以我的经验来看,安全培训或者说安全科普不能教条化,不能书面化,必须得动手实践,结合实例分析演示给他们看,这样才能他们信(xing)服(fu),也才能达到预期的效果。本人曾粗浅的分析过Yii框架中常见SQL操作方法源码实现,以此向开发同学们阐述哪些SQL方法是安全的,哪些是不安全,使其在开发中编写更安全的代码,也曾取得不错的效果。近期有空,总结一下当时培训的内容,于是有了本文。
0x01 CDbCriteria 中的addSearchCondition 为什么比addCondition 更安全
CDbCriteria中的addSearchCondition 可以防止SQL注入,而addCondition 不能,跟着我一起走进Yii框架的源码中一探究竟
1)addCondition 方法源码分析
可以看到addCondition 并没有对传入的查询条件进行任何过滤,存在SQL注入风险
2)addSearchCondition 方法源码分析
可见addSearchCondition 对传入的查询条件(keywords)进行了参数绑定, 绑定的参数是:
self::PARAM_PREFIX.self::$paramCount++
其中 self::PARAM_PREFIX 和 self::$paramCount 的定义如下:
const PARAM_PREFIX=':ycp';
public static $paramCount=0;
所以addSearchCondition 不存在SQL注入风险
与addSearchCondition 同样内置参数绑定的方法还有compare、addBetweenCondition、addInCondition
小结:addSearchCondition 不存在SQL注入风险,addCondition 存在SQL注入风险
0x02 CActiveRecord->save 方法的安全性分析
在对公司内部代码进行安全审计的时候发现很多处都是直接调用CActiveRecord->save() 对于前端传来的数据进行保存或更新,但未对传来的数据进行任何过滤,最开始很好奇,这样难道就不会有注入吗?(insert 型 or update型),使用SQLMAP一顿狂注之后无果,没有注入,更加好奇了,于是开始分析其源码,探究为啥这样没有SQL注入风险,以下是分析过程:
CActiveRecord 中save方法的定义:
首先判断model 是否需要根据model中定义的rules对属性值进行校验(默认是需要校验的),校验通过,则判断是否为新记录,若是新记录就插入到数据库(调用insert方法),若不是新记录,就更新相应的记录(调用update方法),我们以insert 方法为例进行分析(update方法类似):
$builder->createInsertCommand($table,$this->getAttributes($attributes)); 这行代码比较关键,我们跟一下
代码位于 CDbCommandBuilder.php 中的CDbCommandBuilder class中,如下:
代码里面对传入的参数进行了参数绑定和类型转换,如下:
$placeholders[]=self::PARAM_PREFIX.$i;
$values[self::PARAM_PREFIX.$i]=$column->typecast($value);
而且还利用$column->typecast($value) 进行类型转换(其中$column为CDbColumnSchema 对象)
typecast 的定义:
小结:方法在更新数据前(不论是插入还是更新)都会对属性进行校验,然后在构造更新SQL的时候进行参数绑定,并且根据列的类型进行类型转换,所以是可以防止SQL注入的
0x03 CDbCriteria 中的条件属性limit、offset 安全性分析
经常看到代码中如是写代码:
CDbCriteria->limit = xxx;
CDbCriteria->offset = xxx
设置好过滤条件之后,调用findAll之类的方法进行查询,这些xxx 没有任何过滤,这样到底会不会有SQL注入呢
这里以调用model的findAll 方法为例跟进分析:
findAll 最后会调用query,$criteria 是其参数之一, 我们跟一下方法query
query 方法会调用createFindCommand方法,我们再跟一下createFindCommand方法
代码到最后会调用applyLimit方法,这里是我们需要关注的方法, 我们跟一下applyLimit方法
小结: 我们可以看到 用户传入的参数$criteria->limit、$criteria->$offset 已经被做了强制类型转换,不存在SQL注入
0x04 CDbCriteria 条件属性order、group、having、join安全性分析
分析过程同0x03,区别在于0x03是applyLimit,而order、group、having、join对应的方法分别如下:
从代码中可见,通过order、group、having、join属性传入的数据没有任何过滤,存在注入风险
小结: order、group、having、join对传入的数据均未做任何安全过滤处理,存在SQL注入风险
0x05 总结
个人觉得安全不能停留在嘴上,必须动手实践,黑哥说的好,整就牛!安全培训也一样,必须配以图文并茂的演示案例才能让开发们信服,也才能达到预期的培训效果。大家如果在安全培训上有更好的经验心得,也不妨分享一下。
*本文原创作者:ForrestX386,本文属FreeBuf原创奖励计划,未经许可禁止转载