whysafe

whysafe

Разработчик. Делаю игры, сайты и ботов. Рассказываю, как всё ломается и как я это чиню — с кодом, скриншотами и болью.
Пикабушник
3096 рейтинг 3 подписчика 0 подписок 8 постов 2 в горячем
5

Приложению не дали ни одного разрешения, а оно всё равно забрало рабочую почту. Разбор дыры в Microsoft Authenticator⁠⁠

23 октября ребята из Enclave выложили разбор уязвимости в Microsoft Authenticator для Android. Её уже закрыли, но устроена она настолько просто, что хочется пересказать.

Authenticator на Android работает как брокер. Teams, Outlook и остальные приложения Microsoft не спрашивают у вас пароль сами. Они идут к Authenticator и говорят: я Teams, дай мне токен на почту и файлы этого человека. Брокер проверяет, кто пришёл, и выдаёт.

Ошибка как раз в проверке. В Authenticator был экран AccountChooserActivity, и запустить его могло любое приложение на телефоне. Приложение передавало туда JSON, в котором само писало, кто оно такое: имя пакета и адрес возврата (redirect URI). Брокер брал имя пакета из этого же JSON, просил у системы сертификат подписи этого пакета, считал от него хэш и сравнивал с присланным адресом. Совпало, значит свой.

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

На выходе злоумышленник получал access и refresh токены от имени Teams: почту, файлы, календарь и чаты рабочего аккаунта. По refresh токену доступ можно продлевать и дальше. Приложению при этом не нужно ни одного разрешения и не нужен root, от человека требовалось только его установить. Уязвимости дали 8.6 из 10, номер CVE-2026-80097.

Исправили в версии 6.2606.4246. Если у вас в Authenticator есть рабочий аккаунт, обновитесь. Админам советуют больше: токены с устройств, где стояла старая версия, считать утёкшими и отозвать refresh токены.

Я пишу ботов и сайты на заказ, и та же самая ошибка, только попроще, попадалась мне в чужом коде, который приносили доделать. Бот берёт id пользователя из параметра в ссылке или из данных кнопки, а не из того, что прислал сам Telegram. Сайт считает тебя админом, потому что так написано в скрытом поле формы. Правило тут одно: кто к тебе пришёл, спрашивай у системы, а не у того, кто пришёл. В Android для этого есть getCallingPackage() и Binder.getCallingUid(), в Telegram-боте это from.id из апдейта, на сайте сессия на сервере.

Если вы смотрите чужой код и не знаете, с чего начать, начните с этого места. Даже у Microsoft оно оказалось дырявым.

Показать полностью
7

Два часа в PyPI лежала библиотека, которая воровала ключи. И её даже не нужно было импортировать⁠⁠

21 октября взломали LiteLLM. Это популярная питоновская библиотека, через которую программы ходят к разным нейросетям по одному интерфейсу. Сам код на гитхабе никто не трогал. Взломали конвейер, который собирает и выкладывает релизы, и через него в PyPI и на Docker Hub уехала версия 1.107.0 с сюрпризом внутри.

В PyPI она провисела примерно два часа, по их собственному отчёту с 11:39 до 13:23 по UTC. Образы в Docker Hub с тегами v1.107.0 и latest были заражены чуть дольше, до 14:20. Вроде мало. Но популярный пакет за два часа успевают скачать и сервера с автосборкой, и люди, которые просто решили обновиться.

Самое неприятное тут в том, как оно запускалось. При установке в папку site-packages клались три файла: cook.pth, cook.py и sitecustomize.py. Файлы .pth Python читает сам при каждом старте интерпретатора, вообще при каждом. Получается, если пакет просто стоит в окружении, вредонос стартует вместе с любым вашим скриптом, даже если в нём нет ни одного import litellm. Дальше он собирал ключи и пароли, до которых мог дотянуться, и подгружал инструменты для удалённого доступа.

Удалить пакет после этого мало, украденные ключи сами себя не отзовут. Все, кто разбирал инцидент, советуют одно и то же: откатиться на 1.106.2, а все секреты, которые видела заражённая машина, считать утёкшими и перевыпускать.

Я пишу ботов и парсеры на заказ, и почти в каждом проекте у меня лежит .env с токеном бота, доступом к базе, иногда с ключом от платёжки. Так что про такие истории я думаю совсем не абстрактно. Вот что я делаю, чтобы меня это задевало поменьше.

