SQL注入往往是在程序员编写包含用户输入的动态数据库查询时产生的,但其实防范SQL注入的方法非常简单。程序员只要a)不再写动态查询,或b)防止用户输入包含能够破坏查询逻辑的恶意SQL语句,就能够防范SQL注入。在这篇文章中,我们将会说明一些非常简单的防止SQL注入的方法。

我们用以下Java代码作为示例,

String query ="SELECT account_balance FROM user_data WHERE user_name ="

  + request.getParameter("customerName");

try {

Statement statement  = connection.createStatement( …);

ResultSet results = Statement.executeQuery(query);

}

在以上代码中,我们可以看到并未对变量customerName做验证,customerName的值可以直接附在query语句的后面传送到数据库执行,则攻击者可以将任意的sql语句注入。

防范方法1:参数化查询

参数化查询是所有开发人员在做数据库查询时首先需要学习的,参数化查询迫使所有开发者首先要定义好所有的SQL代码,然后再将每个参数逐个传入,这种编码风格就能够让数据库辨明代码和数据。

参数化查询能够确保攻击者无法改变查询的内容,在下面修正过的例子中,如果攻击者输入了UsrID是“’or ‘1 ‘=’1”,参数化查询会去查找一个完全满足名字为‘or ‘1 ‘=’ 1的用户。

对于不同编程语言,有一些不同的建议:

Java EE——使用带绑定变量的PreparedStatement();

.Net——使用带绑定变量的诸如SqlCommand()或OleDbCommand()的参数化查询;

PHP——使用带强类型的参数化查询PDO(使用bindParam());

Hibernate——使用带绑定变量的createQuery()。

Java示例:

String custname = request.getParameter("customerName");

String query ="SELECT account_balance FROM user_data WHERE user_name= ?";

PreparedStatement pstmt = connection.prepareStatement(query);

Pstmt.setString(1,custname);

ResultSet results = pstmt.executeQuery();

C# .Net示例:

String query ="SELECT account_balance FROM user_data WHERE user_name = ?";

Try {

OleDbCommand command = new OleDbCommand(query,connection);

command.Parameters.Add(new OleDbParameter("customerName",CustomerName.Text));

OleDbDataReader reader = command.ExecuteReader();

}catch (OleDbException se){

//error handling

}

防范方法二:存储过程

存储过程和参数化查询的作用是一样的,唯一的不同在于存储过程是预先定义并存放在数据库中,从而被应用程序调用的。

Java存储过程示例:

String custname = request.getParameter("customerName");

try {

CallableStatement cs = connection.prepareCall("call sp_getAccountBalance(?)}");

cs.setString(1,custname);

Result results = cs.executeQuery();

}catch(SQLException se){

//error handling

}

VB .Net存储过程示例:

Try

Dim command As SqlCommand = new SqlCommand("sp_getAccountBalance",connection)

command.CommandType = CommandType.StoredProcedure

command.Parameters.Add(new SqlParameter("@CustomerName",CustomerName.Text))

Dim reader As SqlDataReader = command.ExecuteReader()

‘…

Catch se As SqlException

‘error handling

End Try

防范方法三:对所有用户输入进行转义

我们知道每个DBMS都有一个字符转义机制来告知DBMS输入的是数据而不是代码,如果我们将所有用户的输入都进行转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注入了。

当然,如果要采用这种方法,那么你就需要对所使用的数据库转义机制,也可以使用现存的诸如OWASP ESAPI的escaping routines。ESAPI目前是基于MySQLOracle的转义机制的,使用起来也很方便。一个Oracle的ESAPI的使用示例如下:

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

那么,假设你有一个要访问Oracle数据库的动态查询代码如下:

String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+req.getParameter("userID")+"’ and user_password = ‘"+req.getParameter("pwd")+"’";

try {

Statement statement = connection.createStatement(…);

ResultSet results = statement.executeQuery(query) ;

}

那么,你就必须重写你的动态查询的第一行如下:

Codec ORACLE_CODEC = new OracleCodec();

String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+

ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("userID"))+"’ and user_password = ‘"+

ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("pwd"))+"’";

当然,为了保证自己代码的可读性,我们也可以构建自己的OracleEncoder:

Encoder e = new OracleEncoder();

String query ="SELECT user_id FROM user_data WHERE user_name = ‘"

+ oe.encode(req.getParameter("userID")) +"’ and user_password = ‘"

+ oe.encode(req.getParameter("pwd"))+"’";

除了上面所说的三种防范方法以外,我们还建议可以用以下两种附加的方法来防范SQL注入:最小权限法、输入验证白名单法。

最小权限法:

为了避免注入攻击对数据库造成的损害,我们可以把每个数据库用户的权限尽可能缩小,不要把DBA或管理员的权限赋予你应用程序账户,在给用户权限时是基于用户需要什么样的权限,而不是用户不需要什么样的权限。当一个用户只需要读的权限时,我们就只给他读的权限,当用户只需要一张表的部分数据时,我们宁愿另建一个视图让他访问。

