预防SQL注入笔记

SQL注入如何预防?

本文参考自owasp,重点是提供清晰,简单,可操作的指导,以防止应用程序中的SQL注入漏洞。不幸的是,SQL注入攻击很常见,这是由于两个因素:

  1. SQL注入漏洞的显着流行
  2. 目标的吸引力(即数据库通常包含应用程序的所有有趣/关键数据)。

发生了如此多的成功SQL注入攻击有点可耻,因为在代码中避免SQL注入漏洞非常简单。

当软件开发人员创建包含用户提供的输入的动态数据库查询时,会引入SQL注入漏洞。为了避免SQL注入缺陷很简单。开发人员需要:

a)停止编写动态查询; 

b)防止用户提供的包含恶意SQL的输入影响所执行查询的逻辑。

本文提供了一组通过避免这两个问题来防止SQL注入漏洞的简单技术。这些技术几乎可以与任何类型的数据库一起使用。还有其他类型的数据库,如XML数据库,可能有类似的问题(例如,XPath和XQuery注入),这些技术也可用于保护它们。

主要防御:

  • 选项1:使用准备好的语句(带参数化查询)
  • 选项2:使用存储过程
  • 选项3:白名单输入验证
  • 选项4:转义所有用户提供的输入

额外防御:

  • 另外:强制执行最低权限
  • 另外:执行白名单输入验证作为辅助防御

不安全的例子:

SQL注入漏洞通常如下所示:

以下(Java)示例是UNSAFE,并允许攻击者将代码注入将由数据库执行的查询中。简单地附加到查询的未经验证的“customerName”参数允许攻击者注入他们想要的任何SQL代码。不幸的是,这种访问数据库的方法太常见了。

String query = "SELECT account_balance FROM user_data WHERE user_name = " 
             + request.getParameter("customerName");
try {
    Statement statement = connection.createStatement( ... );
    ResultSet results = statement.executeQuery( query );
}
...

主要防御

防御选项1:准备好的语句(带参数化查询)#

使用带有变量绑定的预准备语句(也就是参数化查询)是所有开发人员应该首先学习如何编写数据库查询的方法。它们比动态查询更易于编写,更易于理解。参数化查询强制开发人员首先定义所有SQL代码,然后将每个参数传递给查询。这种编码风格允许数据库区分代码和数据,无论提供什么用户输入。

准备好的语句可确保攻击者无法更改查询的意图,即使攻击者插入了SQL命令也是如此。在下面的安全示例中,如果攻击者输入的是userID tom' or '1'='1,则参数化查询不会受到攻击,而是会查找与字符串完全匹配的用户名tom' or '1'='1

特定语言的建议:

  • Java EE - PreparedStatement()与绑定变量一起使用
  • .NET - 使用参数化查询,如绑定变量SqlCommand()OleDbCommand()使用绑定变量
  • PHP - 将PDO与强类型参数化查询一起使用(使用bindParam())
  • Hibernate - createQuery()与绑定变量一起使用(在Hibernate中称为命名参数)
  • SQLite - 用于sqlite3_prepare()创建语句对象

在极少数情况下,准备好的陈述会损害绩效。遇到这种情况时,最好是a)强烈验证所有数据或b)使用特定于数据库供应商的转义例程来转义所有用户提供的输入,如下所述,而不是使用预准备语句。

安全JavaSQL语句示例

以下代码示例使用PreparedStatementJava的参数化查询实现来执行相同的数据库查询。

// 一定要验证
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 SQL语句示例

使用.NET,它更加直接。查询的创建和执行不会更改。您所要做的就是使用Parameters.Add()此处所示的调用将参数传递给查询。

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 Name.Text));
  OleDbDataReader reader = command.ExecuteReader();
  // …
} catch (OleDbException se) {
  // error handling
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值