SQL预编译和SQL注入

再说SQL预编译:

最近用go语言时,学习了一下数据库连接的库,这里总结一下SQL预编译相关的知识。貌似网上都是建议使用预编译,我也觉得这种做法靠谱。

先谈 SQL注入:

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过让原SQL改变了语义,达到欺骗服务器执行恶意的SQL命令。其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

其实,反过来考虑,这也是SQL这类解释性语言本身的缺陷,安全和易用性总是相对的。类似的ShellShock也是一种注入攻击,可以看《ShellShock漏洞原理分析》。

一个经典注入:

记得以前看Hack技术资料时,有一个经典的万能密码,’or’=’or’。

01 ResultSet   rs=sm.executeQuery("select * from tb_usertable where name='"+u+"'and password='"+p+"'");
02  if(rs.next())
03  {
04      //查询到就转到成功页面
05    response.sendRedirect("wel.jsp");
06    }else
07  {
08    //说明不存在用户,转到登陆页面
09    response.sendRedirect("login.jsp");
10  }

这是以前很常见的登录判断写法。这和直接在数据库客户端输入SQL没什么区别,如果SQL注入成功的利用SQL拼接改变了SQL的语义,极有可能中招。现有的程序都会严格的检查传入的参数。在这里,’or’=’or’发挥了它的作用。

我们来看验证页面里面的SQL查询。

1 select from tb_usertable where name='"+u+"'and password='"+p+"'"
2 --如果我们把[' or '1' = '1]作为password传入进来.用户名随意,看看会成为什么?
3  select * from tb_usertable where name='"+HEHE+"'and password='1'or'1'='1'
4 -- 这样构造成的SQL语句中因为'1'='1'肯定成立,所以可以任何通过验证

这使得’or’=’or’成为了万能密码。

再说SQL预编译(PreparedStatement):

前面说了,SQL之所以能被注入,最主要的原因就是它的数据和代码(指令)是混合的。

其实我们想一下,C程序为什么从来没听说过注入这种说法,有的也是溢出。这是因为C是一种编译型语言,你没法在语义上欺骗它,语义解析这步提前做了,都生成二进制了。所以攻击C的方式大多是溢出,通过溢出让数据覆盖指令段。

数据库也提供了这种分离数据和代码(指令)的方式,就是SQL预编译。而SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or ‘1=1’也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令。

预编译语法:

1 PREPARE stmt_name FROM preparable_stmt;
2 EXECUTE stmt_name [USING @var_name [, @var_name] ...];
3 {DEALLOCATE DROPPREPARE stmt_name;

预编译的优点:

PreparedStatement可以尽可能的提高访问数据库的性能,我们都知道数据库在处理SQL语句时都有一个预编译的过程,而预编译对象就是把一些格式固定的SQL编译后,存放在内存池中即数据库缓冲池,当我们再次执行相同的SQL语句时就不需要预编译的过程了,只需DBMS运行SQL语句。

所以当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,特别是的大型的数据库中,它可以有效的也加快了访问数据库的速度。

注意:

理论上,SQL预处理对注入的解决是釜底抽薪的。但貌似有的预处理依然是平凑的方式,仅仅是加了过滤。这还需要数据库支持。

转载请注明:旅途@KryptosX » SQL预编译和SQL注入

时间: 2025-01-20 11:54:20

SQL预编译和SQL注入的相关文章

PL/SQL开发中动态SQL的使用方法

动态 内容摘要:在PL/SQL开发过程中,使用SQL,PL/SQL可以实现大部份的需求,但是在某些特殊的情况下,在PL/SQL中使用标准的SQL语句或DML语句不能实现自己的需求,比如需要动态建表或某个不确定的操作需要动态执行.这就需要使用动态SQL来实现.本文通过几个实例来详细的讲解动态SQL的使用. 本文适宜读者范围:Oracle初级,中级 系统环境: OS:windows 2000 Professional (英文版) Oracle:8.1.7.1.0 正文: 一般的PL/SQL程序设计中

sql server 编译与重编译详解

SQLSERVER编译与重编译 编译的含义 当SQLSERVER收到任何一个指令,包括查询(query).批处理(batch).存储过程.触发器(trigger) .预编译指令(prepared statement)和动态SQL语句(dynamic SQL Statement)要完成语法解释.语句解释, 然后再进行"编译(compile)",生成能够运行的"执行计划(execution plan)".在编译的过程中, SQLSERVER会根据所涉及的对象的架构(sc

SQL查询结果集对注入的影响及利用

对于注入而言,错误提示是极其重要.所谓错误提示是指和正确页面不同的结果反馈,高手是很重视这个一点的,这对于注入点的精准判断至关重要.本问讨论下关于几类错误和他产生的原理,希望对读者有所帮助. 错误提示主要有逻辑错误和语法错误以及脚本运行错误三类. 一:逻辑错误 简单的例子是1=1 1=2这两个,1=1与1=2页面不同的原理是什么?以$sql = "select * from news where id=$_GET[id]"为例. select * from news where id=

多条件查询拼接sql语句如何防止sql注入

问题描述 假如有四个条件可以任意输入1到4个条件取交集求解 解决方案 解决方案二:引用楼主abc12346579的回复: 假如有四个条件可以任意输入1到4个条件取交集求解 你的"任意输入条件"是什么意思?如果说随便输入sql,那么这其实根本不需要注入,你都随便让人家写代码了,还要想什么"注入"方式干什么?直接干就行了.解决方案三:你要是让人家输入sql,那就相当于超市敞开大门让顾客把东西搬回家,再来讨论"如何防止盗窃"就没有意义了.解决方案四:在

如何快速编译sql脚本-SQL脚本编译如何快速编译SQL脚本

问题描述 SQL脚本编译如何快速编译SQL脚本 如何快速编译SQL脚本如何快速编译SQL脚本如何快速编译SQL脚本

预定义的SQL*Plus变量

http://benbo.itpub.net/post/26034/393783 SQL*Plus提供了一组预定义变量,可以用于其他替换变量相同的方法使用它们. sys@ORCL> DEFINE -- 显示预定义的SQL*Plus变量列表 sys@ORCL> DEFINEDEFINE _DATE = "09-9月 -07" (CHAR) --当前日期DEFINE _CONNECT_IDENTIFIER = "orcl" (CHAR) --连接的数据库名D

sql语句优化之SQL Server(详细整理)_MsSql

MS SQL Server查询优化方法 查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,

SQL循序渐进(24)嵌入SQL

嵌入SQL 为了更好的理解嵌入SQL,本节利用一个具体例子来说明.嵌入SQL允许程序连接数据库并且包括SQL代码到程序中,这样在程序中就可以对数据库进行使用.操作以及处理数据等等.以下是用C语言编写的使用嵌入SQL的例程,它将打印一个报告:这个程序必须在普通的编译之前先预编译SQL语句.嵌入SQL对于不同系统是不一样的,所以在不同的系统中对以下的程序稍作修改,特别是变量的声明以及过程记录等.在嵌入SQL时,考虑网络.数据库管理系统.操作系统是相当重要的. 以下是详细的代码: #include <

数据点-预编译LINQ查询

在应用程序中使用 LINQ to SQL 或 LINQ to Entities 时,有必要考虑对您 创建并重复执行的任何查询进行预编译.我经常在埋头苦干一项特定任务时忘了 利用预编译查询,等我意识到时为时已晚.这很像"异常处理病",即开发人员 试图在事发后将异常处理强行加入应用程序中. 然而,即使您已经实施了此项重要的性能增强方法,往往也只是徒劳.您可 能会发现预期的性能增强并未实现,但原因(和解决方法)可能仍悬而未决. 在本篇专栏文章中,我首先将解释如何预编译查询,然后将重点讲述在