Автоматический поиск уязвимостей в PHP коде. Часть 1

Discussion in 'Песочница' started by Y-E-S, 13 Sep 2010.

  1. Y-E-S

    Y-E-S New Member

    Joined:
    12 Aug 2009
    Messages:
    0
    Likes Received:
    3
    Reputations:
    0
    Доброго времени суток!

    Это первая статья из трех частей, которая посвящена базовым принцыпам автоматического поиска XSS уязвимостей в PHP коде.

    Опишем суть проблемы.
    Имеется некоторый PHP файл index.php, который потенциально уязвим. Начнем с простого
    PHP:
    <?php
       $bar 
    $foo;
       echo 
    "Test variable:" $bar;
    ?>
    Если в настройках указано register_globals = on, то переменная $bar открывает пасивную XSS уязвимость.
    Это можно определить просто передав в нее некотрую последовательность символов,
    таких как '"<> которые являются спец символами языка HTML и должны быть экранированны.

    Таким образом изначальный код приведем к такому виду
    PHP:
    <?php
       $foo 
    '@@@ name=foo template=\'"<> @@@';
       
    $bar '@@@ name=bar template=\'"<> @@@';
       
    $bar $foo;
       echo 
    "Test variable:" $bar
    ?>
    Мы выполнили поиск всех переменных и вставили их в начало скрипта.
    Переменные все инициализированны текстовой строкой которая содержет в себе:
    1. название самой переменной
    2. и список уязвимых символов.

    Результатом выполнения скрипта будет вывод:
    Code:
    Test variable: @@@ name=foo template='"<> @@@
    Отстается выполнить парсинг вывода, его можно сделать например так:
    PHP:
    // Предполагается, что $dump содержит 
    // текстовый вывод работы предыдущего скрипта
    preg_match_all('/@@@(.*?)@@@/s'$dump$matches);
    for(
    $i=0;$i<count($matches[0]);$i++){
                
      
    $attrs = array();
      
    $pairs explode(' '$matches[1][$i]);
      foreach(
    $pairs as $pair){
        if(!
    trim($pair))
          continue;
        
    preg_match('/(.*?)=(.*)/s'$pair$match);
        list(
    $null$key$value) = $match;
        
    $key trim($key);
        
    $value trim($value);
        
    $attrs[$key] = $value;
      }
      if(
    $attrs['template'] == '\'"<>'{
        
    // Если вывод переменной равен изначальному шаблону, то найдена уязвимость
        
    echo $attrs['name'] . '<br/>';
      }
    }
         
    В результате автоматически найдена пасивная уязвимость, которая заключается в передаче переменной $foo любого вредоносного кода:

    Code:
    index.php?foo=<script>alert('Hello from hole')</script>
    Возможна ситуация, что экранируется часть символов, например \'\"<>
    тогда подобное сравнение не будет подходить и нужно сравнивать посимвольно.

    На этом пока всё, следующие статьи посвещу тому как можно обходить все ветвления программы,
    а не идти по одной из веток if else операторов. О том как раскрывать циклы...

    Пару дней назад нашей командой был открыт сервис поиска уязвимостей /thread229263.html
     
    #1 Y-E-S, 13 Sep 2010
    Last edited: 13 Sep 2010
    2 people like this.
  2. phpdreamer

    phpdreamer Member

    Joined:
    26 Jul 2009
    Messages:
    522
    Likes Received:
    86
    Reputations:
    19
    или просто отключить register_globals и юзать htmlspecialchars
    xD
     
  3. Y-E-S

    Y-E-S New Member

    Joined:
    12 Aug 2009
    Messages:
    0
    Likes Received:
    3
    Reputations:
    0
    Я старался описать саму идею, её небольшие модификации позволяют находить так-же SQL и PHP иньекции.
     
  4. HIMIKAT

    HIMIKAT Elder - Старейшина

    Joined:
    12 Jan 2007
    Messages:
    2,707
    Likes Received:
    581
    Reputations:
    403
    Сам написал или с какой книги позаимствовал?
     
  5. phpdreamer

    phpdreamer Member

    Joined:
    26 Jul 2009
    Messages:
    522
    Likes Received:
    86
    Reputations:
    19
    со скулями посложнее будет))

    Идея по доработке принципа:
    собирать имена переменных GET и POST, но работать со скриптом не добавляя к нему свой код, а через curl.

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

    Например, регулярное выражение для проверки поля
    if(preg_match('#[a-z0-9]{8,15}#uis' ...
    Такие вещи трудно найти парсером кода...
    * безопасное выражение '#^[a-z0-9]{8,15}$#uis'
     
    #5 phpdreamer, 13 Sep 2010
    Last edited: 13 Sep 2010
  6. Y-E-S

    Y-E-S New Member

    Joined:
    12 Aug 2009
    Messages:
    0
    Likes Received:
    3
    Reputations:
    0
    В основном использовал статьи по формальным грамматикам и всяким лексическим анализаторам. Эта работа мне послужала дипломом :)
    В ближайшее время планирую протестировать большинство известных скриптов интернет магазинов и CMS, расскажу что из этого получилось.
     
  7. Y-E-S

    Y-E-S New Member

    Joined:
    12 Aug 2009
    Messages:
    0
    Likes Received:
    3
    Reputations:
    0
    Если после проверки логина предпологается вывод его по типу
    Code:
    Привет %username%
    или запись в базу, то по сути происходит следующее

    1. Передача параметра ?login=<...> на обработку скрипту

    2. Проверка и фильтрация логина какими угодно способами

    3. В итоге происходит вывод этого логина на экран либо запись переменной логина в базу.

    И на сколько б не был сложный и запутанный 2й этап, если в вывод попадает неэкранированная переменная то уязвимость обнаружена.
     
  8. Y-E-S

    Y-E-S New Member

    Joined:
    12 Aug 2009
    Messages:
    0
    Likes Received:
    3
    Reputations:
    0
    1 person likes this.
  9. HIMIKAT

    HIMIKAT Elder - Старейшина

    Joined:
    12 Jan 2007
    Messages:
    2,707
    Likes Received:
    581
    Reputations:
    403
    Видос это несомненно гуд, так сказать сначала почитать теорию, а потом наглядно посмотреть.