Дыркнет капчи
*база заметки написана год назад, как оно работает сейчас, в душе не ебу, да и не особо интересно.
Введение
Одним прекрасным вечером, я как обычно лежал и грустил (бездельничал)
Долго не мудрствуя, решил в качестве развлечения посмотреть на ютуб любимую передачу про фокусы.
Но мои планы были разрушены, ведь в реках всплыло совсем другое видео. Тоже вроде какой-то чел в маске, но оказалось, эт реклама наркс сурса (там тоже в каком-то смысле фокусы) и при том, ихней (а может и евоной) рекламы чет было прям сильно дохуя видосов в выдаче.
В целом, подобное на ютуб не впервой. Но прям нативки в реках я не ожидал.
А тех, кто дейли и сам нутру и гемблу клоачит, такое совсем не удивит.
Примеры классики (на всякий случай, осуждаю)
Щя для креосов можно также потыкать нейронки для Adversarial Attacks to AI Art Tools типо Glaze (еще есть Mist), которые пытаются наебать другие нейронки (взял инфу туть), что на картинке точно котик, а не гигантская анаконда.
Что забавно, в основе нейронок против генерации картинок, та же самая нейронка для генерации картинок.. прост учат ее пиздеть и делать хуйню.
Обсуждение всего этого алго. Пытаясь наебать дифузию учат на ней же..
Ещё одно обсуждение. На тестах, пишут, дифузии фул похуй на "защиту" (примерчики и тесты).
Но над тестить на гуглах, мож для арбитража и прокатит.
Что еще более забавно, сразу после публикации алго появились методы обхода защиты (произошел обман нейронки для обмана нейронки).
Вот еще, обход в пару строк https://github.com/lllyasviel/AdverseCleaner
Хотя, самый красивый (имхо) метод выглядит так
Кароче, я вспомнил, что про сурс уже спрашивали и писали, что там интересная капча. А тыкать интересные капчи я люблю.
Предыстория
Некоторое время назад в чат очередной раз прилетел вопрос "Как решать такую капчу?".
Капча довольно оригинальная, двигаешь ползунок и ищешь там отгадку.
Я предложил элегантное решение, на что получил ответ:
И вот, вспомнив данную ситуацию я решил таки добить, протыкать и доказать, что моя гипотеза рабочая
Штош, похуярили
Первая капча
Открываю фул сурс, вижу первую капчу (да, их тут несколько).
Защита от ботов на js
Также тут имеется js таска, она не шибко интересная интересная.
Ну, тут все вроде с ходу видно, просто микро прочек фингера и js сбор топ сикрет ключа в хэдер.
Вторая капча
А вот, наконец, самое интересное - вторая капча. Прилетает JSON с SVG, что предвещает интересную задачу.
Небольшой спойлер: Именно взломать капчу, найдя дырку чтобы решать 100%, я так не смог, но подозреваю что такое возможно.
Не многие знают, вернее знают не только лишь все, но прямо в ссылке можно загрузить кучу данных, даже целый сайт, при желании. Воспользуюсь этим для удобных тестов.
Потенциально такое можно использовать для SVG XSS, но на деле штука обычно мало полезная, хотя на h1 есть примеры неплохих выплат, даже есть cve.
Кароч, я вытянул саму svg и начал тыкац, чтобы понять как оно вообще устроено
Дальше банально, бреки, спиздинг кода с допилом. Я хотел попасть сразу куда надо, поэтому не стал копаться в сурсах изначально.
И я, действительно, сразу попал куда нужно. По сути, это и есть весь код отвечающий за нужную мне часть капчи.
А дальше, я просто взял все эти сурсы и стал разбираться, как делать генерацию и решение через бас.
Буквально пару модификаций функции - фикс парса данных через xpath и фсе готово
Теперь можно задать позицию и убедиться, что все работает заебись. Я поставил также отрисовку в браузере.
Я потыкал разные настройки, чтоб подобрать как лучше слать капчу, но остановился на исходном.
Тем не менее, мы все равно рисуем это в браузере, что ни есть хорошо. Я сел изучать рисование svg и думать как же мне таки кастовать его без бас браузера.
Я прочитал доку и пару сторонних сурсов по svg, в целом не сложно, если тыкать все последовательно.
Вот этот материал, очень неплох https://yoksel.github.io/svg-path/
И я таки смог обойтись без баса, используя ноду.
Либа - https://www.npmjs.com/package/@resvg/resvg-js
В душе не ебу, что у него под капотом, но работает и хуй с ним
Так, а как выглядит всё вместе?
Прост чекаем, какая картинка выходит по высоте, а потом пихаем все картинки в массив
А после, дергаем лучший вариант
Наконец, настал момент, когда можно приступить к проверке узнать работает ли моя идея.
Ого, оно работает черт возьми!
О, ну ни чего себе, я все-таки оказался прав и оно работает, как неожиданно (сарказм)..
Я думал прикрутить тесеракт, ручками обвел, почекал как оно распознает. Иии.. результат говно, а точнее тессеракт говно под капчи.
Разумеется, если красиво все раскрасить, некоторые нейронки (easyocr) на части изображений могут что-то понять. Но в целом, надо делать как надо, а как не надо не делать. Так делать не надо, тк тесеракт и простые OCR тут не пойдут.
Тогда я решил потыкать другие нейронки, более умные.
Специализированные нейронки, что не удивительно, гадают вообще без проблем.
Можно кстати попробовать и самому обучить типо как туть
По итогу я всё это потыкал, но красивого "разъеба" не вышло, дырку в алго я ни какую найти не смог, по-этому пошёл дальше смотреть свою передачу про фокусы. Я пытался провести обратный инжинеринг, но не имея сурсов наугад протыкать сожно. По сути все состоит из точек и микро отрезков которые их соединяют и хз как фильтровать не мусор.
Также паре товарищей скинул примеры как потыкал капчу, хотя очевидно что всем поебать..
Просто решать капчу довольно это банально, поэтому я позаимствовал сам код слайдера и даже сделал демо страничку, чтоб капчу можно было тыкац.
Хотя, опять же, смысла в этом не много, ибо алго для гена капчи я не придумал, если у кого есть, скиньте плез.
Спустя пол года
Но спустя пол года мне пришло сообщение от товарища
И я такой: Что же там могло поменяться?
И сходу я увидел POW - алго, который по сути пытается брутить (майнить) ответ на задачу.
get - запрос получения таска, в ответ
{"r":8,"secret":"NogO2FUdAuBY473MAzrlT10fKSHUUR84","p":1,"target":"00000","klen":128,"progress":15,"N":256}
verify - валидация таска, шлем решение
{"secret":"NogO2FUdAuBY473MAzrlT10fKSHUUR84","answer":"UvHUJNGysgPujySJ"}
Я сразу понял что это, тк уже видел пару раз, например на auto.ru при просмотре номера и предположил, что тут та же реализация.
Но выглядело непохоже и решил всё же потыкать код ручками и понять, что тут происходит. По сути оно прост создает воркера (4 штуки) по куску кода и начинает ворк.
А далее запускает функцию поиска решения
window.proofOfWorker.postMessage({challenge: window.currentChallenge});
Тогда я хуже понимал wasm чем сейчас, по-этому все что видел было прям необычно и сложно понять с ходу суть, но по факту мы просто имеем алго перебора на wasm и подготовку данных на обычном js в коде ниже.
Решение
А потом я просто взял, почекал на гите и нашел фул ориг кода https://github.com/sequentialread/pow-captcha
Шукал так, имея гит ак: https://github.com/search?q=base32768WASM&type=code
А теперь всё уже не выглядит таким страшным, особенно когда имеешь ориг сурсы)
Видим знакомый код
https://github.com/sequentialread/pow-captcha/blob/1a04d77a5475e7333b4ac8e5bde554ebb5ab17d7/static/proofOfWorker.js
Видим, и теперь понимаем по сути всю схему работы.
https://github.com/sequentialread/pow-captcha/blob/1a04d77a5475e7333b4ac8e5bde554ebb5ab17d7/static/captcha.js
Как и ожидалось, передаем json с задачей сюдаproofOfWorker.postMessage({challenge: challenge});
Тоесть он запускает 4-5 воркеров в работу и прослушивает ответ. Ну.. а на этом мои полномочия все, по сути все сурсы есть, остается только упаковать в ноду
Шо делац?
Имеем либу под подобную "капчу", которая пойдет для авто ру. У сайта выше иная либа, линк на нее дал, отличие как минимум в алго (хеш-функция Scrypt)
Имеем пример решения от @nyooooom. По факту прост делаем сервер на ноде и фсе.
const pow = require('proof-of-work');
const http = require('http');
const url = require("url");
const solver = new pow.Solver();
function solve(prefix, compl) {
return solver.solve(compl, Buffer.from(prefix)).toString("hex")
}
const requestListener = function (req, res) {
res.writeHead(200);
const url = req["url"];
req.on('data', function (_data) {
const data = _data.toString().split("&")
const prefix = data[0].replace("prefix=", "")
const compl = data[1].replace("compl=", "")
console.log("solving prefix " + prefix + ", compl " + compl)
res.end(solve(prefix, compl))
})
};
const server = http.createServer(requestListener);
server.listen('0001', 'localhost', () => {
console.log(`Server is running.`);
});
А дальше кидать запросеки, например с питона
def solve_pow(prefix, compl):
return requests.post("http://localhost:0001/", data={"prefix": prefix, "compl": compl}).text
Чудесно, по итогу, оказывается, не так уж всё и страшно)
Почему pow это неплохая защита от ботов?
Эту "капчу" не получится просто так "наебать", ответ из воздуха взять нельзя, его надо намайнить. Да, можно послать индусу на сервис, а можно привязывать капчу к айпи юзера (но на сервис можно слать прокси), но любое подозрение и таск прилетит овер сложный (да, это в буквально 1 флаг кастомизируется), майнить придется очень дохуя времени, а это ключевая цель любой капчи, особенно в режиме атаки.
Очевидно, она не лишена недостатков, на разных устройствах скорость решения разная (в качестве байпаса можно попытаться прикинуться слабым устройством, а юзать на норм), а еще может сложиться так что придется майнить очень долго.
Но как вспомогательная она прекрасна и потому, теперь ее и в яндекс капче, по слухам, используют)
Вот диаграмма среднего времени решения в секундах в зависимости от целевой сложности:
А какие капчи у них там ещё бывают?
Вообще, их много всяких на подобных сайтах, судя по всему (судя по исследовательским статьям, тк я на оных сурсах не обитаю).
Могу еще пару примеров разобрать:
1) Удаляем фон, дергаем каждую и соотносим с таблицей, чисто хардкод, а потом чекаем какие залиты одним из нескольких популярных алгоритмов, например просто чекнув отношение площади с цветом к площади без.
Тикток в этом смысле четочку сложнее
2) Фильтруем тонкие линии, а дальше радиально шагаем и дергаем инфу о концах каждой стрелки, далее просто соотносим время по углу в градусах простой формулой.
Вот подобная будет в след статье (про тутанота), штука не сложная, но интересная. Только без фигур.
3, 4, 5, 6, 7, 10, 11) Обычное распознавание текста, но обученное под капчу типо Xevil
8) Онли нейронка, какая-нибудь YOLO пойдет.
9) Скорее всего алгоритм кругов хафа из opencv, хотя явно есть и более простой вариант простым матаном.
Итоги
А если серьезно, нахуя я все это опять тыкал?
Мне было интересно изучить чет новое, всё-таки большая часть капч посредственные, а так хоть чет новое почекал.