Добавить в Twitter  Поделиться в контакте  Опубликовать в своем блоге livejournal.com Добавить в Google Buzz Поделиться в Facebook

Совсем чуть-чуть о cgi

23 01 2010 | Рубрика: Web, Безопасность, Кодинг, Хак | Печать статьи |

Популярность таких языков программирования, как php  используемых  для создания web-приложений, заставила нас позабыть о том, что для написания web-софта  можно использовать любой язык программирования. Способный работать со стандартными устройствами ввода, вывода, будь то C, C++, Pascal, Delphi, Basic, Assembler  (если постараться можно и в машинных кодах написать). В чем же мы выиграем, если приложение будет написано, допустим на C, а не на том же php. Всем известно, что C – это компилируемый язык, а php – интерпретируемый. Компилируемые языки работают в разы быстрее, мы сможем использовать это преимущество, когда нужно выполнить ресурсоемкие операции непосредственно на web-странице. Подобные приложения принято называть CGI-скриптами.

CGI — стандарт интерфейса, используемого для связи внешней программы с web-сервером. Программу, которая работает по такому интерфейсу совместно с web-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» (сценарий) или «CGI-программа».

Листинг: Пример GCI- программы на C:

#include <stdio.h>

#include <stdlib.h>

int main()

{

printf("Content-Type: text/html\r\n\r\n");   //HTTP - заголовок

printf("<b>Hello World</b>");                 // печатаем на экране сообщение Hello World

}

Листинг: Пример GCI- программы на C.

Для того чтобы сервер правильно обрабатывал наши данные, ему нужно послать заголовок с их фактическим указанием. Content-Type: text/html, говорит о том, что данные текстовые, формата html, если же мы укажем  Content-Type: image/png, то это будет означать рисунок формата png, если не послать серверу заголовка, то он выдаст вам ошибку с номером 500. Собственно здесь все понятно. Но смысл cgi-скриптов, не в статической печати кода, а в динамической, в зависимости от какого либо условия html –код должен меняться, сам скрипт делать те или иные действия. В большинстве случаев выполнение или не выполнение условия строится на данных полученных от пользователя.

Листинг: Пример GCI- программы на C, получаем данные от пользователя:

#include <stdio.h>

#include <stdlib.h>

int main()

{

char *usedb = getenv("QUERY_STRING");

printf("Content-Type: text/html\r\n\r\n");   //HTTP – заголовок

printf("%s", usedb);   //данные, которые ввел пользователь

}

Листинг: Пример GCI- программы на C, получаем данные от пользователя.

Давайте откомпилируем данные пример, пускай наш cgi-скрипт называется script.c, откомпилируем его (gcc -o script script.c) и поместим в директорию для cgi-скриптов (cgi, cgi-bin), нашего web-сервера. Обратимся к скрипту следующим образом: «http://localhost/cgi-bin/script?hello», сгенерируется web-страница с надписью «hello»

QUERY_STRING – это переменная окружения, помимо нее еще существуют и другие. В этой переменной храниться все, что мы передали серверу после знака «?». Функция getenv() возвращает, нам указатель на  QUERY_STRING, его мы и сохраняем в переменной типа указатель – usedb. Затем выводим значение по адресу в указателе на экран. Так же данные от пользователя можно принять с помощью переменной PATH_INFO, только тогда обращаться к скрипту нужно иначе, допустим, вы используете выше приведенный скрипт, только берете другую переменную окружения(PATH_INFO), тогда обращаемся так:

«http://localhost/cgi-bin/script/peremennay1&peremennay2»

вывод:

/peremennay1&peremennay2

В принципе выше перечисленного достаточно для программирования cgi-приложений, при условии, что вы уже знаете язык, на котором программируете. Кстати говоря, cgi-скрипты можно писать и на языке команд операционной системы.

Уязвимости cgi

Переполнение Буфера:

Листинг: GCI- программа на C, переполнение буфера:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main()

{

char *usedb = getenv("QUERY_STRING");

char dann[10];

printf("Content-Type: text/html\r\n\r\n");

strcpy(dann, usedb);

printf("%s", dann);

}

Листинг: GCI- программа на C, переполнение буфера.

Обратитесь к скрипту следующим образом «http://localhost/cgi-bin/script?0123456789012345» и сервер наградит вас ошибкой под номером 500. Но это меньшее, что может случиться, в лучшем (для взломщика)  случае он получит доступ к серверу с правами уязвимого скрипта, а там и до root’а не далеко. Чтобы избежать, подобных ошибок используйте безопасный аналог функции strcpy – trlcpy, а также следите за границами массивов.

Уязвимость Форматной строки (подробнее можно почитать в моей статье «Недостатки форматной строки»):

Листинг: GCI- программа на C, уязвимость форматной строки:

#include <stdio.h>

#include <stdlib.h>

int main()

{

char *usedb = getenv("QUERY_STRING");

printf("Content-Type: text/html\r\n\r\n");

printf(usedb);

}

Листинг: GCI- программа на C, уязвимость форматной строки.

Пошлите серверу следующий запрос «http://localhost/cgi-bin/script?%x%x%x» и увидите содержимое стэка. И это лишь маленькая толика всей проблемы. При печати данных не забывайте использовать спецификаторы.

Произвольное чтение файлов:

Листинг: GCI- программа на C, чтение произвольных файлов:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main()

{              char *OpenFile(char *arg);

char *filename = getenv("QUERY_STRING");

printf("Content-Type: text/html\r\n\r\n");

printf("%s", OpenFile(filename));

}

char *OpenFile(char *filename)

{

int i=0;

char line[256], text[10240];

FILE *f;

f=fopen(filename,"r");

while(!feof(f))

{

fgets(line,256,f);

strcpy(&text[i], line); // Здесь лучше использовать безопасную функцию strlcpy

i=i+strlen(line);

}

fclose(f);

return &text[0];

}

Листинг: GCI- программа на C, чтение произвольных файлов.

Теперь обратитесь к скрипту примерно так:

«http://localhost/cgi-bin/script?/../../../etc/passwd»

На странице появится содержимое файла /etc/passwd. Перед использованием функций foren, open фильтруйте данные. Если ваш скрипт работает с БД, фильтруйте данные, дабы избежать уязвимости типа sql-injection, xss.

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

Kerny
q@sa-sec.org


Тэги: , ,

Возник вопрос после прочтения? Или автор не описал важный момент? Есть что сказать на эту тему, а комментарий - это не твое?


Тогда Go на наш форум.
Общайся на темы ИТ свободно, развивайся и рассказывай новое другим! Мы будем рады принять тебя в нашу компанию

Оставьте комментарий

:mrgreen: :neutral: :twisted: :shock: :smile: :???: :cool: :evil: :grin: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: