【連載】數據庫審計產品常見缺陷(4)數據庫對象解析錯誤

繼上期爲大家介紹了有關數據庫審計多語句無法有效分割的問題,本期,安華金和圍繞數據庫對象解析錯誤分析數據庫審計產品常見缺陷。數據庫審計產品中一個重要需求是要有效記錄下來SQL語句的操作類型、訪問對象;根據這些操作類型和訪問對象,審計產品可以有效地制訂告警策略,可以有效地根據操作類型、訪問對象進行事後的追蹤與檢索。我國相關部門的數據庫審計產品標準中要求:應對數據庫網絡訪問對象的名稱進行準確審計,包括數據庫服務器名稱、IP名稱、數據庫名稱、表、視圖、序列、包、存儲過程、函數、庫、索引和觸發器等。

目前國內大多數數據庫審計產品都會宣稱支持對SQL語句操作類型和訪問對象的審計支持;但事實上,很多審計產品的支持能力有限,往往只能支持一些簡單語句的解析,比如這樣的語句: 
Select * from tbl1 where col1 > ’1’;

但筆者曾經見過一家大型的信息安全廠商的產品,僅僅是在表名前增加一個schema名稱,就發生了令人震驚的錯誤;這個產品居然將schema名稱審計爲了表名。如上面這條語句改爲:

Select * from user1.tbl1 where col1 > ‘1’;

這種數據庫審計產品就會將user1記錄爲表名。

出現這種情況說明產品設計的比較粗糙,還遠遠達不到專業的數據庫審計產品的要求;這通常是一些網絡審計產品廠商,未經過嚴肅的產品開發過程,僅對原有的網絡審計產品進行了簡單包裝就推向了市場;這些廠商依靠已經積累的品牌和用戶的信任,提供了不嚴肅的數據庫審計產品。而國家相關部門在產品的認證過程中以及用戶的演示中,並未真正仔細地對此進行測試。

事實上,上面被誤報的例子,是一個非常簡單的例子,大多數專業的數據庫審計產品都不會犯這樣的錯誤。事實上,真正的挑戰要比上面的例子複雜很多。安華金和的數據庫審計專家爲讀者準備了一些示例,讀者可以驗證下所使用的數據庫審計產品是否支持對這些類型的語句的操作類型和訪問對象的正確解析。下面的示例,若是未明確說明數據庫類型,那麼均可在Oracle上執行通過。

一、對帶Schema的表能否準確解析並審計

示例1:

Select * from user1.tbl1 where col1 > ‘1’;

挑戰:

是否準確識別出表名是tbl1,數據庫名稱是user1;

示例2:以下語句在SQL Server上可運行

SELECT [Name],

[SalesAmount]

FROM [AdventureWorks].[Production].[Product] P

挑戰:

是否準確識別出表名是product,數據庫名稱是AdventureWorks,Schema名稱是Production;

 

二、對Union中的多表能否準確解析並審計

如:

Select col1, col2 from tbl1

Union

Select col1,col2 from tbl2

Union

Select myCol1,myCol2 from tbl3

Union

Select col3,col4 from tbl1;

挑戰:

是否準確識別出表是tbl1、tbl2、tbl3

 

三、對Update中的多表能否能否準確解析並審計

示例1:Oracle上的多表更新語句:

update landleveldata a set (a.gqdltks, a.bztks)= (select b.gqdltks, b.bztks from gdqlpj b where a.GEO_Code=b.lxqdm)

挑戰:

是否準確識別出涉及的表包括landleveldata、gdqlpj

 

示例2:SQL Server上的多表更新語句:

update a set a.gqdltks=b.gqdltks,a.bztks=b.bztks from landleveldata a,gdqlpj b where a.GEO_Code=b.lxqdm

挑戰:

是否準確識別出涉及的表包括landleveldata、gdqlpj

 

示例3:MySQL上的多表更新語句:

update landleveldata a, gdqlpj b set a.gqdltks= b.gqdltks, a.bztks= b.bztks where a.GEO_Code=b.lxqdm

挑戰:

是否準確識別出涉及的表包括landleveldata、gdqlpj

 

四、對insert中的多表能否能否準確解析並審計

Insert語句有兩種句式涉及多表:insert into .... Select....

Select ....into [table] from

示例1:

Insert into tbl1(col1,col2,col3) select col1,col2,col3 from tbl2 where tbl2.col1=’new’;
挑戰:識別出tbl1和tbl2;

示例2:以下語句在SQL Server上可運行

Select col1,col2,col3 into tbl1 from tbl2 where tbl2.col1=’new’;

挑戰:識別出tbl1和tbl2;

 

五、對join中的多表能否準確解析並審計:

Join是多表關聯查詢的基礎,形式也更多樣;挑戰也更巨大:

示例1:簡單join語句

Select t1.a,t2.b from t1, t2 where t1.c=t2.c

挑戰:

將表t1和t2均識別出來

示例2:inner join的語句

Select t1.a,t2.b  from t1 inner join t2 ON t1.c=t2.c

left join t3 on t1.c=t3.c where t1.name like ‘劉%’ and prince = ‘北京’;

挑戰:

將t1、t2、t3表都準確地識別出來。

示例3:一個更爲複雜的join情況,該語句是在SQL Server中執行的,由開放應用軟

opencms實際發出的,以下語句在SQL Server上可運行:

SELECT CLMNS.COLUMN_ID AS [ID],CLMNS.NAME AS [NAME],CLMNS.IS_NULLABLE AS [NULLABLE],
CAST(ISNULL(CIK.INDEX_COLUMN_ID,0)AS BIT)AS [INPRIMARYKEY],CLMNS.IS_IDENTITY AS [IDENTITY],USRT.NAME AS [DATATYPE],
ISNULL(BASET.NAME,N'')AS [SYSTEMTYPE],CAST(CASE WHEN BASET.NAME IN(N'nchar',N'nvarchar')AND CLMNS.MAX_LENGTH<>-1 
THEN CLMNS.MAX_LENGTH/2 ELSE CLMNS.MAX_LENGTH END AS INT)AS [LENGTH],CAST(CLMNS.PRECISION AS INT)AS 
[NUMERICPRECISION],CAST(CLMNS.SCALE AS INT)AS [NUMERICSCALE],ISNULL(XSCCLMNS.NAME,N'')AS [XMLSCHEMANAMESPACE],
ISNULL(S2CLMNS.NAME,N'')AS [XMLSCHEMANAMESPACESCHEMA],
ISNULL((CASE CLMNS.IS_XML_DOCUMENT WHEN 1 THEN 2 ELSE 1 END),0)AS [XMLDOCUMENTCONSTRAINT],SCLMNS.NAME AS [DATATYPESCHEMA] 
FROM SYS.TABLES AS TBL 
INNER JOIN
SYS.ALL_COLUMNS AS CLMNS ON CLMNS.OBJECT_ID=TBL.OBJECT_ID LEFT 
OUTER JOIN 
SYS.INDEXES AS IK ON IK.OBJECT_ID=CLMNS.OBJECT_ID AND 1=IK.IS_PRIMARY_KEY LEFT 
OUTER JOIN 
SYS.INDEX_COLUMNS AS CIK ON CIK.INDEX_ID=IK.INDEX_ID AND CIK.COLUMN_ID=CLMNS.COLUMN_ID AND CIK.OBJECT_ID=CLMNS.OBJECT_ID AND 0=CIK.IS_INCLUDED_COLUMN 
LEFT OUTER JOIN 
SYS.TYPES AS USRT ON USRT.USER_TYPE_ID=CLMNS.USER_TYPE_ID 
LEFT OUTER JOIN 
SYS.TYPES AS BASET ON(BASET.USER_TYPE_ID=CLMNS.SYSTEM_TYPE_ID AND BASET.USER_TYPE_ID=BASET.SYSTEM_TYPE_ID)OR((BASET.SYSTEM_TYPE_ID=CLMNS.SYSTEM_TYPE_ID)
AND(BASET.USER_TYPE_ID=CLMNS.USER_TYPE_ID)AND(BASET.IS_USER_DEFINED=0)AND(BASET.IS_ASSEMBLY_TYPE=1))
LEFT OUTER JOIN 
SYS.XML_SCHEMA_COLLECTIONS AS XSCCLMNS ON XSCCLMNS.XML_COLLECTION_ID=CLMNS.XML_COLLECTION_ID 
LEFT OUTER JOIN 
SYS.SCHEMAS AS S2CLMNS ON S2CLMNS.SCHEMA_ID=XSCCLMNS.SCHEMA_ID 
LEFT OUTER JOIN 
SYS.SCHEMAS AS SCLMNS ON SCLMNS.SCHEMA_ID=USRT.SCHEMA_ID 
WHERE(TBL.NAME='CMS_HISTORY_PROJECTS' AND SCHEMA_NAME(TBL.SCHEMA_ID)='opencms')ORDER BY [ID] ASC

