k-id를 사용해 어떤 웹사이트에서든 계정을 자동으로 성인으로 나이 인증합니다.
URL: https://age-verifier.kibty.town/
k-id를 사용해 어떤 웹사이트에서든 계정을 자동으로 성인으로 나이 인증합니다.
만든 이: xyzeva 및 Dziurwa, 이전 작업에 대한 greetz: amplitudes (이전 작업에 대해)
현재 영국(UK) 등 이미 접근 가능한 지역에 있는지 여부는 상관없습니다. 이 방법은 지금도 인증되며, 3월의 전 세계 롤아웃 이후에도 계속 유효하도록 계정을 미리 인증합니다. 사용 방법은 간단합니다. discord.com/app으로 들어가서 F12를 누르고, Console로 이동한 다음, 아래 스크립트를 복사해 붙여넣고 엔터를 누르세요. 그러면 뜨는 캡차를 풀면 됩니다(필요하다면 그 전에 allow pasting을 입력).
js// add a chunk to extract webpack's moduleCache let webpackRequire = webpackChunkdiscord_app.push([[Symbol()],{},(r) => r]); // cleanup the chunk we added webpackChunkdiscord_app.pop(); let modules = webpackRequire.m; let cache = webpackRequire.c; // https://github.com/moonlight-mod/moonlight/blob/main/packages/core-extensions/src/spacepack/webpackModules/spacepack.ts // helper to find a webpack module via code snippet function findByCode(src) { for (const [id, mod] of Object.entries(modules)) { if (mod.toString().includes(src)) { return cache[id].exports; } } } // helper to find an object by its key function findObjectFromKey(exports, key) { if (!exports) return; for (const exportKey in exports) { const obj = exports[exportKey]; if (obj && obj[key]) return obj; } } // https://github.com/moonlight-mod/moonlight/blob/main/packages/mappings/src/mappings/discord/utils/HTTPUtils.ts // find the discord api client const api = findObjectFromKey( findByCode('.set("X-Audit-Log-Reason",'), "patch", ); // send a api request to discord /age-verification/verify and then redirect the page to our website const request = await api.post({ url: "/age-verification/verify", body: { method: 3 }, }); const verificationUrl = request.body.verification_webview_url; window.location.href = `https://age-verifier.kibty.town/webview?url=${encodeURIComponent(verificationUrl)}`;
(코드는 편하게 읽어보셔도 됩니다. 읽기 좋게 만들어뒀고 숨길 것도 없습니다.)
링크로 이동되거나(또는 이동할 링크가 제공될 것입니다) 그 다음에는 페이지에 성공(success)이라고 표시될 때까지 기다리기만 하면 됩니다.
축하합니다! 이제 Discord 계정이 나이 인증되었습니다.
나이 인증 페이지로 이동해 셀피(selfie)를 선택하세요. 그 다음 QR 코드의 URL을 가져와 이 입력 상자에 넣고 verify를 누르세요.
Discord가 사용하는 나이 인증 제공업체인 k-id는 얼굴을 서버에 저장하거나 전송하지 않습니다. 대신 얼굴에 대한 여러 메타데이터와 전반적인 프로세스 세부 정보를 서버로 보냅니다. 이는 프라이버시 측면에서는 좋지만(다른 일부 제공업체는 실제로 얼굴 영상까지 서버로 보내기도 하니까요), 그들에게는 나쁠 수도 있습니다. 우리가 그럴듯한 메타데이터를 서버로 보내도, 그들이 그것이 진짜가 아닌지 판별할 방법이 없기 때문입니다.
과거에는 이것이 쉬웠지만, k-id의 얼굴 인증 파트너(faceassure)는 amplitudes k-id verifier가 공개된 이후 이를 훨씬 어렵게 만들었습니다(그리고 그 영향으로 지금은 더 이상 동작하지 않습니다).
Discord가 나이 인증 요구사항을 전 세계로 확대하기로 결정하면서, 우리는 새로운 체크를 우회할 수 있는지 확인하기 위해 다시 살펴보기로 했습니다.
정상적인 요청 페이로드와 생성한 페이로드를 비교해 보니, 기존 구현에서 빠뜨리고 있는 것이 있었습니다. 바디(body)에 encrypted_payload, auth_tag, timestamp, iv가 누락되어 있었습니다.
코드를 살펴보면, 이는 단순한 AES-GCM 암호로 보이며 키는 HKDF(sha256)로 도출된 nonce + timestamp + transaction_id입니다. 우리는 이를 쉽게 복제할 수 있고, 생성 출력에 누락된 파라미터들도 만들 수 있습니다.
여기서부터 조금 까다로워집니다. 암호화를 완벽히 복제한 뒤에도 인증 시도가 성공하지 않았습니다. 그렇다면 실제 페이로드에 대해서도 검사를 하고 있는 것이 분명합니다.
여러 번의 시행착오 끝에, 검사되는 부분을 prediction 배열로 좁혔습니다. 해당 배열은 outputs, primaryOutputs, raws입니다.
알고 보니 outputs와 primaryOutputs는 raws로부터 생성됩니다. 즉 raw 숫자들이 나이 출력으로 매핑되고, 그 다음 이상치(outlier)를 z-score로 제거합니다(primaryOutputs에는 1회, outputs에는 2회 적용).
그 밖에도 다른 차이점이 있습니다:
xScaledShiftAmt와 yScaledShiftAmt는 랜덤이 아니라, 두 값 중 하나만 될 수 있습니다.이 모든 작업을 마친 뒤, 관련 코드는 전부 오픈소스이며 github에서 확인할 수 있습니다. 그래서 실제로 우리가 정확히 어떻게 하는지 직접 볼 수 있습니다.