如果你的策略是都是用存储过程的话,那么仅允许应用程序的账户执行这些查询,而不给他们直接访问数据库表的权限。诸如此类的最小权限法能够在很大程度上保证我们数据库的安全。

输入验证白名单法:

输入验证能够在数据传递到SQL查询前就察觉到输入是否正确合法,采用白名单而不是黑名单则能在更大程度上保证数据的合法性。

防sql注入 盲注等措施 ESAPI的使用的更多相关文章

  1. SQL注入--盲注及报错注入

    盲注查询 盲注其实就是没有回显,不能直观地得到结果来调整注入数据,只能通过其他方式来得到是否注入成功,主要是利用了一些数据库内置函数来达到的 布尔盲注 布尔很明显Ture跟Fales,也就是说它只会根 ...

  2. SQL注入 盲注

    来源:http://www.cnblogs.com/cheatlove/articles/384233.html SQL注入攻击: (1) 脚本注入式的攻击(2) 恶意用户输入用来影响被执行的SQL脚 ...

  3. SQL注入----盲注总结

    参考文章:https://mp.weixin.qq.com/s?__biz=MzIzMTc1MjExOQ==&mid=2247490388&idx=1&sn=c677837d7 ...

  4. 关于sql注入盲注,谈谈自己的心得

    1.没做防御的站点,拿上sqlmap直接怼就行了. 2.做了防御,有的用函数过滤了,有的用了waf(比如安全狗,云锁,华为云waf,360waf,知道创宇盾,护卫神等等) 这些就相当麻烦了,首先要探测 ...

  5. PHP防SQL注入不要再用addslashes和mysql_real_escape_string

    PHP防SQL注入不要再用addslashes和mysql_real_escape_string了,有需要的朋友可以参考下. 博主热衷各种互联网技术,常啰嗦,时常伴有强迫症,常更新,觉得文章对你有帮助 ...

  6. Sqlparameter防SQL注入

    一.SQL注入的原因 随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对 ...

  7. 【荐】PDO防 SQL注入攻击 原理分析 以及 使用PDO的注意事项

    我们都知道,只要合理正确使用PDO,可以基本上防止SQL注入的产生,本文主要回答以下几个问题: 为什么要使用PDO而不是mysql_connect? 为何PDO能防注入? 使用PDO防注入的时候应该特 ...

  8. C#语言Winform防SQl注入做用户登录的例子

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  9. mysql之数据库连接的方法封装及防sql注入

    一.定义数据库和表 create database animal; CREATE TABLE `pet` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name ...

随机推荐

  1. 【UML】UML图的发展和体系结构

    导读:上次给徒弟验收UML的项目,在验收的时候提出了很多问题,徒弟也暴露了一些问题.说好我们一起总结成长的,由于最近的事儿,比较忙,所以现在进行总结.上次会议中说到要用门卫思维去总结这部分的知识点,用 ...

  2. 让Sublime Text成为静态WEB服务器:SublimeServer

    如果你使用Sublime Text作为你的编辑器,那么在进行HTML和Java开发的时候有一个很有用的功能,帮你完成前端的联调测试,那就是Sublime Text的服务器插件:SublimeServe ...

  3. BZOJ 2134 单选错位 ——期望DP

    发现概率是∑1/两道题答案相同的概率, 稍加化简 #include <map> #include <ctime> #include <cmath> #include ...

  4. UVA 11297 Census ——二维线段树

    [题目分析] 二维线段树模板题目. 简直就是无比的暴力.时间复杂度为两个log. 标记的更新方式比较奇特,空间复杂度为N^2. 模板题目. [代码] #include <cstdio> # ...

  5. POJ 1006 生理周期【数论】

    这题是有中文版的(右上角选项卡里把default改成简体中文)然后看到他把biorhythms翻成生理周期我可耻的笑了......23333 如果没有限定从日期d开始,完全可以从第一天起开始计时,因此 ...

  6. 解决mybatis xml文件代码提示

    今天在开源项目社区看到一个插件挺不错的,推荐给大家.叫MyBatis MyBatis 是一个流行的 Java 数据持久层框架.MyBatipse 是一个 Eclipse 插件,在编辑 MyBatis ...

  7. 【bzoj2751】[HAOI2012]容易题(easy) 数论,简单题

    Description 为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪 ...

  8. Admin组件-----Django自带

    1 list_display from django.contrib import admin # Register your models here. from app01.models impor ...

  9. day02-菜单处理

    解决力度到按钮的级别 ----------------------------------------------------------------------------------------- ...

  10. Log4j2同步异步性能比较以及教程和问题(坑)汇总

    线程数:500个   每个线程日志输出次数: 500次 log4j2其实有两个输出异步日志的方式:AsyncLogger和AsyncAppend 他两的区别在于: AsyncLogger使用的是无锁高 ...