博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL注入的原理解说,挺好!
阅读量:6686 次
发布时间:2019-06-25

本文共 5525 字,大约阅读时间需要 18 分钟。

原文地址:http://www.cnblogs.com/rush/archive/2011/12/31/2309203.html

1.1.1 总结

前几天,国内最大的程序猿社区CSDN网站的用户数据库的黑客公告,600登录名和万用户password被公开泄露,随后又有多家站点的用户password被流传于网络。连日来引发众多网民对自己账号、password等互联网信息被盗取的普遍担忧。

网络安全成为了如今互联网的焦点。这也恰恰触动了每一位用户的神经,因为设计的漏洞导致了不可收拾的恶果,验证了一句话“出来混的,迟早是要还的”,所以我想通过专题博文介绍一些经常使用的攻击技术和防范策略。

SQL Injection或许非常多人都知道或者使用过。假设没有了解或全然没有听过也没有关系,由于接下来我们将介绍SQL Injection。

1.1.2 正文

SQL Injection:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,终于达到欺骗server运行恶意的SQL命令。

详细来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎运行的能力。它能够通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的站点上的数据库。而不是依照设计者意图去运行SQL语句。

首先让我们了解什么时候可能发生SQL Injection。

如果我们在浏览器中输入URL 。因为它仅仅是对页面的简单请求无需对数据库动进行动态请求。所以它不存在SQL Injection。当我们输入

testid=23时,我们在URL中传递变量testid,而且提供值为23,因为它是对数据库进行动态查询的请求(当中?testid=23表示数据库查询变量),所以我们能够该URL中嵌入恶意SQL语句。

如今我们知道SQL Injection适用场合,接下来我们将通过详细的样例来说明SQL Injection的应用。这里我们以数据库作为样例。

我们通过Web页面查询job表中的招聘信息。job表的设计例如以下:

图1 jobs表

接着让我们实现Web程序,它依据工作Id(job_id)来查询对应的招聘信息,示意代码例如以下:

/// /// Handles the Load event of the Page control./// /// The source of the event./// The 
instance containing the event data.protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { // Gets departmentId from http request. string queryString = Request.QueryString["departmentID"]; if (!string.IsNullOrEmpty(queryString)) { // Gets data from database. gdvData.DataSource = GetData(queryString.Trim()); // Binds data to gridview. gdvData.DataBind(); } }}

如今我们已经完毕了Web程序。接下来让我们查询对应招聘信息吧。

图2 job表查询结果

如图所看到的,我们要查询数据库中工作Id值为1的工作信息,并且在页面显示了该工作的Id,Description。Min Lvl和Max Lvl等信息。

如今要求我们实现依据工作Id查询对应工作信息的功能,想必大家非常快能够给出解决方式。SQL示意代码例如以下:

SELECT     job_id, job_desc, min_lvl, max_lvlFROM         jobsWHERE     (job_id = 1)

如果如今要求我们获取Department表中的全部数据,并且必须保留WHERE语句。那我们仅仅要确保WHERE恒真就OK了,SQL示意代码例如以下:

SELECT     job_id, job_desc, min_lvl, max_lvlFROM         jobsWHERE     (job_id = 1) OR 1 = 1

上面我们使得WHERE恒真,所以该查询中WHERE已经不起作用了,其查询结果等同于下面SQL语句。

SELECT     job_id, job_desc, min_lvl, max_lvlFROM         jobs

SQL查询代码实现例如以下:

string sql1 = string.Format(    "SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id='{0}'", jobId);

如今我们要通过页面请求的方式,让数据库运行我们的SQL语句,我们要在URL中嵌入恶意表达式1=1(或2=2等等)。例如以下URL所看到的:

图3 job表查询结果

如今我们把job表中的全部数据都查询出来了,只通过一个简单的恒真表达式就能够进行了一次简单的攻击。

尽管我们把job表的数据都查询出来了,但数据并没有太大的价值,因为我们把该表暂时命名为job表,所以接着我们要找出该表真正表名。

首先我们如果表名就是job。然后输入下面URL:

jobid=1'or 1=(select count(*) from job)--

等效SQL语句例如以下:

SELECT       job_id, job_desc, min_lvl, max_lvl FROM         jobs WHERE      job_id='1'or 1=(select count(*) from job) --'

图4 job表查询结果

当我们输入了以上URL后,结果server返回我们错误信息,这证明了我们的如果是错误的,那我们该感觉到挫败吗?不,事实上这里返回了非常多信息,首先它证明了该表名不是job,并且它还告诉我们后台数据库是SQL Server,不是MySQL或Oracle,这也设计一个漏洞把错误信息直接返回给了用户。

接下假定表名是jobs,然后输入下面URL:

等效SQL语句例如以下:

SELECT       job_id, job_desc, min_lvl, max_lvl FROM         jobs WHERE      job_id='1'or 1=(select count(*) from jobs) --'

图5 job表查询结果

如今证明了该表名是jobs,这能够迈向成功的一大步,因为我们知道了表名就能够对该表进行增删改操作了。并且我们还能够推測出很多其它的表对它们作出改动,一旦改动成功那么这将是一场灾难。

如今大家已经对SQL Injection的攻击有了初步的了解了,接下让我们学习怎样防止SQL Injection。

总的来说有下面几点:

1.永远不要信任用户的输入。要对用户的输入进行校验,能够通过正則表達式,或限制长度。对单引號和双"-"进行转换等。

2.永远不要使用动态拼装SQL,能够使用參数化的SQL或者直接使用存储过程进行数据查询存取。

3.永远不要使用管理员权限的数据库连接。为每一个应用使用单独的权限有限的数据库连接。

4.不要把机密信息明文存放,请加密或者hash掉password和敏感的信息。

5.应用的异常信息应该给出尽可能少的提示,最好使用自己定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。

通过正则表达校验用户输入

首先我们能够通过正則表達式校验用户输入数据中是包括:对单引號和双"-"进行转换等字符。

然后继续校验输入数据中是否包括SQL语句的保留字,如:WHERE,EXEC。DROP等。

如今让我们编写正則表達式来校验用户的输入吧。正則表達式定义例如以下:

private static readonly Regex RegSystemThreats =        new Regex(@"\s?or\s*|\s?

;\s?|\s?

drop\s|\s?

grant\s|^'|\s?

--|\s?union\s|\s?delete\s|\s?

truncate\s|"

+
@"\s?sysobjects\s?|\s?xp_.*?|\s?syslogins\s?

|\s?sysremote\s?|\s?sysusers\s?|\s?sysxlogins\s?|\s?sysdatabases\s?|\s?

aspnet_.*?

|\s?exec\s?

"

,
RegexOptions.Compiled |
RegexOptions.IgnoreCase);

上面我们定义了一个正則表達式对象RegSystemThreats,而且给它传递了校验用户输入的正則表達式。

因为我们已经完毕了对用户输入校验的正則表達式了,接下来就是通过该正則表達式来校验用户输入是否合法了,因为.NET已经帮我们实现了推断字符串是否匹配正則表達式的方法——IsMatch()。所以我们这里仅仅需给传递要匹配的字符串就OK了。

示意代码例如以下:

/// /// A helper method to attempt to discover [known] SqlInjection attacks.  /// /// string of the whereClause to check/// 
true if found, false if not found
public static bool DetectSqlInjection(string whereClause){ return RegSystemThreats.IsMatch(whereClause);}/// /// A helper method to attempt to discover [known] SqlInjection attacks. /// /// string of the whereClause to check/// string of the orderBy clause to check///
true if found, false if not found
public static bool DetectSqlInjection(string whereClause, string orderBy){ return RegSystemThreats.IsMatch(whereClause) || RegSystemThreats.IsMatch(orderBy);}

如今我们完毕了校验用的正則表達式。接下来让我们须要在页面中加入校验功能。

/// /// Handles the Load event of the Page control./// /// The source of the event./// The 
instance containing the event data.protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { // Gets departmentId from http request. string queryString = Request.QueryString["jobId"]; if (!string.IsNullOrEmpty(queryString)) { if (!DetectSqlInjection(queryString) && !DetectSqlInjection(queryString, queryString)) { // Gets data from database. gdvData.DataSource = GetData(queryString.Trim()); // Binds data to gridview. gdvData.DataBind(); } else { throw new Exception("Please enter correct field"); } } }}

当我们再次运行下面URL时,被嵌入的恶意语句被校验出来了。从而在一定程度上防止了SQL Injection。

你可能感兴趣的文章
java大数类,两个不超过20位都不为0的十进制字符串相乘,华为笔试题
查看>>
【算法导论】学习笔记——第13章 红黑树
查看>>
02-黑马程序员------C 语言学习笔记---C语言基本语法成分
查看>>
如何判断手机收有几张SIM卡
查看>>
repo简介
查看>>
转行啦,转几本.net的书。。。
查看>>
《豆瓣的基础架构》
查看>>
运算符 and or ont
查看>>
Android 解决setRequestedOrientation之后手机屏幕的旋转不触发onConfigurationChanged方法...
查看>>
[Android Pro] Android权限设置android.permission完整列表
查看>>
headfirst设计模式(6)—单例模式
查看>>
地图坐标服务
查看>>
focus()无效问题
查看>>
python ConfigParser 学习
查看>>
JS 判断中英文字符长度
查看>>
小程序模板
查看>>
raw deferreds vs deferredGenerator vs inlineCallbacks
查看>>
Python中四种样式的99乘法表
查看>>
对于快速排序算法的递归栈深度的一点改进
查看>>
模拟锁定文件
查看>>