MySQL 數據庫系統表的利用

個人博客文章:MySQL 數據庫系統表的利用

背景

學習目標:

  1. 如何利用數據庫的功能讀寫文件,需要什麼樣的條件纔可以讀寫;

  2. 學習數據庫系統表的功能,如何利用 sql 語句查詢庫名、表名、字段名、內容以及當前用戶等基本信息;

  3. 嘗試查詢出用戶的 hash,並使用 hashcat 來對獲取的 hash 進行暴力破解。

MySQL 讀寫文件

讀文件

使用 load_file() 函數

load_file(file_name) 函數讀取文件內容,將內容以字符串的形式返回。

前提條件

  • secure_file_priv 不爲 NULL,使用 select @@secure_file_priv查看其值,值不爲空字符串時,只能使用該目錄進行文件的讀寫操作, 該值的設置見附錄
  • 當前數據庫用戶具有 FILE 權限,使用 show grants查看;
  • 系統用戶 mysql 對該文件可讀(要考慮系統的訪問控制策略),在Ubuntu-18.04使用 MySQL 時默認的系統用戶是 mysql
  • 讀取文件的大小小於 max_allowed_packet,使用 select @@max_allowed_packet查看;
  • 文件存在服務器上。

如果上述任一條件不滿足,函數返回 NULL 值。

用法

select load_file('filename');  

**例子:**讀取文件 /mysql/test.csv

mysql> select  @@secure_file_priv,@@max_allowed_packet;
+--------------------+----------------------+
| @@secure_file_priv | @@max_allowed_packet |
+--------------------+----------------------+
|                    |             16777216 |
+--------------------+----------------------+
mysql> show grants;
+----------------------------------------------------------------------------------------------+
| Grants for user101@localhost                                                                 |
+----------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, DELETE, CREATE, FILE ON *.* TO 'user101'@'localhost' WITH GRANT OPTION |
+----------------------------------------------------------------------------------------------+
mysql> select load_file('/mysql/test.csv');
+------------------------------+
| load_file('/mysql/test.csv') |
+------------------------------+
| 3,Hack
4,World
5,Surprise!
  |
+------------------------------+

**問題:**在設置 secure_file_privilege='' 且目錄權限爲 777load_file() 無法讀取文件

**解決方案:**Ubuntu 自帶的強制訪問控制系統 AppArmor 強制限制了每個程序可使用的資源,它並非針對用戶,而是針對程序的,所以不論用戶是否能訪問某一資源,只要程序被 AppArmor 限制訪問該資源,則程序就不能訪問該資源。因此需要修改 AppArmor 針對於 MySQL 的訪問控制策略,修改文件 /etc/apparmor.d/usr.sbin.mysqld,在其中添加需要訪問的目錄。

**參考:**https://stackoverflow.com/questions/4215231/load-data-infile-error-code-13

使用 LOAD DATA 語句

laod_file()函數只能從 服務器中讀取文件,LOAD DATA語句既能讀取服務器的文件,也能讀取 MySQL 客戶機的文件,兩種方式語法上稍有不同。

**前提條件:**和 load_file() 函數使用條件相同,但通過使用 LOCAL 語句從客戶主機讀取文件內容。

用法:

#[] 中的內容爲可選內容
LOAD DATA
    [LOW_PRIORITY | CONCURRENT] [LOCAL] #使用 LOCAL 表示從客戶主機讀取文件,要設置 mysqld 中的系統變量 local_infile
    INFILE 'file_name'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [CHARACTER SET charset_name] #處理文件的字符集
    [{FIELDS | COLUMNS}  #描述每一列的格式
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES   #描述行的格式,不滿足的行會被略過
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number {LINES | ROWS}] #忽略指定行或列
    [(col_name_or_user_var
        [, col_name_or_user_var] ...)] #寫到數據表中的指定列
    [SET col_name={expr | DEFAULT}, 
        [, col_name={expr | DEFAULT}] ...]