挑戰:

將表名:[SYS].[ALL_COLUMNS];   [SYS].[INDEXES]; [SYS].[INDEX_COLUMNS];   [SYS].[SCHEMAS];   [SYS].[TABLES]; [SYS].[TYPES];   [SYS].[XML_SCHEMA_COLLECTIONS]都識別出來。

 

六、對子查詢中的表能否準確記錄並審計

子查詢是另外一種複雜的情況,整個SQL語句中的表並未老老實實地呆在from語句和where語句之間,而是***到了語句中,這個時候我們要是審計到所有的表對象,將有更大的挑戰。

示例1:一個簡單的子查詢語句

Select * from tbl1 where tbl1.col1 in (select col1 from tbl2 where col2=’中國’);

挑戰:

識別出表tbl1和tbl2

 

示例2:在join中的子查詢 
SELECT     P.ProductID, P.Name, P.ProductNumber, M.Name AS ProductModelName
FROM         Production.Product  P INNER JOIN
(SELECT     Name, ProductModelID
FROM          Production.ProductModel)  M 
ON P.ProductModelID = M.ProductModelID

挑戰: 
識別出表Production.Product和Production.ProductModel

示例3:作爲計算列的子查詢,以下語句在SQL Server上可運行 
SELECT [Name],
(SELECT COUNT(*) FROM AdventureWorks.Sales.SalesOrderDetail S
WHERE S.ProductID=P.ProductID) AS SalesAmount
FROM [AdventureWorks].[Production].[Product] P

挑戰:

識別出表AdventureWorks.Sales.SalesOrderDetail

[AdventureWorks].[Production].[Product]

 

七、一個充滿挑戰的示例,綜合了各種因素

毫無疑問,下面這個示例將是所有基於正則表達等方式進行匹配分析的數據庫審計產品的噩夢;這裏融合了多種SQL複雜的語法特徵,只有基於yacc/lex這樣的詞法和語法分析技術的專業數據庫審計產品才能勝任;這條語句來源於OpenCMS開放應用,該語句在sqlserver中可執行: 
insert #t1 (object_id, object_type, relative_id, relative_type, rank)
select distinct
case when 77 = t.relative_type then obj2.parent_object_id else t.relative_id end, -- object_id
case when 77 = t.relative_type then 1 else relative_type end, -- object_type
dp.referenced_major_id, -- relative_id
case -- relative_type
when dp.class < 2 then
case when 'U' = obj.type then 1
when 'V' = obj.type then 2
when 'TR' = obj.type then 3
when 'AF' = obj.type then 4
when obj.type in ( 'P', 'RF', 'PC' ) then 5
when obj.type in ( 'TF', 'FN', 'IF', 'FS', 'FT' ) then 6
when exists (select * from sys.synonyms syn where syn.object_id = dp.referenced_major_id ) then 7
end
when dp.class = 2 then (case
when exists (select * from sys.assembly_types sat where sat.user_type_id = dp.referenced_major_id) then 8
else 9
end)
end,
3
from #t1 as t
join sys.sql_dependencies as dp on
-- reference table, view procedure
( class < 2 and dp.object_id = t.relative_id and t.relative_type in ( 1, 2, 3, 4, 5, 6, 77) )
--reference type
or ( 2 = class and dp.object_id = t.relative_id ) -- t.relative_type?
--reference xml namespace ( not supported by server right now )
--or ( 3 = class and dp.referenced_major_id = t.relative_id and 10 = t.relative_type )
left join sys.objects as obj on obj.object_id = dp.referenced_major_id and dp.class < 2 and obj.type in ( 'U', 'V', 'P', 'RF', 'PC', 'TF', 'FN', 'IF', 'FS', 'FT', 'TR', 'AF')
left join sys.objects as obj2 on obj2.object_id = t.relative_id and 77 = t.relative_type
where 3 = t.rank

挑戰:

能夠完全識別出訪問的數據庫表包括:#t1、sys.synonyms

sys.assembly_typessys.sql_dependencies、sys.objects


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章