-
-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
241 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,96 @@ | ||
<?php | ||
namespace samdark\webshell; | ||
|
||
use Yii; | ||
use yii\web\ForbiddenHttpException; | ||
|
||
/** | ||
* This is the main module class for the web shell module. | ||
* | ||
* To use web shell, include it as a module in the application configuration like the following: | ||
* | ||
* ~~~ | ||
* return [ | ||
* 'modules' => [ | ||
* 'webshell' => ['class' => 'samdark\webshell\Module'], | ||
* ], | ||
* ] | ||
* ~~~ | ||
* | ||
* With the above configuration, you will be able to access web shell in your browser using | ||
* the URL `http://localhost/path/to/index.php?r=webshell` | ||
* | ||
* @author Alexander Makarov <sam@rmcreative.ru> | ||
*/ | ||
class Module extends \yii\base\Module | ||
{ | ||
public $exitUrl = null; | ||
/** | ||
* @inheritdoc | ||
*/ | ||
public $controllerNamespace = 'samdark\webshell\controllers'; | ||
|
||
/** | ||
* @var string console greetings | ||
*/ | ||
public $greetings = 'Yii 2.0 web shell'; | ||
|
||
/** | ||
* @var array URL to use for `quit` command. If not set, `quit` command will do nothing. | ||
*/ | ||
public $quitUrl; | ||
|
||
/** | ||
* @var string path to `yii` script | ||
*/ | ||
public $yiiScript = '@app/yii'; | ||
|
||
/** | ||
* @var array the list of IPs that are allowed to access this module. | ||
* Each array element represents a single IP filter which can be either an IP address | ||
* or an address with wildcard (e.g. 192.168.0.*) to represent a network segment. | ||
* The default value is `['127.0.0.1', '::1']`, which means the module can only be accessed | ||
* by localhost. | ||
*/ | ||
public $allowedIPs = ['127.0.0.1', '::1']; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function init() | ||
{ | ||
parent::init(); | ||
set_time_limit(0); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function beforeAction($action) | ||
{ | ||
if (!parent::beforeAction($action)) { | ||
return false; | ||
} | ||
|
||
if (Yii::$app instanceof \yii\web\Application && !$this->checkAccess()) { | ||
throw new ForbiddenHttpException('You are not allowed to access this page.'); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* @return boolean whether the module can be accessed by the current user | ||
*/ | ||
protected function checkAccess() | ||
{ | ||
$ip = Yii::$app->getRequest()->getUserIP(); | ||
foreach ($this->allowedIPs as $filter) { | ||
if ($filter === '*' || $filter === $ip || (($pos = strpos($filter, '*')) !== false && !strncmp($ip, $filter, $pos))) { | ||
return true; | ||
} | ||
} | ||
Yii::warning('Access to web shell is denied due to IP address restriction. The requested IP is ' . $ip, __METHOD__); | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
body { | ||
background: black; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,80 @@ | ||
<?php | ||
|
||
|
||
namespace samdark\webshell\controllers; | ||
|
||
|
||
use Yii; | ||
use yii\helpers\Json; | ||
use yii\helpers\Url; | ||
use yii\web\Controller; | ||
use yii\web\Response; | ||
|
||
/** | ||
* DefaultController | ||
* | ||
* @author Alexander Makarov <sam@rmcreative.ru> | ||
* | ||
* @property \samdark\webshell\Module $module | ||
*/ | ||
class DefaultController extends Controller | ||
{ | ||
/** | ||
* @inheritdoc | ||
*/ | ||
public function init() | ||
{ | ||
Yii::$app->request->enableCsrfValidation = false; | ||
parent::init(); | ||
} | ||
|
||
/** | ||
* Displays initial HTML markup | ||
* @return string | ||
*/ | ||
public function actionIndex() | ||
{ | ||
$this->layout = 'shell'; | ||
return $this->render('index'); | ||
return $this->render('index', [ | ||
'quitUrl' => $this->module->quitUrl ? Url::toRoute($this->module->quitUrl) : null, | ||
'greetings' => $this->module->greetings | ||
]); | ||
} | ||
|
||
/** | ||
* ./yii proxy | ||
* RPC handler | ||
* @return array | ||
*/ | ||
public function actionYii() | ||
public function actionRpc() | ||
{ | ||
Yii::$app->response->format = Response::FORMAT_JSON; | ||
|
||
$options = Json::decode(Yii::$app->request->getRawBody()); | ||
|
||
switch ($options['method']) { | ||
case 'yii': | ||
list ($status, $output) = $this->runConsole(implode(' ', $options['params'])); | ||
return ['result' => $output]; | ||
} | ||
} | ||
|
||
/** | ||
* Runs console command | ||
* | ||
* @param string $command | ||
* | ||
* @return array [status, output] | ||
*/ | ||
private function runConsole($command) | ||
{ | ||
$cmd = Yii::getAlias($this->module->yiiScript) . ' ' . $command . ' 2>&1'; | ||
|
||
$handler = popen($cmd, 'r'); | ||
$output = ''; | ||
while (!feof($handler)) { | ||
$output .= fgets($handler); | ||
} | ||
|
||
$output = trim($output); | ||
$status = pclose($handler); | ||
|
||
return [$status, $output]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,55 @@ | ||
<?php | ||
/** @var yii\web\View $this */ | ||
?> | ||
<div id="webshell"></div> | ||
/** @var $this yii\web\View */ | ||
/** @var $quitUrl string */ | ||
/** @var $greetings string */ | ||
use yii\helpers\Url; | ||
|
||
\samdark\webshell\WebshellAsset::register($this); | ||
|
||
$endpoint = Url::toRoute(['default/rpc']); | ||
|
||
$this->title = $greetings; | ||
|
||
<?php | ||
$this->registerJs( | ||
<<<JS | ||
jQuery(function($, undefined) { | ||
$('#webshell').terminal(function(command, term) { | ||
if (command !== '') { | ||
var result = window.eval(command); | ||
if (result != undefined) { | ||
term.echo(String(result)); | ||
jQuery(function($) { | ||
$('#webshell').terminal( | ||
function(command, term) { | ||
if (command.indexOf('yii') === 0 || command.indexOf('yii') === 3) { | ||
$.jrpc('{$endpoint}', 'yii', [command.replace(/^yii ?/, '')], function(json) { | ||
term.echo(json.result); | ||
}); | ||
} else if (command === 'help') { | ||
term.echo('Available commands are:'); | ||
term.echo(''); | ||
term.echo("clear\tClear console"); | ||
term.echo('help\tThis help text'); | ||
term.echo('yii\tyii command'); | ||
term.echo('quit\tQuit web shell'); | ||
} else if (command === 'quit') { | ||
var exitUrl = '{$quitUrl}'; | ||
if (exitUrl) { | ||
term.echo('Bye!'); | ||
location.replace(exitUrl); | ||
} else { | ||
term.echo('There is no exit.'); | ||
} | ||
} else { | ||
term.echo('Unknown command.'); | ||
} | ||
}, | ||
{ | ||
greetings: '$greetings', | ||
name: 'yii2-webshell', | ||
prompt: '$ ' | ||
} | ||
}, { | ||
greetings: 'Javascript Interpreter', | ||
name: 'js_demo', | ||
height: 200, | ||
width: 450, | ||
prompt: 'js> '}); | ||
); | ||
$('html').on('keydown', function(){ | ||
$('#webshell').click(); | ||
}); | ||
}); | ||
JS | ||
); | ||
?> | ||
|
||
<div id="webshell"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,23 @@ | ||
<?php | ||
/** @var $this yii\web\View */ | ||
/** @var $content string */ | ||
use yii\helpers\Html; | ||
?> | ||
<?php $this->beginPage() ?> | ||
<!doctype html> | ||
<html> | ||
<html lang="<?= Yii::$app->language ?>"> | ||
<head> | ||
<meta charset="<?php echo \Yii::$app->charset?>"> | ||
<title><?php echo $this->pageTitle?></title> | ||
<meta charset="<?= Yii::$app->charset ?>"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<?= Html::csrfMetaTags() ?> | ||
<title><?= Html::encode($this->title) ?></title> | ||
<?php $this->head() ?> | ||
</head> | ||
<body> | ||
<?= $content?> | ||
<?php $this->beginBody() ?> | ||
<?= $content?> | ||
<?php $this->endBody() ?> | ||
</body> | ||
</html> | ||
</html> | ||
<?php $this->endPage() ?> | ||
|