**例子:**讀取文件 /mysql/test.csv 到已有的數據表中。CSV文件內容如下:

3,Hack
4,World
5,Surprise!
mysql> select * from test;
+----+------+
| id | name |
+----+------+
|  1 | May  |
|  2 | June |
+----+------+

mysql> load data infile '/mysql/test.csv' into table test fields terminated by ',';
Query OK, 3 rows affected (0.00 sec)

mysql> select * from test;                                                     
| id | name      |
+----+-----------+
|  1 | May       |
|  2 | June      |
|  3 | Hack      |
|  4 | World     |
|  5 | Surprise! |
+----+-----------+
5 rows in set (0.00 sec)

寫文件

使用 SELECT INTO OUTFILE 語句

SELECT INTO OUTFILELOAD DATA 這兩條語句是完全互補的,一個寫文件,一個讀文件,語句的語法也很相似。

前提條件:**

  • secure_file_priv不爲 NULL,使用select @@secure_file_priv`查看其值,值不爲空字符串時,只能使用該目錄進行文件的讀寫操作, 該值的設置見附錄
  • 當前數據庫用戶具有 FILE 權限,使用 show grants查看;
  • 系統用戶 mysql 對該文件可寫(要考慮系統的訪問控制策略),在Ubuntu-18.04使用 MySQL 時默認的系統用戶是 mysql
  • 讀取文件的大小小於 max_allowed_packet,使用 select @@max_allowed_packet查看;
  • 文件不存在。

用法:

#[] 中的內容爲可選內容
SELECT select_expr...
	INTO OUTFILE 'file_name'
    [CHARACTER SET charset_name] #處理文件的字符集
    [{FIELDS | COLUMNS}  #描述每一列的格式
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES   #描述行的格式
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]

**例子:**寫數據表到 CSV 文件中。

mysql> select * from comments;
+----+---------------------------+
| id | comment                   |
+----+---------------------------+
|  1 | test                      |
|  2 | hhhh                      |
|  3 | Need lots of improvements |
+----+---------------------------+
3 rows in set (0.00 sec)

mysql> select comment from comments where id>1 into outfile '/mysql/comments.csv' fields terminated by ',';
Query OK, 2 rows affected (0.00 sec)                     

/mysql/comments.csv 內容:

 hhhh
 Need lots of improvements

注:

使用 SELECT INTO DUMPFILE 可將文件內容寫成一行.

mysql> select comment from comments where id>1 into dumpfile '/mysql/comments';
Query OK, 2 rows affected (0.00 sec) 

/mysql/comments.csv 內容:

hhhhNeed lots of improvements

如果想把遠程數據庫的查詢結果寫到本地主機文件上, 可用:

mysql -h hostname -P portnum -u username -p databsename -e "SELECT ..." > file_name

MySQL 數據庫系統表

MySQL-5.7 默認的系統表/視圖 放在4個數據庫/schema 中,。

在 MySQL 中 schemadatabase 是一樣的就不做區分, 但實際上是有區別的,可以參考這篇文章

視圖也稱爲虛表,是爲了便於查詢某些信息,建立在查詢結果之上的表,所以視圖其實就是被保存起來的一次查詢。視圖和表的區別簡單來說就是視圖存儲的是SQL查詢語句執行的結果,以表的形式存在但在數據庫中並沒有這個表。

庫名 視圖數量 基表數量
information_schema 61 0
mysql 0 31
performance_schema 0 87
sys 100 1(sys_config)

MySQL 數據庫管理系統中的系統表很多,這裏主要介紹和在SQL 注入中常的幾個表和視圖。

information_schema 數據庫

information_schema存放着 MySQL 服務器維護的所有數據庫的詳細信息, 包括數據庫名、表名、列名、列的數據類型、訪問權限等等。

常用視圖

在進行 SQL 注入時比較有用的幾個視圖:SCHEMATACOLUMNSTABLESuser_privileges

schemata 視圖存放 MySQL 數據管理系統中的所有數據的基本信息,叢中可以獲取所有數據庫名字,數據庫使用的字符集、排序規則(collation,數據庫中數據進行排序時的規則,升序、降序,是否忽略大小寫等)

mysql> select * from schemata;
+--------------+--------------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME        | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+--------------------+----------------------------+------------------------+----------+
| def          | information_schema | utf8                       | utf8_general_ci        | NULL     |
| def          | mysql              | latin1                     | latin1_swedish_ci      | NULL     |
| def          | performance_schema | utf8                       | utf8_general_ci        | NULL     |
| def          | sys                | utf8                       | utf8_general_ci        | NULL     |
| def          | webdb101           | latin1                     | latin1_swedish_ci      | NULL     |
+--------------+--------------------+----------------------------+------------------------+----------+

columns 視圖存放列相關的信息,常用字段 table_schema(數據庫名), table_name(表名),column_name(列名)。

mysql> desc columns;
+--------------------------+---------------------+------+-----+---------+-------+
| Field                    | Type                | Null | Key | Default | Extra |
+--------------------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG            | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA             | varchar(64)         | NO   |     |         |       |
| TABLE_NAME               | varchar(64)         | NO   |     |         |       |
| COLUMN_NAME              | varchar(64)         | NO   |     |         |       |
| ORDINAL_POSITION         | bigint(21) unsigned | NO   |     | 0       |       |
| COLUMN_DEFAULT           | longtext            | YES  |     | NULL    |       |
| IS_NULLABLE              | varchar(3)          | NO   |     |         |       |
| DATA_TYPE                | varchar(64)         | NO   |     |         |       |
| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| CHARACTER_OCTET_LENGTH   | bigint(21) unsigned | YES  |     | NULL    |       |
| NUMERIC_PRECISION        | bigint(21) unsigned | YES  |     | NULL    |       |
| NUMERIC_SCALE            | bigint(21) unsigned | YES  |     | NULL    |       |
| DATETIME_PRECISION       | bigint(21) unsigned | YES  |     | NULL    |       |
| CHARACTER_SET_NAME       | varchar(32)         | YES  |     | NULL    |       |
| COLLATION_NAME           | varchar(32)         | YES  |     | NULL    |       |
| COLUMN_TYPE              | longtext            | NO   |     | NULL    |       |
| COLUMN_KEY               | varchar(3)          | NO   |     |         |       |
| EXTRA                    | varchar(30)         | NO   |     |         |       |
| PRIVILEGES               | varchar(80)         | NO   |     |         |       |
| COLUMN_COMMENT           | varchar(1024)       | NO   |     |         |       |
| GENERATION_EXPRESSION    | longtext            | NO   |     | NULL    |       |
+--------------------------+---------------------+------+-----+---------+-------+

tables 存放表相關的信息,常用字段 table_schema(數據庫名), table_name(表名)。

mysql> desc tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)

user_privileges 存放用戶的權限信息。

mysql> desc information_schema.user_privileges;
+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| GRANTEE        | varchar(81)  | NO   |     |         |       |  #被授權的用戶名
| TABLE_CATALOG  | varchar(512) | NO   |     |         |       |
| PRIVILEGE_TYPE | varchar(64)  | NO   |     |         |       |  #權限名,如 SELECT、INSERT 等
| IS_GRANTABLE   | varchar(3)   | NO   |     |         |       |  #是否授權,YES/NO
+----------------+--------------+------+-----+---------+-------+

視圖信息利用

用戶權限查詢

  1. 獲取當前用戶名
selectmysql> select user();
+-------------------+
| user()            |
+-------------------+
| user101@localhost |
+-------------------+
  1. 獲取用戶權限
mysql> select * from information_schema.user_privileges where grantee like '%user101%';
+-----------------------+---------------+----------------+--------------+
| GRANTEE               | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE |
+-----------------------+---------------+----------------+--------------+
| 'user101'@'localhost' | def           | SELECT         | YES          |
| 'user101'@'localhost' | def           | INSERT         | YES          |
| 'user101'@'localhost' | def           | UPDATE         | YES          |
| 'user101'@'localhost' | def           | DELETE         | YES          |
| 'user101'@'localhost' | def           | CREATE         | YES          |
| 'user101'@'localhost' | def           | FILE           | YES          |
+-----------------------+---------------+----------------+--------------+

注入時可以利用 information_schema 數據庫進行信息查詢,一般步驟有:

  1. 獲取數據庫名
mysql> select schema_name from information_schema.schemata;
+--------------------+
| schema_name        |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| webdb101           |
+--------------------+
  1. 獲取表名
mysql> select table_name from information_schema.tables where table_schema='webdb101';
+------------+
| table_name |
+------------+
| comments   |
| test       |
+------------+
  1. 獲取列名
mysql> select column_name from information_schema.columns where table_name='test';
+-------------+
| column_name |
+-------------+
| id          |
| name        |
+-------------+

mysql 數據庫

mysql 數據中存放的都是表,常用的表有 userdb

user表中常用字段有 userhostauthentication_string(存儲密碼的字段,MySQL 版本相關,低一些的版本爲 password)等。

查詢所有用戶名、連接主機和密碼哈希

mysql> select user,host,authentication_string from mysql.user;
+------------------+-----------+-------------------------------------------+
| user             | host      | authentication_string                     |
+------------------+-----------+-------------------------------------------+
| root             | localhost |                                           |
| mysql.session    | localhost | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.sys        | localhost | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| debian-sys-maint | localhost | *962236403F954BF9C92EBDBA0BC04F7CE7FCFB89 |
| user101          | localhost | *6331E4D15433B998EF878BE017AE2A0878316CCC |
+------------------+-----------+-------------------------------------------+

在進行 sql 注入使用常常使用 group_concat(col_name…) 將多個列的信息連成一句話輸出,便於回顯到瀏覽器。

如獲取用戶名及其密碼的一條注入語句:

select group_concat(user, authentication_string) from mysql.user

用戶密碼爆破

MySQL 用戶的密碼存儲方式並非明文直接存儲,而是經過 hash 函數加密進行存儲的,從 mysql.user中獲取到 MySQL 用戶密碼的哈希值後,需要使用工具進行破解。

工具:hashcat

hashcat 號稱最快的高級密碼恢復套機(密碼破解工具),支持多系統(Linux,OS,Windows),多平臺(GPU,CPU,DSP等),支持多達 200 多種的 Hash 類型,支持使用同一系統的不同設備,支持分佈式系統資源等,重要的是開源啊!

下載安裝:

推薦在 Windows 上使用,最好不用虛擬機,這樣安裝最簡單,而且能充分利用 hashcat 支持多設備的特點,在 Linux 上安裝需要安裝很多東西,而且問題特別多,除非特別需要,個人不建議。

使用:

./hashcat64.exe -m 300 -a 3 hashfile -o plaintxt --outfile-format=2 ?a?a?a?a?a?a

參數:

-m 300:hash 類型,200多種,詳見: hashcat --help,300 選擇的是 MySQL4/5 的hash

-a 3:攻擊模式,總共5種,3 表示爆破模式,所有攻擊模式如下表:

攻擊模式
0 Straight:字典模式,從字典內容中依次選擇密碼候選,進行哈希計算,看是否和待破解的哈希值相同
1 Combination:組合模式,將兩個字典的內容組合作爲字典內容,可以通過 -k-j 選項爲兩個字典添加額外規則
3 Brute-force:爆破模式/掩碼模式,使用掩碼固定密碼的字符集,減小爆破的候選密碼數,掩碼格式見下文。
6 Hybrid Wordlist + Mask:混合模式(字典+掩碼),通過字典後接掩碼的方式構建最終的密碼候選。
7 Hybrid Mask + Wordlist:混合模式(掩碼+字典),通過掩碼後接字典的方式構建最終的密碼候選,和上面的組合順序相反。

-o pliantxt :破解後輸出到文件 plaintxt

--outfile-format=2:輸出文件格式,2表示只輸出破解後的內容,所有可用格式如下表

輸出文件格式
1 hash[:salt]
2 plain
3 hash[:salt]:plain
4 hex_plain
5 hash[:salt]:hex_plain
6 plain:hex_plain
7 hash[:salt]:plain:hex_plain
8 crackpos
9 hash[:salt]:crack_pos
10 plain:crack_pos
11 hash[:salt]:plain:crack_pos
12 hex_plain:crack_pos
13 hash[:salt]:hex_plain:crack_pos
14 plain:hex_plain:crack_pos
15 hash[:salt]:plain:hex_plain:crack_pos

?a?a?a?a?a?a:這表示密碼的掩碼,所謂的掩碼就是通過 ?[字符集代號]… 的格式表示密碼的格式,包括密碼的位數和每一位密碼使用的字符集。?a 表示所有的鍵盤上可輸入的字符,6個?a表示密碼有6位。hashcat 內置字符集如下:

字符集代號 字符集
l abcdefghijklmnopqrstuvwxyz
u ABCDEFGHIJKLMNOPQRSTUVWXYZ
d 0123456789
h 0123456789abcdef
H 0123456789ABCDEF
s !"#$%&’()*+,-./:;<=>?@[]^_`{
a ?l?u?d?s
b 0x00 - 0xff

還通過選項自定義字符集,自定以的字符集對應的字符集代號爲 1,2,3,4:

--custom-charset1=CS  #同 -1 的短選項
--custom-charset2=CS  #同 -2 
--custom-charset3=CS  #同 -3
--custom-charset4=CS  #同 -4

如果得知密碼第一位爲大寫字母且不包含字符的8爲密碼,可自定義掩碼,加快解密過程:

hashcat -m 300 -a 3 -1 ?l?u?d hashfile ?u?1?1?1?1?1?1?1

參考

  1. SQL注入-文件操作
  2. load-file
  3. LOAD DATA 語法
  4. MySQL常用系統表彙總

附錄

MySQLsecure_file_priv 變量

Property Value
Command-Line Format --secure-file-priv=dir_name
System Variable secure_file_priv
Scope Global
Dynamic No,表示不能動態使用 set 命令進行設置,只能通過配置文件設置,如在 ~/.my.
Type String
Default Value (>= 5.7.6) platform specific
Default Value (<= 5.7.5) empty string
Valid Values (>= 5.7.6) empty string
dirname
NULL
Valid Values (<= 5.7.5) empty string
dirname

該變量限制 MySQL 用戶對文件的讀寫操作,可設置爲以下值:

  1. 空字符串;
  2. 特定路徑名;
  3. NULL,表示不允許文件的讀寫操作;

具體可在 MySQL 啓動配置文件 /etc/mysql/my.cnf 中設置如下:

[mysql_safe] #服務器啓動腳本
[mysqld] #服務器端配置
secure_file_priv = "" #設置讀取文件目錄爲任意目錄

my.cnf 文件中配置格式:

[group] #常用的 group 有 mysqld:MySQL 服務器,client:MySQL 客戶端,mysql_safe:服務器啓動腳本
opt_name #等同命令行中 --opt_name 選項
opt_name=value #等同命令行中 --opt_name=vale

不同平臺的默認值:

INSTALL_LAYOUT Value Default secure_file_priv Value
STANDALONE empty
DEB, RPM, SVR4 /var/lib/mysql-files
Otherwise mysql-files under the CMAKE_INSTALL_PREFIXvalue
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章