1. Версии зависимостей фиксирую точно, через ==. Никаких «поставь последнюю». Обновляю руками, когда сам решил, а не когда сервер сам пересобрался.

2. В Docker не использую тег latest. Тут прямо в тему: заражённым оказался как раз latest.

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

4. У каждого проекта свои ключи. Если утечёт один, не придётся бегать и менять всё у всех заказчиков.

5. Токены и пароли заказчик оформляет на себя. Если что-то случилось, он может отозвать их сам, не дожидаясь меня.

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

Кстати, по данным Chainguard, LiteLLM так ломают уже второй раз за семь месяцев. Если у вас где-то стоит litellm без указания версии, гляньте, какая там сейчас.

Показать полностью
2

«Вы предложили, я согласился». Как я однажды поработал за 500 рублей⁠⁠

Самый дорогой заказ в моей жизни стоил 500 рублей. Дорогой, понятно, для меня.

Это было в самом начале. Я тогда был фрилансером чуть ниже среднего. Отзывов мало, портфолио никакого, беру всё мелкое, что попадается. За заказы на бирже шла настоящая драка: ставишь цену, а через минуту кто-то откликается дешевле. Поэтому цену я ставил по принципу «лишь бы взяли».

Приходит задача. Продвижение и рассылка сообщений во ВКонтакте. Я читаю, прикидываю и пишу: 500 ₽. Цену я поставил вполне осознанно и, кажется, был собой доволен.

Довольства хватило ровно до того момента, как я сел работать. Работы там оказалось минимум на несколько тысяч. Ошибся я в разы.

Пишу заказчику. Вежливо, по делу: недооценил объём, давайте пересмотрим цену.

Ответ пришёл быстро и был железно логичным: «Вы предложили, я согласился».

Спорить, если честно, было не с чем. Я предложил. Он согласился. Всё по-честному.

Отменить заказ я тоже думал. Но отмена грозила плохим отзывом, а у меня отзывов и так было по пальцам пересчитать. Для новичка это хуже любых потерянных денег. Так что я выдохнул и сделал всё, что было в задаче.

Сдаю. Заказчик пишет: «А можно ещё отчёт по проделанной работе?»

Можно, конечно. За 500 рублей у нас всё включено.

Отчёт я тоже сделал. Аккуратный, по пунктам. Подозреваю, это был самый подробный отчёт в истории заказов за пятьсот рублей.

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

С тех пор у меня простое правило. Сначала разбираюсь в задаче, потом называю цену. И называю её так, чтобы потом не хотелось писать заказчику «давайте пересмотрим».

А у вас было такое, что сами назвали цену и сами же об этом пожалели?

Показать полностью
4

Работаю из дома с 2023 года. Ожидание и реальность⁠⁠

Когда я уходил на фриланс, у меня в голове была картинка. Я её хорошо помню, потому что она так ни разу и не сбылась. Записал по пунктам, пока помню обе версии.

Ожидание: встаю, когда хочу.
Реальность: встаю, когда заказчик написал «вы тут?». Обычно это 7:12. Почему именно 7:12, не знаю. Но так пишут разные люди из разных городов.

Ожидание: работаю с ноутбуком в кафе, пью раф, смотрю в окно.
Реальность: попробовал один раз. Розетка нашлась только у столика возле туалета, вайфай отваливался каждые десять минут, а раф остыл, пока я выяснял, почему не деплоится бот. В кафе я больше не работаю. В кафе я ем.

Ожидание: свободный график.
Реальность: график правда свободный. Он свободно растекается на все сутки. Утром правки, днём созвон, вечером я «на минутку гляну логи», и вот уже час ночи.

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

Ожидание: рабочее место как в видео на ютубе. Подсветка, растение, механическая клавиатура.
Реальность: клавиатура механическая, тут я себя не обманул. Растение было. Оно не пережило дедлайн по игре для Яндекс Игр, две недели я про него не вспоминал. Подсветка тоже есть, это монитор.

Ожидание: созвоны в рубашке.
Реальность: рубашка сверху. Снизу шорты с котами. Камера стоит так, что видно потолок и половину лица. Заказчики не жалуются, некоторые сидят так же.

Ожидание: обед по расписанию.
Реальность: обед наступает, когда прошли тесты. Если тесты не прошли, обеда нет. В плохие дни это ужин в четыре часа дня из того, что нашлось в холодильнике.

