Serverside web applications (such as this current PHP one), more so than purely clientside web applications, are a bit like a lot of sports …
- there is the “offence” functionality side that provides a product or service to the user … as well as …
- there is the “defence” functionality side, depending on the architecture of the web application, that concerns itself with security
… and our signature “Passthru” “whatis” web application ticks a lot of the boxes asking for a good “defence”. Why?
- the (PHP serverside) web application accepts user input from a textbox, and feeds it back to itself via an HTML form, to perform more underlying operating system actions
- in the first incarnation of whatis.php we set that form to method=GET … which makes it just too easy to have the worries below be a relevant (bad for security) issue
- if that first incarnation of whatis.php 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 …
- web address bar URL like (for “whatis find”) …
HTTP://www.rjmprogramming.com.au/PHP/whatis.php?insearch=find
- curl (command line entry (for “whatis find”)) …
curl HTTP://www.rjmprogramming.com.au/PHP/whatis.php?insearch=find
… as benign examples of the modus operandi
- web address bar URL like (for “whatis find”) …
… but what if the motivations of a user are not benign? Well, yesterday’s Stop Press Oops! intervention is a case in point. It is a …
- security issue, up to the programmer, for such “underlying operating system” 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 (and so we are not doing any as of this second incarnation) 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 “virtue signal”) …
- the user input data to contain a multi-command aspect to it … via scrutiny of $_POST[‘insearch’] and/or $_GET[‘insearch’] (if a localhost web server name in $_SERVER[‘SERVER_NAME’])
- the user input data, yesterday and today, all along, at least ties down that “verb” word of the “operating system via PHP
passthru” command line command first (and all important) word (ie. hardcoded “whatis “) - the user input data, yesterday and today, all along, at least ties down that “verb” word of the “operating system via PHP passthru” command line command switches the user might define that cause web server damage (though with “whatis” we could not think of any)
- call of web application must come from expected place … via examination of $_SERVER[‘REFERER’]
… the HTML form method=POST preferable to method=GET for those reasons already talked about
- limit modes of use as per table below …
PHP Mode of use localhost web server rjmprogramming.com.au web server Surfing the web … no “whatis” user input Allowed (shows textbox for user input) Allowed (shows textbox for user input) Surfing the web … “whatis” user input Allowed (method=GET) Allowed (method=POST only) Curl … no “whatis” user input Allowed (nothing returned) Not allowed (nothing returned) Curl (NB. curl can (method=)POST) … “whatis” user input Allowed (via command line ? argument simulating method=GET) Not allowed (nothing returned) Command line … no “whatis” user input Not allowed (nothing returned) Not allowed (nothing returned) Command line … “whatis” user input Erroneous (Could not open input file: whatis.php?insearch=find) Erroneous (Could not open input file: whatis.php?insearch=find)
… causing what we hope to be a similarly functional second changed whatis.php, yet considerably more secure whatis.php second incarnation of our “Passthru” “whatis” (report) web application improvement to PHP Passthru Output Buffering Primer Tutorial …
<?php
// whatis.php
// Supervise whatis command
// November, 2020
$meth="POST";
if (strpos(("~" . strtolower($_SERVER['SERVER_NAME'])), '~localhost') !== false) { $meth="GET"; }
$gb="";
try {
if (strpos(('~' . $_SERVER['HTTP_USER_AGENT']), '~curl') === false) {
$gb="y";
}
} catch (Exception $ee) {
}
$pins='';
if (isset($_POST['insearch']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), "rjmprogramming.com.au") !== false) {
$pins=$_POST['insearch'];
} else if (isset($_GET['insearch']) && strpos(strtolower('' . $_SERVER['HTTP_REFERER']), "/localhost") !== false) {
$pins=$_GET['insearch'];
} else if ($meth == "GET" && isset($_GET['insearch'])) {
$pins=$_GET['insearch'];
} else if ($meth == "GET") {
$pins=' ';
}
if (trim($pins) != '' && !isset($argv)) {
if (urldecode($pins) == '') {
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=" . $meth . "><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
} else if ($meth == "GET" && $gb == "") {
passthru("whatis " . explode("\n",explode("\r",explode(";",explode("<",explode(">",explode("|",str_replace("+"," ",urldecode($pins)))[0])[0])[0])[0])[0])[0]);
} else {
ob_start();
passthru("whatis " . explode("\n",explode("\r",explode(";",explode("<",explode(">",explode("|",str_replace("+"," ",urldecode($pins)))[0])[0])[0])[0])[0])[0]);
$var = ob_get_contents();
ob_end_clean();
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><pre>$ whatis " . explode("\n",explode("\r",explode(";",explode("<",explode(">",explode("|",str_replace("+"," ",urldecode($pins)))[0])[0])[0])[0])[0])[0] . "<br>" . str_replace("\n", "<br>", $var) . "</pre><br><br><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=" . $meth . "><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
exit;
}
} else if (!isset($argv) && ($pins == '' || (trim($pins) == '' && $meth == "GET")) && !isset($_GET[$insh]) && $gb != "") {
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=" . $meth . "><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
}
?>
Previous relevant PHP Passthru Output Buffering Primer Tutorial is shown below.
The PHP passthru command …
Execute an external program and display raw output
… is a good way for your underlying command line be expressed within a PHP web application executed in a web browser.
But that “raw” above is just that, very “raw” in that the neat reports you see with Linux and macOS commands (at the command line) will not show that neatly just by using “passthru”.
But you can use PHP output buffers as per (but there’s more) …
<?php
// whatis.php
// Supervise whatis command
// November, 2020
if (isset($_GET['insearch'])) {
if (urldecode($_GET['insearch']) == '') {
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=GET><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
} else {
ob_start();
passthru("whatis " . explode("\n",explode("\r",explode(";",explode("<",explode(">",explode("|",str_replace("+"," ",urldecode($_GET['insearch'])))[0])[0])[0])[0])[0])[0]);
$var = ob_get_contents();
ob_end_clean();
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><pre>" . "$ whatis " . explode("\n",explode("\r",explode(";",explode("<",explode(">",explode("|",str_replace("+"," ",urldecode($_GET['insearch'])))[0])[0])[0])[0])[0])[0] . "<br>" . str_replace("\n", "<br>", $var) . "</pre><br><br><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=GET><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
exit;
}
} else {
echo "<html><body onload=\" document.getElementById('insearch').focus(); \"><h1>Supervise whatis command</h1><h3>RJM Programming - November, 2020</h3><br><br><form action=./whatis.php method=GET><input placeholder='Enter whatis object' type=text id=insearch name=insearch value=''></input> <input type=submit value=Go></input></form></body></html>";
}
?>
… to effectively reinstate those carriage return/line feeds that make the “passthru” (underlying operating system) commands those neat reports appealing to our eyes.
Better on a local MAMP web server (under macOS operating system) is today’s proof of concept whatis.php‘s “whatis” command supervisor PHP web application for you to try out (or perhaps download to a local web server).
Stop Press
Oops!
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.