Топ тупых лазеек для исследования конкурентов: source map
Введение
Инструменты и подходы из этой серии маленьких статьей вроде уже достаточно давно известны и расписаны, но я все равно встречаю такие лазейки один-два раза в неделю. На 1 из 10 проектов до сих пор находятся чемпионы, у которых открыт и .git с конфигами к БД и phpMyAdmin, бери не хочу.
Я часто присматриваюсь к конкурентам, продуктам и компаниям, в которых есть интерес к покупке (или реализации своими силами). Чтобы оценивать техническую составляющую, или подготовится к переговорам о слиянии, я всегда сам исследую интересующий продукт. Моя задача — понять насколько крутой в технологическом плане конкурент или проект, который мы могли бы купить. Но не стоит даже и переговоров начинать без минимального представления о состоянии "чужого храма". Иногда мне просто интересно кого-то "поковырять".
Я уж точно не являюсь профессионалом в пентестинге и уже тем более куллхакерцом, но с древних времен предпочитаю исследовать все ручками. Мне немного чужды инструменты комплексного сканирования (например, Metasploit), для меня пропадает вся интрига и атмосфера.
Source map для всех
Какое-то время назад верстальщикам стало скучно, ребята на JQuery тоже приуныли, и вот в один неизвестный день они собрались вместе и сказали – «Хватит! Мы тоже хотим писать много кода», и придумали современный фронтенд стек. Рынок сказал — «Супер, еще большее разделение труда!», и нехило так подогрел зарплаты фронтендеров и жопы некоторых бэкендеров.
И вроде все нормально, такое уже было и с мобильной разработкой, и с вебом, когда я был еще молод, но в этот раз целая куча вайтишников побежало писать на этих ваших ангулярах и реактах. Как результат - вырвиглазный код и бандлы по 20 мегабайт. Не поймите меня неправильно, я не хочу обидеть всех фронтенд разработчиков, но ваши менее опытные коллеги на зарплате в 300к сильно вас подставляют.
Вам же, наверняка, будет не очень удобно дебажить сжатый и обфусцированный код в браузере, тут на помощь нам приходят Source Map файлы. Если же вы можете получить к ним доступ, то, скорее всего, сможете восстановить изначальный код фронта и его конфигов (если они не .env, респект этим ребятам) и иногда даже с комментариями. Грешат этим многие, например мой любимый Яндекс.
Открываем исходную страничку, ищем подключенные js файлы, а в них упоминание файла с расширением js.map, и проверяем их доступность. Обычно в React.js это app.js
с кодом приложения и vendor.js
с подключенными пакетами. Если source map доступны, начинаем нашу экспедицию.
Скачиваем нужные нам файлы, кладем в директорию и распаковываем. Так как эти файлы обычный JSON, можно накалякать на коленке простенький скрипт для распаковки. Вот, например, мой максимально понятный и прозрачный:
const path = require('path'), fs = require('fs'), mf = process.argv[2], dir = 'unpack', {sources:s = [], sourcesContent:sc = []} = JSON.parse(fs.readFileSync(mf, {encoding: 'utf8'})); s.forEach((uri, i) => (fpath = `./${dir}/${uri}` .replace('webpack:///', ''), fdir = path.dirname(fpath)) && (fs.existsSync(fdir) || fs.mkdirSync(fdir, { recursive: true })) && fs.writeFileSync(fpath, sc[i]) || console.log(`-> ${fpath}`));
После распаковки получаем древо со всеми файлами фронт проекта, теперь можно искать интересные роуты, перенимать опыт и т.д.
Но я люблю "поставить на мониторинг": создаем гит репозиторий и пишем баш скриптик, который будет выкачивать, распаковывать и коммитить раз в неделю, например.
Итог
Подход мониторинга изменений помогает анализировать в какую сторону движется разработка и предсказать многие события, например: выход в новые страны, смену технологий и бизнес процессов. На долгосрочную перспективу - это очень интересный подход. Он уже выручал меня не раз в предсказании новых фич конкурентов, и мы всегда были на шаг впереди.
Если у вас есть фронт, разработанный на React/Angular или других фреймворках, и вам не пофиг, то советую проверить ваши js.map, возможно ваши матюги в комментариях уже кто-то читает.
Самый быстрый способ скрыть их от лишних глаз, добавить конфиг в nginx на закрытие файлов по маске *.map.
location ~ \.map$ { # Hide js.map, css.map and others *.map files error_page 404; # Send 404 # deny all; # Send 403 }