Ожидание: появится время на спорт.
Реальность: мой спорт это дойти до двери, когда курьер привёз пиццу. Шагомер в телефоне иногда смотрит на меня с осуждением. Ну, как умеет.

Ожидание: дома все поймут, что я работаю.
Реальность: «Ты же всё равно дома. Прими посылку, сходи на почту, погуляй с собакой». Объяснить, что я на работе, сложно. Особенно когда я на работе в шортах с котами.

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

Кто тоже работает из дома, какая ваша картинка не сбылась?

Показать полностью
201

Пятница, 17:40. «Там поменять одну строчку»⁠⁠

Это было весной, в пятницу. Я записывал по ходу, потому что уже на втором часу понял, что это надо сохранить.

17:40. Пишет заказчик, которому я полгода назад делал бота для записи в барбершоп. «Алексей, привет! Там в боте надо поменять одну строчку. "Запись подтверждена" на "Ждём вас!". Пять минут, не больше». Соглашаюсь. Действительно, строчка.

17:46. Открываю проект. Последний раз я его видел в октябре. Вспоминаю, где лежат тексты. Тексты в отдельном файле. Молодец, прошлый я.

17:49. Меняю строчку. Хочу перезапустить бота на сервере. Сервер меня не пускает.

18:05. Выясняется, что заказчик переехал на другой хостинг. Сам. «Там тариф был дешевле». Доступы у знакомого, который «помогал с переездом».

18:30. Знакомый отвечает. Присылает пароль фотографией экрана. Снято под углом, и непонятно, где маленькая l, а где единица. Пробую оба варианта. Подходит третий.

18:52. Захожу. Бот работает, но код на сервере не мой. Кто-то правил его прямо там. В файле с текстами появилась строчка «Скидка 15% для постоянных!!!». С тремя восклицательными знаками. Это ценная информация, её терять нельзя.

19:20. Сливаю свою версию с серверной. Аккуратно, руками. Восклицательные знаки сохраняю все три.

19:35. Перезапускаю. Бот падает. На новом хостинге другая версия Python, и одна библиотека с ней не дружит.

20:10. Обновляю библиотеку. Бот поднимается. Делаю тестовую запись на завтра на 12:00. Приходит «Ждём вас!». Красота.

20:12. Заказчик: «О, работает! Слушай, а раз ты там, можно "ждём вас" с маленькой буквы? А то как-то кричит».

20:13. Меняю. Перезапускаю. Ничего не падает. Я даже немного разочарован.

20:15. Заказчик: «Спасибо огромное! Сколько я тебе за пять минут должен?»

Я честно посчитал. Вышло два с половиной часа, из них на саму строчку ушло секунд сорок. Взял за час. Он перевёл и прислал смайлик с бицепсом.

После той пятницы я кое-что поменял. При сдаче проекта мы теперь сразу договариваемся, кто трогает сервер. Доступы храню у себя. Пароли фотографией больше не принимаю, только текстом. А «одна строчка» у меня теперь стоит как час работы, и заказчики, кстати, не спорят.

Рассказывайте, у кого какая «одна строчка» растянулась на вечер.

Показать полностью
2785

«Ты же программист». Что я чинил родне за последний год⁠⁠2

На фрилансе я с 2023 года. Пишу ботов, сайты, игры на Unity. Для заказчиков я разработчик. Для родственников я человек, который «что-то там с компьютерами», а значит, отвечает за всё, где есть провод или кнопка.

Собрал список за год. Всё правда, я только убрал имена.

1. Тётя попросила «поставить интернет на телевизор». Интернет на телевизоре был. Не было пароля от вайфая, который она сама поменяла и записала на обороте календаря. Календарь выбросили в январе.

2. Дядя спросил, могу ли я «взломать» его старую почту. Почта его, пароль он помнит. Не помнит только, на каком она сервисе. Перебрали три, нашли на четвёртом. Хакером я себя ощущал ровно минуту.

3. Бабушка позвонила с вопросом: «Почему у меня в телефоне всё большое?» Включилось увеличение шрифта. Двадцать минут я по телефону вёл её до настроек. В итоге она решила, что так даже лучше видно, и оставила.

4. Двоюродный брат попросил сделать ему игру «как GTA, только про наш район». Срок к выходным. Бюджет «ну ты же свой». Я сделал ему кубик, который ездит по квадрату. Он сказал, что для начала нормально.

