1. 程式人生 > 其它 >第五篇 SQL注入基礎知識

第五篇 SQL注入基礎知識

1 什麼是SQL注入

一種將SQL語句插入到使用者輸入的引數中,進行攻擊,這些會通過後端伺服器傳入到SQL伺服器,執行對應的SQL語句,比如可以獲取資料庫資訊、使用者資訊、管理員許可權等

2 常見的SQL注入技巧

2.1 識別資料庫型別

常見的資料庫型別有:Oracle、MySQL、SQL Server、Access、Postgresql等

  • 首先根據web前端的技術棧,如:
asp和.net 通常使用sqlserver,asp有的時候也適用access
php通常使用mysql,postgresql
java通常使用oracle,mysql

  • 其次根據使用的作業系統進行判斷,比如windows,使用的資料庫很有可能就是sqlserver,linux一般都是mysql,postgresql

  • 再次,基於查詢、報錯資訊進行識別

1. 基於version:

	sqlserver :
		1)select @@version, 返回結果示例:
			Microsoft SQL Server 2019 (RTM-CU14) (KB5007182) - 15.0.4188.2 (X64) 
	
	mysql:
		1)select @@version,返回結果示例:
			+-----------+
			| @@version |
			+-----------+
			| 8.0.26    |
			+-----------+
		2)  select version(),返回結果示例:
			+-----------+
			| version() |
			+-----------+
			| 8.0.26    |
			+-----------+
			
	postgresql:
		1)select version(),返回結果示例:
			PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

	oracle:
		1) select banner from v$version,返回結果示例:
			Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
			PL/SQL Release 11.2.0.1.0 - Production
			CORE	11.2.0.1.0	Production
			TNS for Linux: Version 11.2.0.1.0 - Production
			NLSRTL Version 11.2.0.1.0 - Production
			
2. 基於字串的拼接方式:somestring
	
	sqlserver: select 'some'+'string';
	mysql:select 'some' 'string'
	postgresql:select 'some' || 'string'
	oracle:select 'some' || 'string' from dual
	
3. 使用數字引數

	sqlserver:
		1) @@pack_reveived:返回資料包資訊,示例:
		
			1> select @@pack_received
			2> go

			-----------
					132
		2) @@rowcount:返回上一句影響的行數,示例:
		
			1> select @@rowcount
			2> go

			-----------
					  1
					  
	mysql:
		1)connection_id():返回連線的id,示例:
		
			mysql> select connection_id();
				+-----------------+
				| connection_id() |
				+-----------------+
				|              12 |
				+-----------------+
				1 row in set (0.00 sec)
		2)last_insert_id():獲取最近插入主鍵的id,示例:
		
			mysql> select last_insert_id();
				+------------------+
				| last_insert_id() |
				+------------------+
				|                0 |
				+------------------+
				
		3)row_count():獲取上次受影響的行數,示例:
		
			mysql> select row_count();
				+-------------+
				| row_count() |
				+-------------+
				|          -1 |
				+-------------+

	oracle:
		1)bitand:返回按位進行運算的結果,示例:
		
			SQL> select bitand(1,1) from dual;

				BITAND(1,1)
				-----------
					  1

	postgresql:
		1)extract():提取時間或者日期資訊,示例:
		
			postgres=# select extract(dow from now());
				 extract 
				---------
					   4
				(1 row)
				
4. 註釋

	mysql:#,--,/* */
	oracle和sqlserver:--,/* */,oracle不支援;符號
	
	

2.2 常用注入語句

2.2.1 UNION語句

用來合併兩條或多條SELECT語句的查詢結果

SELECT col1,col2 ... coln FROM table1
UNION
SELECT col1,col2 ... coln FROM table2

預設情況下,結果中只包含不同的值,如果需要包含所有的值,就需要改為:UNION ALL,如果應用程式返回第一個表查詢所得的資料,那麼就可以利用UNION來查詢任何一張表,但是也需要滿足一定的條件

1)兩個查詢返回的列數必須相同。想要獲取準確的列數,有兩種方法:
     a)通過對第二個語句進行注入多次,每次逐漸增大列數,直到查詢正確執行,為了避免資料型別不一致導致錯誤,可以使用null來代替
	 b)使用ORDER BY子句,可以增大列的數字來判斷列數,示例:ORDER BY 1(2,3,等),如果ORDER BY 3報錯,證明是2列,該方法比較推薦,主要原因是可以使用二分查詢的方式,速度更快,同時留下的痕跡更少
	 
2)兩個SELECT語句對應列所返回的資料型別必須相同(或至少是相容的)。在獲取列數之後,想要判斷資料型別,就可以通過null的方式來進行替換,比如:UNION SELECT 'test', NULL,NULL ...
2.2.2 條件語句

有的情況,查詢結果只有兩種答案:是或否,這個時候就可以通過使用條件語句,格式示例:

IF 條件 THEN 執行 ELSE 執行其他
2.2.2.1 基於時間

比如想知道執行查詢的語句是不是系統管理員賬號

常用的有:

  • 獲取資料庫資訊,比如:資料庫名(substr(),left()),資料庫長度(length()),示例猜測資料庫長度

  • 獲取資料表資訊,示例猜測表名長度

  • 獲取列資訊,示例猜測列名長度

2.2.2.2 基於錯誤

基於時間不適用於提取多位資訊,比如出現1和0的概率都是一樣的,主要方法有利用回顯的報錯注入和利用報錯資訊的報錯注入