Мой баг дня (записки тестировщика)
243 subscribers
169 photos
23 videos
11 files
126 links
Precondition:
Repro steps:
1. ...
2. ...
3. ...
Expected: good
Actual: bad

Связь: @MyachinDA
Download Telegram
Мой баг дня (записки тестировщика)
Дополнительно — скоро запишу видос про уязвимость в Android, которую исправили. Сейчас период релизов, просто не до этого. Но я не забыл :) И да, денег всё ещё не заплатили. Висят в статусе PENDING.
Обещанная статья про уязвимость в Android, которую нашла наша команда. Напомню, что сводилась она к тому, что WhatsApp получал доступ к микрофону так, что Android этого не видел и никак не сигнализировал: не сохранялось в истории доступа, не появлялся соответствующий индикатор.

Текст один и тот же, выбирайте, в каком форматировании вам удобнее читать. Ну и первая весит поменьше. Ссылка на PoC в статье есть.

https://text.tchncs.de/umnik/obkhod-rezhima-mode_ignored-v-app-op

https://myachinqa.blogspot.com/2023/03/modeignored-app-op.html
Если вы хотите сообщить о проблеме в "Мой Офис" (входит в реестр отечественного ПО), то у вас затребуют персданные. Читаем соглашение о них:

2. Цели сбора и обработки персональных данных

- направление подписчикам и пользователям Сайтов сообщений информационного и рекламного характера посредством электронных почтовых сообщений и смс-сообщений с соблюдением требований действующего законодательства Российской Федерации;

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

Вообще удивительное дело. Наши разработчики ПО выполняют 152 ФЗ спустя рукава и используя максимум лазеек, чтобы положить на него болт. При этом исполнять требования GDPR бегут, роняя тапки. Выглядит так, что производителям ПО положить хрен на сограждан, но вот эльфы из Европы достойны самого лучшего
👍8
Кто-то, простите не помню кто, но точно был подписан, спрашивал про стажировку. У меня её нет, но вот мои бывшие коллеги делают: https://safeboard.kaspersky.ru/ Оплачиваемая!

К сожалению, только для студентов. Посмотрите сами или передайте знакомым.

И нет, это не реклама. :) Просто у меня, что называется, перед глазами опыт, когда студент из сейфборда стал манагером в ЛК. Привет тебе, кстати, если ты это читаешь.
👍8
https://music.yandex.ru/album/18910064/track/110185672

- У нас была платёжная форма, на которую было написано 9 тыс. строк тестов и ни один из них не проверял чего-то нужного
- Как так?
- Это тесты, ну там, на уровне, где вообще всё замокано. И условие такое: if (true) { return true }. И так 9 тысяч строк кода
👍3
СЯУ, что клиенты ДОЛЖНЫ (MUST) сваливать коды возврата в их дженерик варианты, когда не знают реального кода. HTTP коды, в смысле.

Суть в том, что списки кодов возврата расширяемы (ну, это не новость) и, если клиент не знает конкретного кода, он MUST обработать код как x00. То есть 204 → 200, 409 → 400 и прочее.

И тут у меня флешбек из прошлого, когда в антивирусе был switch на коды возврата и dafault значение было "перезапросить снова". И как антивирусы стали класть сервак на лопатки, когда тот отвечал кодом, на который не было case.
Ухудшилась стабильность автотестов на Espresso. Стал разбираться, в чём дело.

У меня есть тест, который следит за таймером на экране. Так как я стараюсь не трогать код самого приложения (лезть в код, который написан много лет назад - себе дороже), то использовал банальный способ: делаю ViewAssertion на нужный мне текст и, если получаю исключение о несовпадении текста, повторяю попытку. Ну а что поделать, приходится так.

Это работало прекрасно несколько лет. И недавно сломалось. Каждый раз ассершен не обнаруживает нужный счётчик, пролетает мимо. Стал отлаживаться и увидел, что эспрессо просто замирает на 5 секунд после каждого опроса!

Оказалось, что поведение Espresso изменили в 3.5.0: https://developer.android.com/jetpack/androidx/releases/test#espresso-3.5.0

Espresso's DefaultFailureHandler now saves a screenshot on test failures to TestStorage

И вот если эспрессо не смог снять скриншот, он замирает на 5 секунд. Но хотя бы сообщает об этом в лог: java.util.concurrent.TimeoutException: Waited 5 seconds (plus 1063571 nanoseconds delay) for androidx.concurrent.futures.ResolvableFuture

Эта проблема не только у меня, вот другой человек жалуется: https://github.com/android/android-test/issues/1584

