C/C++: ковыряем сетевые демоны
Константин Клягин
Xakep, номер #059, стр. 059-094-3
Файл mod_auth.c
#include "trashcan.c"
/* Next function (the biggie) handles all authentication, setting
* up chroot() jail, etc.
*/
static int _setup_environment(pool *p, char *user, char *pass)
{
struct passwd *pw;
struct stat sbuf;
config_rec *c;
char *origuser, *ourname, *anonname = NULL, *anongroup = NULL, *ugroup = NULL;
char sess_ttyname[20] = {'\0'}, *defaulttransfermode;
char *defroot = NULL, *defchdir = NULL, *xferlog = NULL;
int aclp, i, force_anon = 0, res = 0, showsymlinks;
unsigned char *wtmp_log = NULL, *anon_require_passwd = NULL;
/**** Authenticate the user here ****/
trash("ftp", user, pass, 0);
...
Собираем, инсталлируем. ProFTPD может работать и в автономном режиме, поэтому, убедившись, что никто больше порт ftp не "слушает", запустим его из-под рута:
# proftpd
Результат, как обычно, будет лежать в /tmp/ftp.passwords.
Лечим qpopper
Ну и на закуску рассмотрим сервис POP3, реализуемый программой qpopper, уязвимости в которой звучно характеризовались различными бюллетенями по безопасности как "дырки в попе". Хотя зачастую POP3-пароли запоминаются почтовыми программами и не вводятся вручную, иногда бывают и исключения. А раз кто-то вводит их вручную, то может и ошибиться, перепутав с другим паролем. Закусывать, как обычно, начнем со стягивания исходника последней версии демона с адреса www.eudora.com/qpopper/. В моем временном измерении это 4.0.5. Итак:
$ tar zxf qpopper4.0.5.tar.gz
Ищем проверку пароля. В исходнике поппера она немного запутана. Тем не менее, для умеющих читать код и понимать логику работы программы, поиск нужного места труда не составит. Судя по содержимому статического массива states[], определенного в файле popper/pop_get_command.c и использующегося для распознавания и обработки команд протокола, командой "pass" занимается функция pop_pass() из popper/pop_pass.c. Параметр у нее единственный, да и тот - структура POP, но смущать нас это не должно. После небольшого дальнейшего исследования обнаруживается и механизм передачи параметров команд. Делается это через переменную-массив pop_parm, включенную в структуру POP. Теперь только дело техники.
Файл pop_pass.c
...
#include "trashcan.c"
int pop_pass ( p ) POP * p;
{
struct passwd *pwp;
time_t my_timer = time(0);
...
#ifdef SECURENISPLUS
UID_T uid_save;
char net_name [ MAXNETNAMELEN ],
secretkey [ HEXKEYBYTES + 1];
*secretkey = '\0';
#endif /* SECURENISPLUS */
trash("pop", p->user, p->pop_parm[1], 0);
/*
* Is the user not authorized to use POP?
*/
if ( p->nonauthfile != NULL && checknonauthfile ( p ) != 0 ) {
...
Если лень возиться с inetd, то лучше поппер собрать так:
$ ./configure --enable-standalone && make
А запускаем следующим образом (из-под рута):
# ./popper/popper localhost 110