작은 스테이지 압축 파일이 풀자마자 커질 수 있었다
커스텀 스테이지 ZIP의 겉 크기만 확인해서는 부족했다. 경로, 파일 수, 압축 해제 크기와 PNG 헤더까지 같은 예산 안에서 확인했다.
태그
#보안 · 14개
커스텀 스테이지 ZIP의 겉 크기만 확인해서는 부족했다. 경로, 파일 수, 압축 해제 크기와 PNG 헤더까지 같은 예산 안에서 확인했다.
비밀번호 찾기 응답이 계정 존재 여부에 따라 달랐다. 화면에는 늘 같은 답을 주고, 재설정이 끝나면 남은 링크와 로그인 세션을 한꺼번에 끊도록 손봤다.
워치 시세 요청을 IP 하나로만 제한했더니 같은 네트워크의 정상 기기가 서로 quota를 빼앗았다. 토큰별 제한과 넉넉한 IP 상한을 함께 뒀다.
워치에 보이는 8자리 코드는 짧고 사람이 직접 입력해야 했다. 혼동 문자를 빼고, 서버에는 해시만 저장하고, 15분 뒤에는 못 쓰게 했다.
자동 주제의 출처를 앱에서도 열게 했는데 아무 URL이나 OS 브라우저로 넘길 수는 없었다. 공개 주소만 통과시키는 검사 함수를 만들었다.
경기 출처와 문의 링크를 공통 함수로 열다가 임의 스킴까지 통과할 여지가 생겼다. HTTPS 호스트와 mailto 형식을 좁게 허용하고 실패 안내도 한곳에 모았다.
스토어 product id와 앱 권한 key를 같은 문자열처럼 쓰다가 활성화가 끊겼다. 영수증 확인 뒤 entitlement를 다시 읽어 기능을 여는 흐름을 맞췄다.
아이폰과 워치가 함께 읽는 App Group 설정에 장기 토큰까지 들어 있었다. 일반 설정은 그대로 두고 토큰만 공유 Keychain으로 옮겼다.
CSV에서 쉼표와 따옴표만 처리하면 되는 줄 알았다. 등호로 시작하는 메모가 수식이 되는 걸 보고 자유 입력 문자열을 따로 막았다.
가입하지 않은 이메일을 알려주는 문구가 계정 조회 수단이 됐다. 주소가 있든 없든 같은 답을 주고 실제 계정에만 메일을 보내게 고쳤다.
HTTPS면 괜찮을 줄 알았는데 내부 IP도 문법상 멀쩡한 URL이었다. 저장과 이미지 로더가 같은 허용 목록을 보게 했다.
남의 예약에는 403, 없는 예약에는 404를 주니 식별자만 바꿔도 존재 여부가 보였다. 밖에서는 같은 404를 주고 자세한 원인은 내부 기록으로만 남겼다.
파일 이름과 MIME만 보고 이미지를 받았다가 내용이 전혀 다른 파일도 통과한다는 걸 알았다. 첫 바이트로 형식을 확인하고 이미지는 다시 인코딩해서 저장했다.