[英]Show me an Injection Attack for this Stored Procedure
我注意到很多人都說過可以進行注入攻擊,但是我的理解是,如果有人從字符串而不是參數創建查詢。 為了測試存儲過程不能保護您免受注入攻擊的聲明,我將此示例放在希望有人可以向我顯示漏洞(如果有)的情況下。
請注意,我已經以這種方式構建了代碼,以便輕松插入調用過程並將其嵌入SELECT查詢的函數。 這意味着我無法創建預備聲明。 理想情況下,我希望以這種方式保持設置,因為它是動態且快速的,但是如果有人可以創建有效的注入攻擊,則顯然不會發生。
DELIMITER $$
#This procedure searches for an object by a unique name in the table.
#If it is not found, it inserts. Either way, the ID of the object
#is returned.
CREATE PROCEDURE `id_insert_or_find` (in _value char(200), out _id bigint(20))
BEGIN
SET @_value = _value;
SET @id = NULL;
SELECT id INTO _id FROM `table` WHERE name=_value;
IF _id IS NULL THEN
BEGIN
INSERT INTO `table` (`name`) VALUE (_value);
SELECT LAST_INSERT_ID() INTO _id;
END;
END IF;
END$$
CREATE FUNCTION `get_id` (_object_name char(200)) RETURNS INT DETERMINISTIC
BEGIN
SET @id = NULL;
call `id_insert_or_find`(_object_name,@id);
return @id;
END$$
我在這里使用的PHP代碼是:
( 請注意,Boann在下面指出了這段代碼的愚蠢之處。我並不是為了尊重答案而對其進行編輯,但是它肯定不是代碼中的直接查詢。它將使用-> prepare進行更新,等等。如果發現新的漏洞,我仍然歡迎您提供任何其他評論。 )
function add_relationship($table_name,$table_name_child) {
#This table updates a separate table which has
#parent/child relationships listed.
$db->query("INSERT INTO table_relationships (`table_id`,`tableChild_id`) VALUES (get_id('{$table_name}'),get_id('{$table_name_child}')");
}
最終的結果是
table `table`
id name
1 oak
2 mahogany
現在,如果我想讓橡木成為桃花心木的孩子,我可以使用
add_relationship("mahogany","oak");
如果我想把塑料做成橡木的孩子,我可以使用
add_relationship("oak","plastic");
希望這有助於提供一些框架和背景。
存儲過程不一定是不安全的,而是您調用它的方式。
例如,如果您執行以下操作:
mysqli_multi_query("CALL id_insert_or_find(" + $value + ", " + $id + ")");
那么攻擊者會設置$value="'attack'" and id="1); DROP SCHEMA YOUR_DB; --"
那么結果將是
mysqli_multi_query("CALL id_insert_or_find('attack', 1); DROP SCHEMA YOUR_DB; --)");
死亡
嚴格來說,應該編寫該查詢以轉義表名:
$db->query("INSERT INTO table_relationships (`table_id`,`tableChild_id`) " .
"VALUES (get_id(" . $db->quote($table_name) + ")," .
"get_id(" . $db->quote($table_name_child) . "))");
否則,如果其中一個參數包含單引號,它將突破引號。 如果你只是在代碼中使用文字字符串調用該函數(例如, add_relationship("mahogany", "oak");
)那么不要逃避它是安全的。 如果您可能使用來自$ _GET / $ _ POST / $ _ COOKIE或其他數據庫字段或文件等的數據調用add_relationship
,則會遇到麻煩。 我當然不會讓它通過代碼審查。
如果用戶可以控制提供給該函數的表名,那么他們可以這樣做,例如:
add_relationship("oak", "'+(SELECT CONCAT_WS(',', password_hash, password_salt) FROM users WHERE username='admin')+'");
現在您可能會說,如果生成的表名不存在,那么就沒有實際的方法來提取該信息,但即便如此,您仍然可以使用二進制搜索和單獨的查詢一次提取一個二進制位的信息,只需打破查詢。 這樣的事情(未經測試的確切語法):
add_relationship("oak", "plastic'+(IF(ORD(SUBSTR(SELECT password_hash FROM users WHERE username='admin'),1,1)>=128, 'foo', ''))+'");
真的,只是逃避參數更容易,然后你不必擔心。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.