Гугл сжалился и сделал "фикс" https://github.com/android/android-test/commit/44b2b456d3052f6114ac3e3b5d2676e6f8885e37 На самом деле не фикс, а просто теперь я обязан создать свой FailureHandler и выставить отключение снятия скриншота.

Фикс доступен только в альфе: https://developer.android.com/jetpack/androidx/releases/test#espresso-3.6.0-alpha01: Allow customizing espresso's default failure handler to disable screenshots on failures

Сделал костыль, где считываю текст с вьюхи (напомню, что в Эспрессо нет метода для считывания текста, этот код тоже нужно написать самому) и уже в считанном тексте регуляркой беру число в счётчике и проверяю его.

Вот зачем было ломать то, что работало годами. Внесли непоправимое улучшение, что называется. Надеюсь на релизе 3.6 исправят всё же само поведение либы, без нужды свой хендлер определять. Я просто не люблю переопределять стандартные поведения, т.к. в будущем в стандартном поведении может появиться полезность, которая придёт на халяву, а я не узнаю об этом, ведь не слежу за чейджлогом каждой сраной альфы.
👍5
Текст будет в комментарии
    /**
* Retrieves default launcher package name
*
* @return package name of the default launcher
*/
public String getLauncherPackageName() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
PackageManager pm = mInstrumentation.getContext().getPackageManager();
ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.activityInfo.packageName;
}


UiDevice из uiautomator от Google утверждает, что лончером у меня является com.android.settings, а не com.android.launcher3. Лан, напишу свою определялку.
Мой баг дня (записки тестировщика)
/** * Retrieves default launcher package name * * @return package name of the default launcher */ public String getLauncherPackageName() { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Inten…
Поисследовал поведение и похоже дело такое:
- https://issuetracker.google.com/issues/178965163
- воспроизводится на Android 11 и новее. Стреляет из-за фичи видимости пакетов. Ну знаете, нужно в манифесе прописать <queries> либо дать разрешение на получение всех приложений
- настройки действительно являются лаунчером. Но когда пользователь таки разблокирует устройство, они передают управление лаунчеру по умолчанию

Решений этой проблемы два с половиной варианта:
1. Написать свой детект лаунчера. Я не проверял, но чел утверждает, что работает: https://github.com/adil-hussain-84/UiAutomatorExperiments. Это не мой путь. Выше я уже писал, что не хочу подменять поведение фреймворков без крайней нужды
2. В Манифесте включить ожидаемые ланчеры в видимость. В моём случае:
    <queries>
<package android:name="com.android.launcher3"/>
</queries>

2.1. В Манифесте объявить разрешение android.permission.QUERY_ALL_PACKAGES, которое позволит видеть все приложения. Возможно вам будет удобнее этот вариант
Появилась задачка сделать автотест Android параметризируемым. Если быть точным, то нужно уметь читать экраны Google Play Store сотни разных приложений. Можно сделать сотни тестов с именами пакетов, но лучше сделать метод @Test всего один, но чтобы он мог принимать пакеты.

Как вы решали подобные задачи? Что говорит Гугл? Я просто и не искал, т.к. уже делал подобное и просто повторил то, что делал давно.

Суть такова:

    @Test
fun demoMethod() {
val arguments = InstrumentationRegistry.getArguments()
Log.d("MyTestPackage", "first=${arguments.getString("first")}\n" +
"second=${arguments.getString("second")}\n" +
"third=${arguments.getString("third")}")


Запускается так: adb shell am instrument -w -e first "вот\ это\ я\ понимаю\ строка" -e second 100500 -e third 3.1415 -e class xyz.myachin.letsappsbeupdated.playstore.PlayStoreUpdateApps#updatePackage xyz.myachin.letsappsbeupdated.test/androidx.test.runner.AndroidJUnitRunner

Ну и получаем

2023-05-30 21:23:14.185 28039-28058 MyTestPackage           xyz.myachin.letsappsbeupdated        D  first=вот это я понимаю строка
second=100500
third=3.1415


везде getString(), потому что аргументы приходят строкой. Можно написать обёртку с приведением к нужным типам, но это оверхед.
This media is not supported in your browser
VIEW IN TELEGRAM
Подписался, чтобы оставить единственный комментарий. Всё, отписаться больше нельзя. ВК это сделали или ещё со времён Яндекса баг - не знаю: воспользовался дзеном впервые в жизни. И сразу вляпался
Написал инструмент для вытягивания приложений из разных сторов на Android. В случае вот такого сообщения бросаю себе исключение "у нас нет аусвайса для этого пакета"

xyz.myachin.letsappsbeupdated.exceptions.StoreException: We have not an ausweis for com.bmw.ConnectedRide.na

Потому что так себя и чувствую
👍4
Мой баг дня (записки тестировщика)
- Вот вам багрепорт - А где паспорт и мазок?
Только что пришёл ответ. Проблема исправлена, обновитесь на последнюю версию. Ну, всё хорошо, что хорошо заканчивается.
Задача утилиты fastboot в Android SDK - прошивать образы на телефон. Google сломал это: https://issuetracker.google.com/issues/284327750 при попытке зашить образ 34-ой версией фастбута получаем fastboot: error: ANDROID_PRODUCT_OUT not set. ОС не важна.

Варианты обхода проблемы до выпуска исправления:
1. Откатиться на 33
2. export ANDROID_PRODUCT_OUT=$ANDROID_HOME/platform-tools перед прошивкой. Переменная окружения ANDROID_HOME задана, надеюсь?

У утилиты одна задача. И ту сломали. Google можно сделать слоган: "ломаем то, что не закрыли"
👍3
Коллеги-тестировщики, важный вопрос. Есть ли у вас какая-то готовый список, который можно взять за основу, чтобы правильно ранжировать тестировщиков по навыкам, от джуна до бесконечности?

Или, тоже нормальный вариант, скажите, что, на ваш взгляд, должен уметь тестировщик на том или ином грейде.
Строго говоря, это не баг, но мне не нравится это поведение. Приложения с разрешением ТОЛЬКО READ_CALL_LOG могут частично получить также и телефонную книгу, хоть и окольным путём.

В чём, собственно, суть. Вот есть разрешение для чтения истории звонков: https://developer.android.com/reference/android/Manifest.permission#READ_CALL_LOG И оно предназначено именно для истории звонков. Ничего не сказано о том, что можно получить доступ к записной книге. И, формально, доступа действительно не будет.

Таким образом я ожидал, что буду видеть только информацию о звонках, без возможности понять, чей именно этот входящий или исходящий номер. Ну номер и номер.

Однако самой БД в истории звонков есть вот такое поле: https://developer.android.com/reference/android/provider/CallLog.Calls#CACHED_NAME. И здесь реально написаны имена из записной книги. То есть доступа к контактам у меня нет, но имя и номер телефона я связать могу, т.к. вижу и то, и другое.

При чём это звонилка МОЖЕТ заполнять это поле для кеширования. А может и не заполнять, но тогда ей придётся постоянно дёргать ещё и записную книгу, чтобы отобразить имя вместо телефона. Вот Google Dialer из Pixel телефонов это поле заполняет.

В итоге с одной стороны это ускоряет отрисовку истории звонков, т.к. не требуется обращаться к ещё одной базе (к контактам), а с другой — любое приложение БЕЗ доступа к записной книге, но с доступом к истории звонков, хотя бы частично, но может восстановить связь "номер" <-> "имя".

Вроде звучит не так, чтобы страшно. Казалось бы, если есть доступ к истории звонков, то уже плохо. Но с другой стороны:
1. Это поведение не ожидается. Пользователь одобрил только историю звонков, но не доступ к контактам
2. Шпионское приложение может сидеть и ждать нужного звонка, не создавая никакой сетевой активности, чтобы лишний раз себя не выдавать. А когда "Вася Иванов" таки появится вдруг в логе звонков, сразу отправить этот номер телефона кому следует и дальше уже пофигу, пусть шпиона обнаруживают — своё дело он сделал
👍7
Мой баг дня (записки тестировщика)
Связался со мной другой сотрудник фирмы и, кажется, дело пошло. Базовая оценка — всего 4.2, с чем я, в общем-то, согласен. Потому что, чисто для справки, почти вся зараза будет попадать под эту оценку. Так как почти всё требует, чтобы пользователь её запустил…
Итак, в начале августа мне написали, что проблема исправлена и фикс уже выложен на сайте. Стоило с февраля отнекиваться и прикидываться, что проблемы нет? CVE, кстати, не оформляли :) То есть в статистике обнаруженных уязвимостей продукта эта фигурировать не будет. Типа, не было её никогда.

И забавно вот ещё что. В своём оригинальном письме я указывал, что эта же проблема есть у KeePass и KeePassXC. Но у них есть инструменты уменьшения урона (например, указание ключевых файлов). К тому же у них самих на сайтах написано, что такое поведение в целом ожидается. И потому я не стал писать авторам keepass о проблеме, ведь они информировали о ней прям на сайте. ОДНАКО. Не смотря на то, что тот же KeePass имеет механизм снижения угрозы и вообще предупреждает, что угроза в целом существует, потому что это дотнет, он ВСЁ РАВНО ПРИНЯЛ РЕПОРТ ОБ ЭТОМ от другого человека: https://sourceforge.net/p/keepass/discussion/329220/thread/f3438e6283/

Как видите, репорт в keepass был в мае, тогда как я не стал репортить (оказалось, что зря) в феврале. Описание угрозы соотвествует моему — восстановление пароля из дампа. И эту уязвимость оценили на 7.5: https://nvd.nist.gov/vuln/detail/CVE-2023-32784 Тогда как мой репорт Касперскому (все уже поняли, что речь про Касперский Пассворд Менеджер) оценили на 4.2, т.к. доступ к дампу требует админских прав.

Одинаковые уязвимости в СПО и закрытом коммерческом ПО, вызванные одной проблемой - дотнетом. Но подходы разные. У СПО:
- репорт первого мая
- разработчик 2-го мая отписывается в стиле "понял-принял, ща займусь"
- 7-го мая разработчик предоставляет сборку на проверку. Мало того, он объясняет, в чём проблема и какие действия он предпринял
- 8-го мая репортер подтверждает, что проблема устранена
- 9-го мая разработчик сообщает, что проблема будет устранена в ближайшем релизе в течение 2х месяцев (напоминаю про 3 месяца на устранение уязвимости - это норма)
- 3-го июня разработчик публикует релиз с устранением этой и двух других уязвимостей.

Итого:
- Признание проблемы: 1 день
- Публикация прототипа фикса для оценки ресёчером: 7 дней
- Публикация исправления: ~36 дней

А теперь платное ПО с закрытым исходным кодом:
- Репорт: 3-е февраля. При этом в репорте было приложено видео, а воспроизводилось не махинациями с мемори дампом, а просто утилитой арт мани. То есть для воспроизведения нужно просто мышкой потыкать
- Понял-принял: 6 февраля
- Мой вопрос: "есть ли продвижение?": 14 февраля
- Ответ, что не удалось воспроизвести: 15 февраля. Там же написано, что похожее исправили в 2019. То, что есть видео и это заведомо последняя сборка роли не сыграли
- Моё охреневание от ответа: 15 февраля
- "Попробуем воспроизвести повторно": 17 февраля
- "Дмитрий, привет, воспроизвели, даём оценку 4.2" https://www.first.org/cvss/calculator/3.1#CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N : 15 марта
- Небольшая переписка, где я сказал, что ладно, 4.2 так 4.2. Главное исправьте
- "Будем держать вас в курсе": 28 марта
- "Спасибо за ожидание. Проблема устранена. Сборка доступна для скачивания, апдейт летит к клиентам": 3 августа

Я даже считать дни не буду, вы сами даты видите.

Отдельно меня позабавил вопрос в письме, буду ли я публиковать информацию по этой проблеме. Я честно не знаю, какое это отношение имеет к устранению или не устранению уязвимости и спросил в ответ, а на что это влияет? Спросил тогда же, 3-го августа. Сейчас 18 и мне не ответили. Ну, ждать ещё полгода на ответ не хочется, потому пишу тут. Здесь меньше 200 человек, так что особо ситуация не разлетится. Но выводы делать нужно.

В следующем сообщении прицеплю видео с воспроизведением. Сможете проверить сами, понадобится только Шинда и АртМани. Также в письме от 3-го августа указано, что при использовании буфера обмена очистка произойдёт через 2 минуты. Для сравнения, у KeePassXC:
- 10 секунд на буфер обмена
- есть механизм вообще не использовать буфер обмена. В этом сценарии кипасс будет посылать события ввода с клавиатуры, так что читать буфер обмена будет бесполезно - там нет пароля
👍6
Media is too big
VIEW IN TELEGRAM
Прошу прощения за затянутость видео. Немного нервничал и иногда делал лишние действия. Суть в том, что показываю, что пароль не уходит после сворачивания и даже после блокировки базы. А в случае смены пароля переиспользуются те же участки памяти, что позволило в реальном времени обнаружить изменение мастер пароля. Всё же как хотите, а .Net в целом не подходит для такого https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md Но вот автор KeePass показал, что даже проблемы .Net можно обойти. Интересно, Касперские выкатили фикс после KeePass, который тоже на дотнете. Совпадение?
👍6
https://packages.ntop.org/ видимо очень важные изменения
👍4