注入以及防护sql注入

文章介绍了SQL注入的几种方法,包括宽字节注入、TIMINGATTACK、SQLColumnTruncation和XML注入,强调学习思路的重要性。同时,提出了防御SQL注入的策略,如使用预编译语句、存储过程、严格数据类型检查以及使用安全编码函数。
摘要由CSDN通过智能技术生成

前言:对于常见的注入方法我们都已经知道,但是大家有没有想到过,这些东西早就被玩烂了呢?(我朋友也如此提醒我)虽然我讲的东西也被用烂了,但是大家请记住一点,学渗透不仅仅是只学方法,更重要的是学习这个方法的思路,这才是最重要的!

 

 

 

 

1.攻击方法

1.1宽字节注入

宽字节注入有一个限制,就是需要使用GBK编码,在讲原理之前我们先来看看如下信息

0x5c=\

0x27='

0xbf27=¿'

0xbf5c=縗

其原理为一个GBK编码的汉字会占据两个字节(bf是第一个而5c是第二个),当使用GBK编码遇到两个字节都符合其取值范围时,就会将其解析成为一个汉字,第一个字节取值范围为129-254,第二个字节范围为64-254

因此综上所述,当我们遇到反斜杠转义时,就可以在前面输入bf,就可以使其混乱,从而绕过它的转义字符。那如果是使用单引号’时,按照上例,你又该如何进行绕过呢?是的,也是在其前面输入bf。

 1.2 TIMING ATTACK

对于这种攻击方式也许有些人会感到陌生,实际上这就是我们所熟知的延时注入方式一种。

mysql数据库中存在一个函数BENCHMARK()函数,该函数是用于测试函数的性能。测试性能是什么意思呢?BENCHMARK(1,ENCODE('1','2')),这个语句是将BENCHMARK(1,ENCODE('1','2'))执行一次,可能一瞬间就完成了,姑且算它0.000001秒就完成了吧,但是大家有没有想过,如果我将这个函数执行10w次,甚至100w次,服务器响应这个请求需要多少时间?呢?BENCHMARK(100w,ENCODE('1','2'))执行时间为4.74s。这种方法替用sleep()被过滤的情况。那如果BENCHMARK()也被过滤了呢?那就需要我们深入探索MYSQL了,此外其他数据库也存在类似于BENCHMARK()的函数,MS SQL Server函数中的WAITFOR DELAY ‘0:0:5'

那我也简单的演示一下代码吧

1 union select if(substring(current,1,1) = char(120),BENCHMARK(5000000,ENCODE('MSG','by 5 seconds'),null) from (select database() as a) as table;

其中是char(120)是小写的x,目的是检测第一个字符是否为x,若是则会发生时间延迟,同理按照基本方法我们还可以得到许多东西。这里就不为大家一一演示了。

1.3 SQL Column Truncation

在mysql的配置选项里,有一个sql-mode选项,当其设置为default时,也就是将STRICT-ALL-TABLESS选项关闭,那我们输入一串超长字符串时,只会提示warning,而不是error(显示error插入不成功,warning成功插入)那如果我们insert一个和管理员名称相同的会怎么样呢?比如admin(100个空格)x,那么由于超过了原来长度限制,会自动删除后面的信息而只保留前面的信息,为什么末尾加一个x呢?要是我输入很长一串,但是服务器检测我输入的一大串都是空白,会不会给我输入那么久的东西都默认为空呢?但是我们输入x后由于x被截断,x也就不会显示在数据库里。历史上出现过一个真实案例,WordPress有个注册了超长包含admin信息的用户,好在修改密码后被及时发现,没有造成太大的危机。被发现的原因是修改密码后会发送邮件到用户邮箱里。看来做攻击还是得晚上才行。

1.4 XML

XML也是一种常见的文本标记语言,和html一样也存在注入攻击,这里为大家浅浅的讲解一下

<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
      <name>user
      </name>
      <email>输入的值
      </email>
</USER>

但是我们输入特定的语句

user@a.com</email></USER><USER role="admin_role"><name>test</name><email>user@2.com

他们拼接在一起就会变成

<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
      <name>user
      </name>
      <email>user@a.com
      </email>
</USER>
<USER role="admin_role">
      <name>test
      </name>
      <email>user@2.com
      </email>
</USER>

咦,变成两组数据了,如果是插入什么东西到数据库的话,那么这个后果不可想象!

1.5 CRLF

CRLF其实是两个字符,其中CR表示\r,LF表示\n,他们都是换行的意思。CRLF通常不同语句之间的分隔符,那么就有可能改变原有语义。

在写入日志文件时,CRLF可能会伪造一条新的记录

比如一个失效的登陆日志为

User login failed for:guest

如果没有处理换行符,那么就可以伪造一个登陆日志

User login failed for:guest
User login successed for:admin

第二条记录是伪造的,不仅仅是log上,只要是使用CRLF的,都有可能存在安全隐患,例如HTTP的头部信息,可以构造出一个XSS攻

 

击,这个后面章节会讲到。


2.防御手段

1.使用预编译语句

一般情况下,防御SQL注入的最佳方式就是使用预编译语句。如果使用预编译语句,经过拼凑后,原有语句并不会发生过多的改变。就比如用户输入“1;, or '1'='1"字符串,也只会把1;, or '1'='1当作一个整体来查询

这是PHP预编译绑定变量的示例

$query = "INSERT INTO myCity (Name, CountryCode, District) VALUES (?,?,?)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("sss",$vall,$va12,$va13);
$va11 = 'Stuttgart';
$va12 = 'DUE';
$va13 = 'Baden-Wuerttemberg';
/* Execute the statement*/
$stmt->execute*();

2.使用存储过程

使用存储过程和预编译类似,存区别在于储过程首先需要将SQL语句定义在数据库中。但是存储过程也存在注入攻击,因此我们需要尽量避免使用动态的SQL语句。要是必须使用无法避免的情况下,那么就要回到严格过滤和编码函数来处理用户的输入的数据了。

下面是一个JAVA调用存储过程的例子:

String custname = request.getParameter("customerName");
try{
   CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}");
   cs.setString(1,custname);
   ResultSet results cs.executeQuery();
   //结果集处理
}catch(SQLException se) {
   //日志记录和错误处理
}

custname来接受request.getParameter()(通过容器的实现来取得通过post,get等方式传入的数据)传递用户输入的customerName的值。

这里使用了try catch异常捕获,try中使用CallableStatement是java语句中调用存储过程,RrsultSet是结果集,是存储查询的一个对象,后面的cs.executeQuery()用来执行查询语句。

catch中的SQLException是一个提供了数据库访问错误或者其他错误信息的异常,从而获取异常信息。

3.严格查询数据类型

如下的php代码限制输入的类型只能为integer

<?php
settye($offset,'integer');
$query = "select id,name from products order by name LIMIT 20 OFFSET $offset;";

$query = sprintf("select id,name from produncts order by name LIMIT 20 OFFSET %d;"),
$offset);

?>

此外邮箱的格式,输入的时间都严格按照格式。这能有效的防范sql注入,如果需要用户提交字符串,类似输入电话号码时(字符串类型),规定其字节大小或者其他方法防范。

4.使用安全函数

上面我们讲到的一些例子能绕过编码,因此我们需要一个较为安全的编码函数。我们可以惨考OWASP ESAPI中的实现。

ESAPI.encoder().endodeForSQL( new OracleCodec(),queryparam);

这里博主没有仔细了解太多,只是知道有这么函数。总而言之,从数据库自身来说,我们应该遵守最小权限原则,避免web应用使用高权限,此外还有一点,我们一定要注意数据与代码分离

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B10SS0MS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值