5. Мама попросила удалить вирус, который пишет, что память заполнена. Вирусом оказались 11 тысяч картинок из родительского чата. Каждая открытка «с добрым утром» в трёх экземплярах.

6. Принтер. Тут без подробностей. Принтер был всегда, и принтер победил.

7. Отец решил, что раз я пишу ботов, я могу сделать бота, который будет за него спорить в домовом чате. Я честно задумался. Потом представил, чем это кончится, и отказался.

Самое смешное, что за всё это время никто ни разу не спросил, чем я на самом деле занимаюсь. Зато на семейных праздниках меня представляют так: «Это Лёша, он по компьютерам. Лёш, глянь потом, у Светы ноутбук гудит».

Ноутбук я глянул. Там была кошка. Она спала на решётке вентилятора.

Показать полностью
7

Разговорник «заказчик – русский». Составлен за три года фриланса⁠⁠

Я делаю сайты и ботов на заказ. За это время накопился словарик. Делюсь, вдруг кому пригодится. Заказчикам тоже можно, я не со зла.

«Там делов на пять минут»
Перевод: я не знаю, сколько это займёт. Но надеюсь, что дёшево.

«Нужен простой бот»
Бот с оплатой, админкой, рассылкой, выгрузкой в Excel и интеграцией с 1С. Простой он потому, что заказчику его будет просто использовать.

«Сделайте как у Озона, только попроще»
Сделайте Озон.

«Бюджет обсудим»
Бюджет уже обсудили. Без вас. Он маленький.

«Можно небольшую правочку?»
Можно поменять логику, дизайн и, если не сложно, название проекта.

«Я сам немного разбираюсь»
Сейчас будет скриншот кода с ChatGPT и вопрос, почему я так не сделал.

«Срочно!»
Можно было вчера. Но ТЗ будет в четверг.

«Это же просто кнопка»
За кнопкой оплата, проверка, база данных, уведомление менеджеру и письмо клиенту. Но да, снаружи кнопка.

«Мой племянник сделал бы за выходные»
Племянник уже делал. Поэтому вы здесь.

«Давайте сначала сделаете, а если понравится, заплачу»
Давайте я сначала заплачу вам, а если понравится, вы мне вернёте.

«Логотип покрупнее»
Ещё покрупнее. Нет, не так.

«Посмотрю вечером и отпишусь»
Отпишется через две недели с фразой «ну что там, готово?».

«У меня есть идея на миллион, нужен только программист»
Программист нужен бесплатно, за долю. Миллион пока тоже в виде идеи.

«Всё отлично, спасибо!»
Редкий зверь. Встречается примерно в половине случаев, и ради этого всё и делается.

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

Дополняйте в комментах, у кого что было. Особенно жду дизайнеров, у вас наверняка свой разговорник.

Показать полностью
2

Три года на фрилансе. Что я понял про работу на себя⁠⁠

Я фрилансер-разработчик. Делаю ботов, сайты, игры, скрипты. С 2023 года работаю на себя, на Kwork за это время набралось 149 отзывов. Решил записать, что понял за три года. Без мотивации и «уволься с завода», просто как есть.

Свобода есть, выходных нет. Можно работать в два часа ночи в пижаме. Но и заказчик может написать в два часа ночи, и ответить хочется, потому что иначе он уйдёт к тому, кто ответит.

Деньги приходят волнами. Месяц густо, месяц тихо. Первое правило, которое я выучил: не тратить всё в густой месяц.

Самое сложное не код. Код это как раз самая понятная часть. Сложно понять, что человек на самом деле хочет, когда он пишет «нужен простой бот».

Быстрый ответ продаёт лучше портфолио. Серьёзно. В отзывах мне чаще всего пишут не «отличный код», а «быстро отвечал» и «всё объяснил».

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

Отказывать нормально. Лучше сказать «это не моё», чем взять заказ и сорвать срок. Отказ забывают через день, плохой отзыв висит годами.

Друзья думают, что ты не работаешь. «Ты же дома сидишь, можешь в среду днём помочь с переездом?». Могу. Но потом буду доделывать заказ до ночи.

В общем, фриланс это не «работа мечты» и не «нестабильная фигня». Это обычная работа, просто начальник у тебя ты сам. Иногда хороший, иногда так себе.

Кто тоже на фрилансе, что бы добавили?

Показать полностью
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества