설명
비밀번호, 토큰, API 키, 세션 식별자 같은 민감 정보를 파일이나 브라우저 저장소에 평문으로 저장하면 디스크, 백업, 로컬 스토리지, 로그성 파일을 통해 비밀 값이 유출될 수 있습니다. 공격자는 유출된 값을 이용해 인증 우회, 세션 탈취, 내부 API 접근을 시도할 수 있습니다.
잠재적 영향
- 파일 시스템이나 백업에 남은 평문 비밀 값이 유출될 수 있습니다.
- 브라우저 저장소에 저장된 장기 토큰이 XSS나 로컬 접근으로 탈취될 수 있습니다.
- 평문 비밀번호 저장은 한 번의 유출로 여러 서비스의 계정 탈취로 이어질 수 있습니다.
해결 방법
- 비밀번호는 Argon2id, bcrypt, scrypt 같은 비밀번호 전용 해시로 저장하세요.
- 토큰, API 키, 세션 값은 가능한 저장하지 말고 필요한 경우 서버 측 vault 또는 암호화 저장소를 사용하세요. 키와 데이터의 접근 권한은 분리하세요.
- 브라우저
localStorage와sessionStorage에는 장기 인증 토큰을 저장하지 마세요. - 쿠키에 민감 값을 넣어야 하면 최소
Secure,HttpOnly,SameSite속성을 함께 설정하고 값 자체도 최소화하세요. 쿠키 속성은 값 자체를 암호화하지 않습니다.
예시
users는 애플리케이션의 저장 계층이며, 입력 검증과 오류 처리는 생략했습니다. bcrypt의 72바이트 입력 제한과 비용을 확인하고, 로그인 검증에도 동일한 입력 정책을 적용하세요.
변경 전
javascript
const fs = require("fs");
function save(req, res) {
fs.writeFileSync("/tmp/password.txt", req.body.password);
}
변경 후
javascript
const bcrypt = require("bcrypt");
async function save(req, res) {
const passwordHash = await bcrypt.hash(req.body.password, 12);
await users.save({ passwordHash });
}
설명:
- 변경 전: 비밀번호를 평문 파일에 써서 디스크나 백업 유출 시 그대로 재사용될 수 있게 합니다.
- 변경 후: 비밀번호를 전용 해시로 변환하고 원문을 저장하지 않습니다.
서명된 JWT도 내용이 암호화되는 것은 아닙니다. 쿠키의 전송·스크립트 접근 보호와 저장할 데이터의 민감성을 각각 확인하세요.