Статьи Введение в cgi-security

Discussion in 'Статьи' started by k00p3r, 9 Jun 2005.

  1. k00p3r

    k00p3r Banned

    Joined:
    31 May 2005
    Messages:
    430
    Likes Received:
    8
    Reputations:
    2
    Ну вот добрались мы до такой интересной темы как ошибки в cgi-скриптах и методы их обнаружения. Редкий сайт в наше время обходится без пары скриптов, а это значит, что хоть один из них может быть уязвим и даст нам полный доступ к серваку. Забудь про всякие /../../ сегодня я расскажу о более серьёзных вещах.

    Начнем пожалуй с такой приятной вещи как Нулевой байт aka Poison NULL byte. Насколько я слышал эту багу впервые нашли ребята из ukr-team. В чем же заключается этот баг. Допустим у нас есть скрипт открывающий некий файл.

    $database="$user_input.db";
    open(FILE "<$database");

    Этому скрипту передается значение user_input которое являет собой не что иное как название файла, а скрипт в свою очередь прикрепляет к названию .db и открывает файл. Например: user_input=file тогда скрипт откроет файл: file.db
    Но будет гораздо интереснее если мы передадим значение user_input=file%00
    Перл считает что $database="file\0.db", а потом попытается открыть $database. И что мы увидим в итоге? Он откроет файл "file" А что же случилось с расширением ".db"? Вот это самое интересное. Видишь ли перл принимает NUL-байты как часть значения какой-либо переменной. А С/С++ наоборот думает, что такой байт будет концом строки.
    Немного поискав вы найдете туеву хучу скриптов, которые к введенному пользователем значению прикрепляют ".html". То есть введя page.cgi?page=1 мы увидим страничку 1.html т.к. скрипт добавил к переданному ему значению расширение ".html". И ты думаешь, что этот скрипт показывает только html-странички. А вот и нет!
    Если вы сделаем так: page.cgi?page=page.cgi%00 то увидим исходный текст самого скрипта.
    Как же от этого защитится. Тут всё просто как компутер. Надо убрать все нулевые байты из строки, полученной скриптом в качестве аргумента:

    $insecure_data=~s/\0//g;

    Если ты читал W3C WWW Security FAQ то ты наверное видел список символов рекомендуемых к удалению из строк вводимых пользователем: & ; ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \ n \ r
    Самое интересное тут в том, что все забыли про бэкслеш ( \ )
    Поэтому в твоих скриптах на перле из всех переменных нужно убирать вот эти символы:

    s/([\&;\`'\\\|"*?~<>^(\)\[\]\{\}\$\n\r])/\\$1/g

    Почему это важно? Представь что твоему скрипту передали параметр: `rm -rf /` (с апострофами!)
    Скрипт прогонит это через свою подпрограмму проверки строки на недопустимые символы, и в конце строка примет вид:

    \`rm -rf /\`

    Теперь представим, что мы забыли обезвредить бэк-слэши. Скрипту передают вот такую строку:

    \`rm -rf/ \`

    твой скрипт делает из неё:

    \\`rm -rf / \\`

    тогда два бэкслеша обрубять друг друга, оставив апострофы нетронутымии. При особом желании можно будет снести всё подчистую.
    Вторая интересная возможность вытекает из попыток горе програмистов избавится от ошибки /../
    s/\.\.//g - эта строка убирает двойные точки, эффективно закрывая эту уязвимость. Тогда:

    /usr/../../etc/passwd станет /usr/etc/passwd

    Но теперь попробуем поиграться с бэкслешем, набираем строку:
    /usr/.\./.\./etc/passwd

    Эта строка отлично пройдет проверку на /../ и примет вид /usr/../../etc/passwd, чего мы и добивались!
    Защита: Если в скрипте используется ключ '-e' или есть указание на способ открытия файла (<$file), то всё это работать не будет 8(

    Ну и напоследок о такой всеми любимой палочке |
    Как наверняка многие знают, если к концу открываемого файла прилепить "|" то перл запустит этот файл вместо того, чтобы его открыть. Таким образом сделав:

    open(FILE, "/bin/ls")

    ты вдоволь насладишься кишками ls но сделав:

    open(FILE, /bin/ls|")

    ты увидишь листинг директории.
    Защита: Выкидываем символы: s/(\|)/\\$1/g

    Ну вот я и рассказал тебе немного о cgi-security. Конечно это не всё, но рассказать обо всех возможных дырах мне не хватит ни времени ни терпения.

    Автор: 1dt.w0lf