{"id":50797,"date":"2020-11-07T03:01:09","date_gmt":"2020-11-06T17:01:09","guid":{"rendered":"http:\/\/www.rjmprogramming.com.au\/ITblog\/?p=50797"},"modified":"2020-11-07T07:53:38","modified_gmt":"2020-11-06T21:53:38","slug":"php-passthru-output-buffering-security-tutorial","status":"publish","type":"post","link":"https:\/\/www.rjmprogramming.com.au\/ITblog\/php-passthru-output-buffering-security-tutorial\/","title":{"rendered":"PHP Passthru Output Buffering Security Tutorial"},"content":{"rendered":"<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php\"><img decoding=\"async\" style=\"float:left; border: 15px solid pink;\" alt=\"PHP Passthru Output Buffering Security Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis_defence_one.jpg\" title=\"PHP Passthru Output Buffering Security Tutorial\"  \/><\/a><p class=\"wp-caption-text\">PHP Passthru Output Buffering Security Tutorial<\/p><\/div>\n<p>Serverside web applications <font size=1>(such as this current PHP one)<\/font>, more so than purely clientside web applications, are a bit like a lot of sports &#8230;<\/p>\n<ul>\n<li>there is the &#8220;offence&#8221; functionality side that provides a product or service to the user &#8230; as well as &#8230;<\/li>\n<li>there is the &#8220;defence&#8221; functionality side, depending on the architecture of the web application, that concerns itself with security<\/li>\n<\/ul>\n<p> &#8230; and our signature &#8220;Passthru&#8221; &#8220;whatis&#8221; web application ticks a lot of the boxes asking for a good &#8220;defence&#8221;.  Why?<\/p>\n<ul>\n<li>the (PHP serverside) web application accepts user input from a textbox, and feeds it back to itself via an HTML form, to perform more <i>underlying operating system<\/i> actions<\/li>\n<li>in the <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php_GETME\" title=\"whatis.php\">first incarnation of whatis.php<\/a> we set that form to method=GET &#8230; which makes it just too easy to have the worries below be a relevant (bad for security) issue<\/li>\n<li>if that <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php_GETME\" title=\"whatis.php\">first incarnation of whatis.php<\/a> was still current on the rjmprogramming.com.au website we could have circumvented any textbox validation we might have implemented (in a clientside sense) with whatever a savvy user might want to refeed into the web application via either &#8230;\n<ol>\n<li>web address bar URL like (for &#8220;whatis find&#8221;) &#8230;<br \/>\n<code>HTTP:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php?insearch=find<\/code>\n<\/li>\n<li>curl (command line entry (for &#8220;whatis find&#8221;)) &#8230;<br \/>\n<code>curl HTTP:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php?insearch=find<\/code>\n<\/li>\n<\/ol>\n<p> &#8230; as <i>benign<\/i> examples of the modus operandi\n<\/li>\n<\/ul>\n<p> &#8230; but what if the motivations of a user are not <i>benign<\/i>?   Well, yesterday&#8217;s <a href='#poops' title='Security Oops!'>Stop Press <font color=red>Oops!<\/font> intervention<\/a> is a case in point.  It is a &#8230;<\/p>\n<ul>\n<li>security issue, up to the programmer, for such &#8220;underlying operating system&#8221; leaning web applications to close things down as far as the role that textbox user input (or faux ones) so that you do not allow (and in doing so, not needing <font size=1>(and so we are not doing any as of this second incarnation)<\/font> any textbox validation that could cut off at a semicolon or less than sign or greater than sign or vertical (pipe) line character or line feed or carriage return, that textbox validation though could be used as a &#8220;virtue signal&#8221;) &#8230;\n<ol>\n<li>the user input data to contain a multi-command aspect to it &#8230; via scrutiny of $_POST[&#8216;insearch&#8217;] and\/or  $_GET[&#8216;insearch&#8217;] (if a <i>localhost<\/i> web server name in $_SERVER[&#8216;SERVER_NAME&#8217;])<\/li>\n<li>the user input data, yesterday and today, all along, at least ties down that &#8220;verb&#8221; word of the &#8220;operating system via PHP<br \/>\n passthru&#8221; command line <i>command<\/i> first (and all important) word (ie. hardcoded &#8220;whatis &#8220;)<\/li>\n<li>the user input data, yesterday and today, all along, at least ties down that &#8220;verb&#8221; word of the &#8220;operating system via PHP passthru&#8221; command line <i>command<\/i> switches the user might define that cause web server damage (though with &#8220;whatis&#8221; we could not think of any)<\/li>\n<li>call of web application must come from expected place &#8230; via examination of $_SERVER[&#8216;REFERER&#8217;]<\/li>\n<\/ol>\n<p> &#8230; the HTML form method=POST preferable to method=GET for those reasons already talked about\n<\/li>\n<li>limit modes of use as per table below &#8230;<br \/>\n<table border=1>\n<tr>\n<th>PHP Mode of use<\/th>\n<th>localhost web server<\/th>\n<th>rjmprogramming.com.au web server<\/th>\n<\/tr>\n<tr>\n<td>Surfing the web &#8230; no &#8220;whatis&#8221; user input<\/td>\n<td>Allowed (shows textbox for user input)<\/td>\n<td>Allowed (shows textbox for user input)<\/td>\n<\/tr>\n<tr>\n<td>Surfing the web &#8230; &#8220;whatis&#8221; user input<\/td>\n<td>Allowed (method=GET)<\/td>\n<td>Allowed (method=POST only)<\/td>\n<\/tr>\n<tr>\n<td>Curl &#8230; no &#8220;whatis&#8221; user input<\/td>\n<td>Allowed (nothing returned)<\/td>\n<td>Not allowed (nothing returned)<\/td>\n<\/tr>\n<tr>\n<td>Curl (NB. curl can (method=)POST) &#8230; &#8220;whatis&#8221; user input<\/td>\n<td>Allowed (via command line ? argument simulating method=GET)<\/td>\n<td>Not allowed (nothing returned)<\/td>\n<\/tr>\n<tr>\n<td>Command line &#8230; no &#8220;whatis&#8221; user input<\/td>\n<td>Not allowed (nothing returned)<\/td>\n<td>Not allowed (nothing returned)<\/td>\n<\/tr>\n<tr>\n<td>Command line &#8230; &#8220;whatis&#8221; user input<\/td>\n<td>Erroneous (Could not open input file: whatis.php?insearch=find)<\/td>\n<td>Erroneous (Could not open input file: whatis.php?insearch=find)<\/td>\n<\/tr>\n<\/table>\n<\/li>\n<\/ul>\n<p> &#8230; causing what we hope to be a similarly functional <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Geographicals\/diff.php?one=http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php-GETME\" title=\"whatis.php\">second changed whatis.php<\/a>, yet considerably more secure <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php-GETME\" title=\"whatis.php\">whatis.php<\/a> second incarnation of our &#8220;Passthru&#8221; &#8220;whatis&#8221; (report) <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php\">web application<\/a> improvement to <a title='PHP Passthru Output Buffering Primer Tutorial' href='#phppobpt'>PHP Passthru Output Buffering Primer Tutorial<\/a> &#8230;<\/p>\n<p><code><br \/>\n&lt;?php<br \/>\n \/\/ whatis.php<br \/>\n \/\/ Supervise whatis command<br \/>\n \/\/ November, 2020<br \/>\n<br \/> <br \/>\n $meth=\"POST\";<br \/>\n if (strpos((\"~\" . strtolower($_SERVER['SERVER_NAME'])), '~localhost') !== false) { $meth=\"GET\"; }<br \/>\n<br \/> <br \/>\n $gb=\"\";<br \/>\n try {<br \/>\n  if (strpos(('~' . $_SERVER['HTTP_USER_AGENT']), '~curl') === false) {<br \/>\n    $gb=\"y\";<br \/>\n  }<br \/>\n } catch (Exception $ee) {<br \/>\n }<br \/>\n<br \/> <br \/>\n $pins='';<br \/>\n if (isset($_POST['insearch']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), \"rjmprogramming.com.au\") !== false) {<br \/>\n   $pins=$_POST['insearch'];<br \/>\n } else if (isset($_GET['insearch']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), \"\/localhost\") !== false) {<br \/>\n   $pins=$_GET['insearch'];<br \/>\n } else if ($meth == \"GET\" && isset($_GET['insearch'])) {<br \/>\n   $pins=$_GET['insearch'];<br \/>\n } else if ($meth == \"GET\") {<br \/>\n   $pins=' ';<br \/>\n }<br \/>\n<br \/> <br \/>\n if (trim($pins) != '' && !isset($argv)) {<br \/>\n   if (urldecode($pins) == '') {<br \/>\n     echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=\" . $meth . \"&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n   } else if ($meth == \"GET\" && $gb == \"\") {<br \/>\n     passthru(\"whatis \" . explode(\"\\n\",explode(\"\\r\",explode(\";\",explode(\"&lt;\",explode(\"&gt;\",explode(\"|\",str_replace(\"+\",\" \",urldecode($pins)))[0])[0])[0])[0])[0])[0]);<br \/>\n   } else {<br \/>\n     ob_start();<br \/>\n     passthru(\"whatis \" . explode(\"\\n\",explode(\"\\r\",explode(\";\",explode(\"&lt;\",explode(\"&gt;\",explode(\"|\",str_replace(\"+\",\" \",urldecode($pins)))[0])[0])[0])[0])[0])[0]);<br \/>\n     $var = ob_get_contents();<br \/>\n     ob_end_clean();<br \/>\n     echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;pre&gt;$ whatis \" . explode(\"\\n\",explode(\"\\r\",explode(\";\",explode(\"&lt;\",explode(\"&gt;\",explode(\"|\",str_replace(\"+\",\" \",urldecode($pins)))[0])[0])[0])[0])[0])[0] . \"&lt;br&gt;\" . str_replace(\"\\n\", \"&lt;br&gt;\", $var) . \"&lt;\/pre&gt;&lt;br&gt;&lt;br&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=\" . $meth . \"&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n     exit;<br \/>\n   }<br \/>\n } else if (!isset($argv) && ($pins == '' || (trim($pins) == '' && $meth == \"GET\")) && !isset($_GET[$insh]) && $gb != \"\") {<br \/>\n   echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=\" . $meth . \"&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n }<br \/>\n<br \/> <br \/>\n?&gt;<br \/>\n<\/code><\/p>\n<p><!--p>You can also see this play out at WordPress 4.1.1's <a target=_blank  href='\/\/www.rjmprogramming.com.au\/ITblog\/php-passthru-output-buffering-security-tutorial\/'>PHP Passthru Output Buffering Security Tutorial<\/a>.<\/p-->\n<hr>\n<p id='phppobpt'>Previous relevant <a target=_blank title='PHP Passthru Output Buffering Primer Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/php-passthru-output-buffering-primer-tutorial\/'>PHP Passthru Output Buffering Primer Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php\"><img decoding=\"async\" style=\"float:left; border: 15px solid pink;\" alt=\"PHP Passthru Output Buffering Primer Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.jpg\" title=\"PHP Passthru Output Buffering Primer Tutorial\"  \/><\/a><p class=\"wp-caption-text\">PHP Passthru Output Buffering Primer Tutorial<\/p><\/div>\n<p>The PHP <a target=_blank title='PHP passthru() method information' href='http:\/\/php.net\/manual\/en\/function.passthru.php'><i>passthru<\/i><\/a> command &#8230;<\/p>\n<blockquote cite='https:\/\/www.php.net\/manual\/en\/function.passthru.php'><p>\nExecute an external program and display raw output\n<\/p><\/blockquote>\n<p> &#8230; is a good way for your underlying command line be expressed within a PHP web application executed in a web browser.<\/p>\n<p>But that &#8220;raw&#8221; above is just that, very &#8220;raw&#8221; in that the neat reports you see with Linux and macOS commands (at the command line) will not show that neatly just by using &#8220;passthru&#8221;.<\/p>\n<p>But you can use PHP output buffers <font color=blue>as per<\/font> <font size=1 color=red>(but there&#8217;s more)<\/font> &#8230;<\/p>\n<p><code><br \/>\n&lt;?php<br \/>\n \/\/ whatis.php<br \/>\n \/\/ Supervise whatis command<br \/>\n \/\/ November, 2020<br \/>\n if (isset($_GET['insearch'])) {<br \/>\n   if (urldecode($_GET['insearch']) == '') {<br \/>\n     echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=GET&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n   } else {<br \/>\n     <font color=blue><a target=_blank title='PHP ob_start method information' href='http:\/\/php.net\/manual\/en\/function.ob-start.php'>ob_start<\/a>();<\/font><br \/>\n     passthru(\"whatis \" . <font color=red>explode(\"\\n\",explode(\"\\r\",explode(\";\",<\/font>explode(\"&lt;\",explode(\"&gt;\",explode(\"|\",str_replace(\"+\",\" \",urldecode($_GET['insearch'])))[0])[0])[0]<font color=red>)[0])[0])[0]<\/font>);<br \/>\n     <font color=blue>$var = <a target=_blank title='PHP ob_get_contents method information' href='http:\/\/php.net\/manual\/en\/function.ob-get-contents.php'>ob_get_contents<\/a>();<br \/>\n     <a target=_blank title='PHP ob_end_clean method information' href='http:\/\/php.net\/manual\/en\/function.ob-end-clean.php'>ob_end_clean<\/a>();<\/font><br \/>\n     echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;pre&gt;\" . <font color=blue>\"$ whatis \" . <font color=red>explode(\"\\n\",explode(\"\\r\",explode(\";\",<\/font>explode(\"&lt;\",explode(\"&gt;\",explode(\"|\",str_replace(\"+\",\" \",urldecode($_GET['insearch'])))[0])[0])[0]<font color=red>)[0])[0])[0]<\/font> . \"&lt;br&gt;\" . str_replace(\"\\n\", \"&lt;br&gt;\", $var)<\/font> . \"&lt;\/pre&gt;&lt;br&gt;&lt;br&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=GET&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n     exit;<br \/>\n   }<br \/>\n } else {<br \/>\n   echo \"&lt;html&gt;&lt;body onload=\\\" document.getElementById('insearch').focus(); \\\"&gt;&lt;h1&gt;Supervise whatis command&lt;\/h1&gt;&lt;h3&gt;RJM Programming - November, 2020&lt;\/h3&gt;&lt;br&gt;&lt;br&gt;&lt;form action=.\/whatis.php method=GET&gt;&lt;input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''&gt;&lt;\/input&gt;&nbsp;&lt;input type=submit value=Go&gt;&lt;\/input&gt;&lt;\/form&gt;&lt;\/body&gt;&lt;\/html&gt;\";<br \/>\n }<br \/>\n<br \/>\n?&gt;<br \/>\n<\/code><\/p>\n<p> &#8230; to effectively reinstate those carriage return\/line feeds that make the &#8220;passthru&#8221; (underlying operating system) commands those neat reports appealing to our eyes.<\/p>\n<p>Better on a local <a target=_blank title='MAMP for Apache\/PHP\/MySql on Mac OS X local web server' href='http:\/\/www.mamp.info'><i>MAMP<\/i><\/a> web server (under macOS operating system) is today&#8217;s proof of concept <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php_GETME\" title=\"whatis.php\">whatis.php<\/a>&#8216;s <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/whatis.php\" title=\"Click picture\">&#8220;whatis&#8221; command supervisor<\/a> PHP web application for you to try out (or perhaps download to a local web server).<\/p>\n<p id=poops><i><b><font color=red>Stop Press<\/font><\/b><\/i><\/p>\n<p><font color=red>Oops!<\/font><\/p>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d50785' onclick='var dv=document.getElementById(\"d50785\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/passthru\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d50785' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d50797' onclick='var dv=document.getElementById(\"d50797\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/security\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d50797' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Serverside web applications (such as this current PHP one), more so than purely clientside web applications, are a bit like a lot of sports &#8230; there is the &#8220;offence&#8221; functionality side that provides a product or service to the user &hellip; <a href=\"https:\/\/www.rjmprogramming.com.au\/ITblog\/php-passthru-output-buffering-security-tutorial\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,29,37],"tags":[168,234,284,452,1533,744,1830,3467,853,3468,2427,932,970,997,1114,1200,1231,1319,1358,3470,3469],"class_list":["post-50797","post","type-post","status-publish","format-standard","hentry","category-elearning","category-operating-system","category-tutorials","tag-buffer","tag-command-line","tag-curl","tag-form","tag-get","tag-mamp","tag-method","tag-ob_get_contents","tag-ob_start","tag-output-buffer","tag-passthru","tag-php","tag-post","tag-programming","tag-security","tag-stop-press","tag-switches","tag-tutorial","tag-validation","tag-virtue-signal","tag-whatis"],"_links":{"self":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/50797"}],"collection":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/comments?post=50797"}],"version-history":[{"count":25,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/50797\/revisions"}],"predecessor-version":[{"id":50822,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/50797\/revisions\/50822"}],"wp:attachment":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/media?parent=50797"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/categories?post=50797"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/tags?post=50797"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}