distinct去重,如果遇到text字段,可以用以下方法解決
1.用not exists
select * from tab a
where not exists (
select 1 from tab b
where b.col1 = a.col1
and b.col2 = a.col2
...
)
2.轉成字符型
CONVERT(VARCHAR(8000),你的字段)
select distinct * from (
select id, convert(varchar(8000), ntextCol) as colName from XXX
)
用EXISTS替換DISTINCT: 當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果.
例子:
(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
用EXISTS的確可以替代DISTINCT,不過以上方案僅適合DEPT_NO為唯一主鍵的情況。 如果要去掉重復記錄,需參照以下方法:
SELECT * FROM EMP WHERE DEPT_NO EXISTS(select Max(DEPT_NO) FROM DEPT D , EMP E WHERE E.DEPT_NO = D.DEPT_NO GROUP BY D.DEPT_NO)
得到重復記錄數
SELECT * FROM EMP WHERE DEPT_NO NOT EXISTS(select Max(DEPT_NO) FROM DEPT D , EMP E WHERE E.DEPT_NO = D.DEPT_NO GROUP BY D.DEPT_NO)
在我們進行sql注入的過程中常常會用到union查詢方法,大多數情況下使用union查詢法可以讓我們很快的知道目標的數據組織方式。然而當我們遇到ntext、text或image數據類型時,union查詢就不太管用了。以sql server為例,在這種情況下會拋出如下錯誤:ntext 數據類型不能選為 DISTINCT,因為它不可比。
這里,我以sql server數據庫為測試環境來進行分析。因為ntext、text、image數據字段可能存儲非常多的數據,默認的情況下,數據庫為提高效率會強制排除以上類型的字段中的相同的數據,這樣就相當於在sql查詢語句中加入了distinct關鍵字。而又因為這種類型的數據量可能非常大,數據庫無法對這種類型的字段進行有效的比較,而distinct又要求數據庫進行數據比較,從而導致帶有unionr的sql語句執行錯誤,造成上述現象。
了解了出錯的原理我們就可以在執等的sql語句中加入相應的條件來使sql能正確執行。從上面可以看出,sql語句無法執行的原因是因為數據庫去檢查union的數據是否相同,那么我們只需要去掉這個默認的條件就可以了。解決的方法就是在union關鍵字后邊加上“all”關鍵字。
下面用實例來演示這種類型的union注入。首先創建兩個表: CREATE TABLE [dbo].[ntextTest]( [id] [int] NOT NULL, [name] [nchar](10) NULL, [target] [ntext] NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] CREATE TABLE [dbo].[support]( [col1] [nchar](10) NULL, [col2] [nchar](10) NULL ) ON [PRIMARY] 然后分別在這兩個表中插入數據: insert into ntextTest values(1,'aaa','adfsfs') insert into ntextTest values(2,'test','aaaa') insert into support values('aa','bb') 之后執行下列查詢: select * from ntextTest union select 1,2,col1 from support 一如即往,沒有成功。再執行: select * from ntextTest union all select 1,col1,col2 from support 這次正常返回結果!接下來被卡住的sql注入可以繼續進行了。
上面所講的問題的前提是ntext、text、image等數據類型出現在union查詢的前面部分,在進行sql注入時,注入對象原有的查詢語句中包含ntext數據類型即是這種情況。還有另一種情況是在我們注入時希望查詢ntext數據字段的內容。這種情況還有以有另一種操作方式。比如要注入一個地址:http://www.test.com/show.asp?id=1,假定其后后的sql查詢語句為:select id,productName,productInfo from product where id=@id,其中productName和productInfo都為nvarchar類型,如果我們想要查詢這個網站后台的article表中的文章的內容(用content表示,為ntext類型)可以用substring 函數來實現。用substring 可以將ntext數據截取一部分出來作為nvarchar類型返回,這樣可以繞過ntext類型。如我們做如下構造:http://www.test.com/show.asp?id=1 and 1=2 union select 1,2,…,substring(content,1,200),...n from article where id=XX 下面附上substring詳細用法:
substring函數: { 返回值:返回字符、binary、text 或 image 表達式的一部分。 語法:SUBSTRING ( expression , start , length ) 參數: expression:是字符串、二進制字符串、text、image、列或包含列的表達式。不要使用包含聚合函數的表達式。 start:是一個整數,指定子串的開始位置。 length:是一個整數,指定子串的長度(要返回的字符數或字節數)。 返回類型: 1)、如果 expression 是支持的字符數據類型,則返回字符數據。 2)、如果 expression 是支持的 binary 數據類型,則返回二進制數據。 返回字符串的類型與給定表達式的類型相同(表中顯示的除外)。
}
給定的表達式 | 返回類型 |
---|---|
text | varchar |
image | varbinary |
ntext | nvarchar |
注釋: 在字符數中必須指定使用 ntext、char 或 varchar 數據類型的偏移量(start 和 length)。在字節數中必須指定使用 text、image、binary 或 varbinary 數據類型的偏 移量。
ps:之后以寫這篇文章是因為本人在注入過程中遇到了上面的問題,百度了好久都沒有找到有用的信息。相信很多像我一樣的小菜遇到這樣的問題也難以解決,希望這篇文章對小菜有所幫助。另本人初學安全技術,很多東西一知半解,難免出錯,如果老鳥們發現了還請指點!
用NOT EXISTS替代NOT IN
在子查詢中,NOT IN子句將執行一個內部的排序和合並。 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)。 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
例如:
SELECT … FROM EMP WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT=’A’); |
為了提高效率。改寫為:
(方法一: 高效)
SELECT …. FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’ |
(方法二: 最高效)
SELECT …. FROM EMP E WHERE NOT EXISTS (SELECT ‘X’ FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’); 用EXISTS替換DISTINCT
當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換
例如:
低效:
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO |
高效:
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); |
EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果。
識別‘低效執行’的SQL語句
用下列SQL工具找出低效SQL:
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC; |
(雖然目前各種關於SQL優化的圖形化工具層出不窮,但是寫出自己的SQL工具來解決問題始終是一個最好的方法)