puzzled-pirates-blockade
·
CTF Write Up/Plaid CTF 2023
코드 분석더보기server/src/index.mts보드와 진영, 배를 초기화하고 현재 라운드와 점수를 관리한다. 특히 advancedRound()에서 매 라운드 진행, 선공/후공 상태 결정, 상태 전송, 최종 플래그 판정까지 처리한다.const RoundTime = 1000000000;const MaxRounds = 75;const RoundMutex = new Mutex();const Flag = process.env["FLAG"] ?? "PCTF{test_flag}";async function main() { await dataSource.initialize(); await dataSource.dropDatabase(); await dataSource.synchronize(); await lo..
Undercover Pirate
·
CTF Write Up/UMassCTF 2026
코드 분석더보기docker-compose.yamlcaptain 서비스는 Compose 설정상 piratenet과 vault 두 네트워크에 동시에 연결되어 있다. 반면 vault 서비스는 vault 네트워크에만 연결되어 있고, 이 네트워크는 internal: true로 선언되어 있어 외부와 격리된 내부망이다. 또한 vault 서비스에는 ports 설정이 없어 호스트로 직접 publish되지 않는다.services: proxy: build: context: ./proxy args: HOST: ${HOST} ports: - "${PORT}:443" networks: piratenet: ipv4_address: ${PIRATENET}..
moonshot
·
CTF Write Up/Plaid CTF 2024
코드 분석더보기docker-compose.yml지구 → 달 → 착륙선(lander) 구조를 흉내 낸 3단 프록시 네트워크이다. services: traefik: image: traefik:v2.5 restart: always command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:8080" ports: - "8080:8080" networks: - 1_earth volumes: - /var/run/docker.sock:/var/run/docker.sock earthlink..
Viehaw!
·
CTF Write Up/Plaid CTF 2025
코드 분석더보기bun/index.tsbun은 모든 GET 요청을 받지만 validURL을 통과한 경로만 graphite로 프록시한다.function validURL(c: Context) { const req_path = c.req.path; if (req_path.startsWith("/media/")) return true; if (req_path == "") return true; return false;} 외부에서는 graphite에 직접 요청할 수 없지만 localhost:1337/media/... 형태로 내부 graphite 요청이 가능하다.app.get('*', async (c: Context) => { ... if (!utils.validURL(c)) throw new Error(..
ChatPPP
·
CTF Write Up/Plaid CTF 2025
코드 분석더보기server/src/api.ts사용자 conversation을 sanitize 없이 json으로 직렬화해서 db에 저장한다.ApiRouter.post("/chat/save", async (req, res) => { const { conversation } = req.body; if (typeof conversation !== "object") { res.status(400).send("Invalid request"); return; } const result = saveConversation(conversation); return res.json(result);}); server/src/db.ts테이블에는 임의 16진수 문자열인 uid와 ..
hangman(FIVE PACES)
·
CTF Write Up/Plaid CTF 2025
코드 분석더보기hangman1플레이어가 단어를 고르고 bandits 프로그램이 글자를 추측한다. 규칙대로 응답하여 50번을 이기면 FLAG를 출력한다.__int64 __fastcall main(int a1, char **a2, char **a3){ char **v4; // rbx size_t v5; // rax __int64 v6; // rcx __int64 v7; // rdx unsigned int v8; // eax __int64 v9; // rdx unsigned int v10; // eax char *v11; // rcx __int64 v12; // rdx char j; // [rsp+13h] [rbp-18Dh] char v14; // [rsp+14h] [rbp-18Ch] c..
Prospectin'(Fool's Gulch)
·
CTF Write Up/Plaid CTF 2025
코드 분석더보기prospectors_claimresult가 가리키는 값을 1씩 증가시킨다._DWORD *__fastcall bump(_DWORD *result){ ++*result; return result;} 사용자 입력 문자열을 받아서 수백 개의 조건을 검사하고, 맞춘 개수(score)에 따라 플래그 출력을 결정한다.int __fastcall main(int argc, const char **argv, const char **envp){ char s; // [xsp+Bh] [xbp-45h] BYREF char v5; // [xsp+Ch] [xbp-44h] char v6; // [xsp+Dh] [xbp-43h] char v7; // [xsp+Eh] [xbp-42h] char v8; // [..
The Sundown Vault
·
CTF Write Up/Plaid CTF 2025
코드 분석더보기api.tsMaxSecretDate는 시스템에서 허용하는 비밀 공개 날짜의 최대 상한선이다. 해당 날짜보다 미래의 비밀은 만들지 못하도록 제한하려는 의도로 정의된 상수로 보여진다.UpdateIntervals는 비밀의 남은 시간을 체크하는 주기들을 미리 정의해 둔 배열이다. const MaxSecretDate = "2030-01-01T00:00:00.000"; // if you want to keep a secret longer than this, do it yourself >:(const UpdateIntervals = [ Duration.fromObject({ years: 2 }).toMillis(), Duration.fromObject({ years: 1 }).toMillis(), Du..
Cybergames Store
·
CTF Write Up/Jeanne CTF 2026
Exploit사이트 소개 페이지에서 LDAP 로그인이 추후 제공될 예정이라고 힌트를 주고 있다. 로그인 페이지의 주석을 통해 LDAP 기반 인증 기능이 서버 측에 부분적으로 구현되어 있음을 확인할 수 있었다. 이에 로그인 요청의 인증 타입 파라미터를 ldap로 변경하여 서버가 실제로 LDAP 인증 경로를 처리하는지 검증하였다. 그 결과, 사용자 입력이 적절히 검증되지 않은 상태로 LDAP 쿼리에 사용되고 있었으며, admin* / *와 같은 입력을 통해 LDAP Injection이 가능하였다. 관리자로 로그인에 성공하면 Admin Panel에서 숨겨진 인증 경로가 존재한다. 해당 경로에는 숨겨져 있던 관리자 전용 탭이 보여진다. 관리자 로그인을 한 번 더 해야했지만 admin / admin으로 통과할 수..
Ocarina - Level 3
·
CTF Write Up/Jeanne CTF 2026
코드 분석더보기crypto.js사용자가 직접 입력한 문자열이 그대로 AES 암호화 키로 사용된다.// AES encryption implementation for client sidelet USER_KEY = null;const crypto = { // Set the user key setKey(key) { USER_KEY = key; }, // Pad key to 32 bytes (for AES-256) padKey(key) { const bytes = new TextEncoder().encode(key); const padded = new Uint8Array(32); padded.set(bytes.slice(0, 32)); ..