Search code examples
coldfusioncoldfusion-9exploit

ColdFusion 9 - File Write detection (anti-exploit)


I have a web server (IIS 7) with ~400,000 files on it. 80,000 of these are .cfm files. I believe that one of those files is permitting an exploit whereby a file can be uploaded anywhere in wwwroot.

I think this because I enabled windows auditing, and see that the file generated has an event log specifying JRun.exe as the culprit. It is definitely written to disk by Jrun.

I need to know the best way to determine which coldfusion script running inside Jrun's singular instance is causing the file to be written to disk.

I am about to override the java.io namespace, unless someone here has a better idea. And yes, I ran PowerGREP utility to scan all files for file write strings, such as:

  • CFIDE.componentutils.cfcexplorer
  • action="upload" (+single quotes, and ="write")
  • java.io
  • BufferedWriter etc

The exploit I'm seeing appear in numbers is: http://pastebin.com/sNGycNZS Simple google search by content yielded it.


Solution

  • Alright, so I ended up decompiling java.io.FileOutputStream.class inside Coldfusion\runtime\jre\lib\rt.jar And patching it to log to the event log for each function that performs the Write() function.

    public FileOutputStream(String paramString)
    throws FileNotFoundException{  // aka @override
        this(paramString != null ? new File(paramString) : null, false);
        DoEvent("_Single_", "FileOutputStream(" + paramString + "): ");
    }
    
    // my attempt at forcing line breaks in through command prompt were insufficient. So I used regex after-the-fact to replace %NL% with \r\n. :P
    public static void DoEvent(String type, String description)  {
    if (description.contains("wwwroot"))
    {
      StackTraceElement[] stack = Thread.currentThread().getStackTrace();
      StringBuilder sz = new StringBuilder();
      String linefeed = "%NL%";
      for (StackTraceElement s : stack)
      {
        sz.append(s.toString());
        sz.append(linefeed + "-------------" + linefeed);
      }
      description = description + linefeed + sz.toString();
      String command = "cmd /c \"SET NLM=^\r\n\r\n && set NL=^^^%NLM%%NLM%^%NLM%%NLM% && ";
      command = command + "eventcreate  /l APPLICATION /so \"COLDFUSION FILE WRITE :: " + type + " " + "\"" + " /t " + "ERROR" + " /id " + new Random().nextInt(500) + " /d \"" + description + "\"";
    
      command = command + "\"";
      try
      {
        Runtime.getRuntime().exec(command);
      }
      catch (IOException e) {}
    } 
    

    Which yielded results:

    FileOutputStream(E:\.....\wwwroot\public\subdomain.site.com\images\veryver.cfm):
    java.lang.Thread.getStackTrace(Thread.java:1479)
    ^--> java.io.FileOutputStream.DoEvent(FileOutputStream.java:26)
    ^--> java.io.FileOutputStream.<init>(FileOutputStream.java:75)
    ^--> java.io.FileOutputStream.<init>(FileOutputStream.java:60)
    ^--> coldfusion.vfs.VFSFileFactory.fetchOutputStream(VFSFileFactory.java:442)
    ^--> coldfusion.vfs.VFSFileFactory.getOutputStream(VFSFileFactory.java:283)
    ^--> coldfusion.tagext.io.FileUtils.copyFile(FileUtils.java:944)
    ^--> coldfusion.tagext.io.FileUtils$2.run(FileUtils.java:613)
    ^--> java.security.AccessController.doPrivileged(Native Method)
    ^--> coldfusion.tagext.io.FileUtils.uploadFile(FileUtils.java:609)
    ^--> coldfusion.tagext.io.FileTag.upload(FileTag.java:591)
    ^--> coldfusion.tagext.io.FileTag.doStartTag(FileTag.java:266)
    ^--> coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722)
    ^--> cftvb2ecfm60673673._factor26(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:468)
    ^--> cftvb2ecfm60673673._factor27(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:466)
    ^--> cftvb2ecfm60673673._factor28(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:465)
    ^--> cftvb2ecfm60673673._factor29(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:464)
    ^--> cftvb2ecfm60673673._factor121(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:462)
    ^--> cftvb2ecfm60673673._factor124(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:76)
    ^--> cftvb2ecfm60673673._factor125(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:72)
    ^--> cftvb2ecfm60673673.runPage(E:\....\wwwroot\CFIDE\scripts\tvb.cfm:1)
    ^--> coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231)
    ^--> coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416)
    ^--> coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65)
    ^--> coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:387)
    ^--> coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)
    ^--> coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
    ^--> coldfusion.filter.PathFilter.invoke(PathFilter.java:94)
    ^--> coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)
    ^--> coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
    ^--> coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
    ^--> coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)
    ^--> coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
    ^--> coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
    ^--> coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)
    ^--> coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:126)
    ^--> coldfusion.CfmServlet.service(CfmServlet.java:201)
    ^--> coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
    ^--> jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
    ^--> coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
    ^--> coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
    ^--> jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
    ^--> jrun.servlet.FilterChain.service(FilterChain.java:101)
    ^--> jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
    ^--> jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
    ^--> jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
    ^--> jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
    ^--> jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
    ^--> jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
    ^--> jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
    ^--> jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
    ^--> jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
    ^--> 
    

    So as you can see, it was a remnant script located in CFIDE. Not sure how they accessed it, because it's outside of the scope of public accessible documents. You have to have VPN access AND remote desktop, just to access CFIDE.

    Anyway, so I solved this by removing the file. Please also note that I used this same method to trace what wrote the above mentioned file, and determined it to be a compiled coldfusion class inside the Coldfusion classes/cache folder. E:\ColdFusion9\wwwroot\WEB-INF\cfclasses\

    I deleted it to be safe, though the code seems quite docile when decompiled. i would also recommend everyone to check their system's scheduled tasks, as well as coldfusion's scheduled tasks, and any cf probes.

    In order to assist others in finding this content, here are some strings for google (ordered by frequency of occurrence within infected file --- scan in .php,.cf?, and *.class):

    • S?bastien Denis
    • CFIDE.componentutils.cfcexplorer
    • hermes
    • Silence is golden

    And the most-common files:

    • veryver.cfm
    • img.cfm
    • co.cfm
    • as.cfm
    • good.cfm
    • z.txt

    And the targets of the attack:

    I'd like to have attached the source code to that .class i spoke of, but can't seem to find the option on this site. Probably for the better that I don't share the source of it anyway.

    Thanks for the help all :)