Цель программы - учебно-демонстрационная, пример работы с Internet через
API. Проверялась на: Win2000 (Delphi 5, MSVC), Debian Linux. База данных уязвимых скриптов не прилагается. Ее можно найти в интернете (например, на сайте группы Nerf)

1 Параметры запуска
2 Описание алгоритма
2.1 Обработка параметров и инициализация
2.2 Разрешение имен
2.3 Главный цикл
2.4 Алгоритм работы функции geturl
3 Детали реализации для языков/платформ
3.1 MSVC и GNU C
3.2 Delphi

1. Параметры запуска.

После компиляции (в Windows) бинарный код имеет имя cgiscan.exe.
Есть два варианта запуска: с одним параметром - без использования прокси-сервера
и с тремя параметрами - с использованием прокси.
Без прокси:
cgiscan.exe <имя сервера>
Например: cgiscan.exe www.void.ru
С использованием прокси-сервера:
cgiscan.exe <имя сервера> <прокси> <порт прокси>

В качестве имени сервера и названия прокси можно использовать как имя, так и
IP-адрес.

2. Описание алгоритма.

Задача сканера CGI - проверить сервер на наличие потенциально уязвимых
скриптов, которые могут быть использованы для проникновения в систему.
Программой используется база данных скриптов, хранящаяся в файле cgilist.txt 

2.1. Обработка параметров и инициализация

Для приложений под Windows выполняется инициализация подсистемы работы с сетью
WSA: WSAStartup. Требуемая версия - 1.1

Проверяется кол-во параметров. Если их не 1 и не 3, то выводится сообщение о
копирайтах, требуемых параметрах, пример использования, и программа завешает
работу.

Далее программа пытается открыть файл cgilist.txt - базу данных уязвимых скритов.
При файла отсутствии выдается ошибка.

2.2. Разрешение имен.
Далее происходит определение IP-адреса сервера, через который будет
производиться сканирование (прокси, если используется, иначе - адрес сайта).
Сначала проверяется, является ли строка IP-адресом, если нет - то программа
пытается определить адрес, соответствующий этой строке. Если ни то, ни другое
не удается, программа выдает сообщение и завершает работу. 

2.3. Если все еще не случилось никакой ошибки :), то программа читает из файла
имена скриптов и вызывает функцию geturl. Если функция вернула 
положительный результат, то выводится сообщение "найден" <имя скрипта>.

2.4. geturl
Функция geturl запрашивает у сервера (напрямую или через прокси) заданный
URL, и проверяет, есть ли в ответе сервера (первые 20 символов) подстоки 200 или
500. Подразумевается, что 200 - код ответа HTTP 200 (OK), а 500 - код ответа
HTTP 500 (внутренняя ошибка сервера), и наличие одной из этих двух подстрок
в ответе сервера свидетельствует о наличие на сервере этого скрипта.

Сначала создается сокет типа SOCK_STREAM (TCP), далее производится подсоединение
к серверу. При прямом соединении выполняется запрос HTTP/1.1 (почему-то IIS5
с установленным прокси иногда некорректно воспринимает HTTP версии 1.0).
------------
HEAD /scriptname HTTP/1.1
Host: localhost
------------
При соединении через прокси выполняется запрос HTTP версии 1.0 (он синтаксически
проще):

HEAD http://servername/scriptname HTTP/1.0

Далее читаются 20 (или меньше, если сервер вернул меньше) символов ответа
сервера, и в них ищутся подстроки 200 или 500.

3. Детали реализации.

Отличия реализации на MSVC и GNU C незначительны, сначала была написана
MSVC-версия (консольное приложение), а затем из нее сделали Unix-версию.
Пришлось исправить лишь несколько строк: список include-файлов, убрать
инициализацию WSA, заменить closesocket на close. В остальном тексты идентичны.

Версия на Delphi написана "с нуля", но алгоритм и названия процедур
по возможности сохранены.

3.1. MSVC и GNU C.
Список параметров запуска программы получается через аргументы функции
main. argc - количество параметров+1, argv - массив указателей на строки-параметры.

Приложение - консольное, вывод производится функцией printf, чтение из файлов
- fopen и fgets(форматированный ввод, читает до пробела или символа конца
строки). Имя файла со списком скриптов находится в глобальной переменной
cgilist. Для хранения адреса сервера используется глобальная переменная proxy_addr
типа sockaddr_in - структура, напрямую используемая функцией connect, включающая
в себя и адрес, и порт.

При работе через прокси содержит порт и адрес прокси,
адрес порта берется из параметра функцией atoi (преобразование строки в число).
То, что параметр - это именно число - не проверяется, т.е. при некорректном
вводе номером порта окажется какое-то число, и ошибка произойдет уже при
соединении.

При прямом подключении номером порта считается 80.

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

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

Разница в реализации: Аргументы получаются через функцию ParamStr, количество
аргументов - через ParamCount, причем значение "количества агрементов"
в Delphi на 1 меньше, чем в Си. Аргумент с номером 0 содержит полный путь
к программе, что некрасиво выглядит в подсказке по использованию. Обрезать
его программно поленился, вместо этого просто "забил" имя cgiscan.exe в текст
программы.

Имена скриптов из файла читаются как строки, а не как слова. Проверка на конец
файла установлена не перед функцией geturl, а после, почему-то Delphi
устанавливает признак конца файла после прочтения последней строки, а не
после попытки чтения "лишней".

Исходники: cgiscan.zip

Оставить мнение