This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You can get a copy of the GNU General Public License from this address: http://www.gnu.org/copyleft/gpl.html#SEC1 You can also write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* There are no user-configurable settings in this file anymore, please see * config.php instead. */ /* This error handler will turn all notices, warnings, and errors into fatal * errors, unless they have been suppressed with the @-operator. */ function error_handler($errno, $errstr, $errfile, $errline, $errcontext) { /* The @-opertor (used with chdir() below) temporarely makes * error_reporting() return zero, and we don't want to die in that case. * We do note the error in the output, though. */ if (error_reporting() == 0) { $_SESSION['output'] .= $errstr . "\n"; } else { die(' PHP Shell 2.1

Fatal Error!

' . $errstr . '

in ' . $errfile . ', line ' . $errline . '.


Please consult the README, INSTALL, and SECURITY files for instruction on how to use PHP Shell.


Copyright © 2000–2005, Martin Geisler. Get the latest version at mgeisler.net/php-shell/.
'); } } /* Installing our error handler makes PHP die on even the slightest problem. * This is what we want in a security critical application like this. */ set_error_handler('error_handler'); function logout() { /* Empty the session data, except for the 'authenticated' entry which the * rest of the code needs to be able to check. */ $_SESSION = array('authenticated' => false); /* Unset the client's cookie, if it has one. */ // if (isset($_COOKIE[session_name()])) // setcookie(session_name(), '', time()-42000, '/'); /* Destroy the session data on the server. This prevents the simple * replay attach where one uses the back button to re-authenticate using * the old POST data since the server wont know the session then.*/ // session_destroy(); } function stripslashes_deep($value) { if (is_array($value)) return array_map('stripslashes_deep', $value); else return stripslashes($value); } if (get_magic_quotes_gpc()) $_POST = stripslashes_deep($_POST); /* Initialize some variables we need again and again. */ $username = isset($_POST['username']) ? $_POST['username'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; $nounce = isset($_POST['nounce']) ? $_POST['nounce'] : ''; $command = isset($_POST['command']) ? $_POST['command'] : ''; $rows = isset($_POST['rows']) ? $_POST['rows'] : 24; $columns = isset($_POST['columns']) ? $_POST['columns'] : 80; /* Load the configuration. */ $ini = parse_ini_file('config.php', true); if (empty($ini['settings'])) $ini['settings'] = array(); /* Default settings --- these settings should always be set to something. */ $default_settings = array('home-directory' => '.'); /* Merge settings. */ $ini['settings'] = array_merge($default_settings, $ini['settings']); session_start(); /* Delete the session data if the user requested a logout. This leaves the * session cookie at the user, but this is not important since we * authenticates on $_SESSION['authenticated']. */ if (isset($_POST['logout'])) logout(); /* Attempt authentication. */ if (isset($_SESSION['nounce']) && $nounce == $_SESSION['nounce'] && isset($ini['users'][$username])) { if (strchr($ini['users'][$username], ':') === false) { // No seperator found, assume this is a password in clear text. $_SESSION['authenticated'] = ($ini['users'][$username] == $password); } else { list($fkt, $salt, $hash) = explode(':', $ini['users'][$username]); $_SESSION['authenticated'] = ($fkt($salt . $password) == $hash); } } /* Enforce default non-authenticated state if the above code didn't set it * already. */ if (!isset($_SESSION['authenticated'])) $_SESSION['authenticated'] = false; if ($_SESSION['authenticated']) { /* Initialize the session variables. */ if (empty($_SESSION['cwd'])) { $_SESSION['cwd'] = realpath($ini['settings']['home-directory']); $_SESSION['history'] = array(); $_SESSION['output'] = ''; } if (!empty($command)) { /* Save the command for late use in the JavaScript. If the command is * already in the history, then the old entry is removed before the * new entry is put into the list at the front. */ if (($i = array_search($command, $_SESSION['history'])) !== false) unset($_SESSION['history'][$i]); array_unshift($_SESSION['history'], $command); /* Now append the commmand to the output. */ $_SESSION['output'] .= '$ ' . $command . "\n"; /* Initialize the current working directory. */ if (ereg('^[[:blank:]]*cd[[:blank:]]*$', $command)) { $_SESSION['cwd'] = realpath($ini['settings']['home-directory']); } elseif (ereg('^[[:blank:]]*cd[[:blank:]]+([^;]+)$', $command, $regs)) { /* The current command is a 'cd' command which we have to handle * as an internal shell command. */ if ($regs[1]{0} == '/') { /* Absolute path, we use it unchanged. */ $new_dir = $regs[1]; } else { /* Relative path, we append it to the current working * directory. */ $new_dir = $_SESSION['cwd'] . '/' . $regs[1]; } /* Transform '/./' into '/' */ while (strpos($new_dir, '/./') !== false) $new_dir = str_replace('/./', '/', $new_dir); /* Transform '//' into '/' */ while (strpos($new_dir, '//') !== false) $new_dir = str_replace('//', '/', $new_dir); /* Transform 'x/..' into '' */ while (preg_match('|/\.\.(?!\.)|', $new_dir)) $new_dir = preg_replace('|/?[^/]+/\.\.(?!\.)|', '', $new_dir); if ($new_dir == '') $new_dir = '/'; /* Try to change directory. */ if (@chdir($new_dir)) { $_SESSION['cwd'] = $new_dir; } else { $_SESSION['output'] .= "cd: could not change to: $new_dir\n"; } } elseif (trim($command) == 'exit') { logout(); } else { /* The command is not an internal command, so we execute it after * changing the directory and save the output. */ chdir($_SESSION['cwd']); // We canot use putenv() in safe mode. if (!ini_get('safe_mode')) { // Advice programs (ls for example) of the terminal size. putenv('ROWS=' . $rows); putenv('COLUMNS=' . $columns); } /* Alias expansion. */ $length = strcspn($command, " \t"); $token = substr($command, 0, $length); if (isset($ini['aliases'][$token])) $command = $ini['aliases'][$token] . substr($command, $length); $io = array(); $p = proc_open($command, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io); /* Read output sent to stdout. */ while (!feof($io[1])) { $_SESSION['output'] .= htmlspecialchars(fgets($io[1]), ENT_COMPAT, 'UTF-8'); } /* Read output sent to stderr. */ while (!feof($io[2])) { $_SESSION['output'] .= htmlspecialchars(fgets($io[2]), ENT_COMPAT, 'UTF-8'); } fclose($io[1]); fclose($io[2]); proc_close($p); } } /* Build the command history for use in the JavaScript */ if (empty($_SESSION['history'])) { $js_command_hist = '""'; } else { $escaped = array_map('addslashes', $_SESSION['history']); $js_command_hist = '"", "' . implode('", "', $escaped) . '"'; } } ?> PHP Shell 2.1

PHP Shell 2.1

Authentication Login failed, please try again:

' . "\n"; else echo "

Please login:

\n"; ?>

Username:

Password:

Current Working Directory:

Size: ×


Please consult the README, INSTALL, and SECURITY files for instruction on how to use PHP Shell.


Copyright © 2000–2005, Martin Geisler. Get the latest version at mgeisler.net/php-shell/.