style="display:block;padding:0px 10px;" class="ContentFont">文章作者:记忆碎片
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
已经很久没有在这圈里转悠了,有点开始脱节了,也不知道有没有人用过相同的方法(估计也没我这么恶心的人),如果有请首创者多多见谅,
一次恶心而诡异的SQL拒绝服务攻击
。事情是这样,前几天去巴黎,约一个兄弟酒馆吹牛,他刚给学院设计了一个PHP+MySQL的公告板系统,号称在Web层面上是无懈可击的。这算是个Challenge吧,我就拿了他的源代码过来读,在针对XSS和SQL Injection方面的功夫算是做足了,一个典型的瓶颈设计:所有的查询经过 "db" 类的 "query()" 函数,query函数调用sec_check对所有的用户输入进行安全检查,确认无误后再执行mysql_query。
sec_check函数进行类型检查,编码检查,敏感字符过滤一堆一堆的项目,反正是为了安全豁出效率去了,至少在我的水平层面上已经看不出有什么破绽。不过他的一段“发布帖子”功能设计让我觉得很有趣(示范代码片断):
//此处省略一堆代码
$columns = $values = "";
foreach($_GET as $key=>$value)
{
sec_check($key); //对键进行安全检查
sec_check(%value); //对值进行安全检查
$columns .= $key.","; //要插入的字段列表
$values .= $value.","; //要插入的值列表
}
//这里trim掉最后的"," 省略...
mysql_query("INSET INTO posts( {$columns} ) VALUES( {$values} )");
他为了省事,也怕需要构造太长的查询语句而遍历所有$_GET数组的元素,用键名和值自动构造查询语句进行修改记录的操作,同样的代码也出现在 “注册会员”功能中,
电脑资料
《一次恶心而诡异的SQL拒绝服务攻击》(https://www.unjs.com)。这貌似没什么可玩的,因为sec_check已经把安全检查做到了位,不过……嘿嘿,我再三确定,只要我能有效地破坏他的程序,今天的酒钱他得来付,他说任何"攻击"都可以,只要在web层面。那就别怪我恶心了。通过观察数据库的表结构,发现'id'是一个自增唯一编号主键,类型为MEDIUMINT 为了简单起见我们就假设他是TINYINT 反正原理都一样, 这个类型的取值范围是1-255(好像不会从0开始编号, 习惯了C没办法...)。而且SQL有一个特性, 主键不允许重复, 自增列会根据最大的那个ID继续++进行编号。
哪有什么用呢? ID一般不会被大家考虑在可利用的字段内。但是,因为这个程序的逻辑设计问题,如果我们提交了一个名为id的字段,那个插入的新纪录的id字段就是我们制定的值了。那么我们构造URL: localhost/newpost.php?id=255&title=something..... 这样一个新的帖子的ID就是255。
255已经到达TINYINT类型的上限, 如果再有人要发帖子, SQL就会出错. 成功D.O.S了该系统!
不仅仅是INSERT, 继续读代码, 同样逻辑还出现在“编辑用户资料”功能中,但是这次他的UPDATE语句是这样的:
UPDATE SET {$key} = {$value} WHERE id = {$_SESSION['ID']}
还好是session (也是标准做法)要是直接从表单取ID值倒直接可以改任意用户密码了(好像2006年的时候一个论坛就出过这种漏洞)。 同样的方法构造一个 id=上限 的查询,新用户也就别想注册了(把id放在查询的最后一项, 不然前面的查询也出错了)。
我这凌晨2:43 从巴黎折腾回来没多久, 要是写的有什么纰漏 请大家指正