오늘은 RSA 암호화에서 기본으로 사용되는 PKCS#1 v1.5 패딩의 취약점에 대해 자세히 알아보겠습니다!
PKCS#1 v1.5 패딩이란? 🤔
마치 택배 상자에 물건을 안전하게 보내기 위해 완충재를 넣는 것처럼, RSA 암호화에서도 데이터를 안전하게 보내기 위한 '패딩'이 필요합니다.
PKCS#1 v1.5는 가장 오래된 RSA 패딩 방식으로:
- 1993년에 발표
- 구현이 단순하고 이해하기 쉬움
- Java의
Cipher.getInstance("RSA")
에서 기본으로 사용
패딩 오라클 공격이란? 💣
1. 공격 원리
// 취약한 코드 예시
Cipher cipher = Cipher.getInstance("RSA"); // 기본적으로 PKCS#1 v1.5 사용
cipher.init(Cipher.DECRYPT_MODE, privateKey);
try {
byte[] decrypted = cipher.doFinal(ciphertext); // 여기서 패딩 오류 발생 가능
return true; // 패딩이 올바름
} catch (BadPaddingException e) {
return false; // 패딩이 잘못됨
}
2. 공격 과정
- 공격자가 암호문을 수정해서 전송
- 서버의 오류 메시지를 관찰
- 패딩이 올바른지 여부를 통해 원본 메시지를 유추
실제 사례 연구 📱
1. Bleichenbacher의 공격 (1998)
- SSL/TLS 서버를 대상으로 한 최초의 실용적인 공격
- 백만 번의 쿼리로 메시지 복호화 성공
- HTTPS 통신의 보안을 위협
2. ROBOT 공격 (2017)
- 19년 된 Bleichenbacher 공격의 현대판
- Facebook, Paypal 등 주요 사이트 영향
- CVE-2017-17382 등록
안전한 대안 제시 🛡️
1. RSA-OAEP 사용하기
// 안전한 코드 예시
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encrypted = cipher.doFinal(data);
2. 추가 보안 조치
에러 메시지 일반화
try { byte[] decrypted = cipher.doFinal(ciphertext); } catch (Exception e) { throw new CryptoException("Decryption failed"); // 구체적인 에러 숨기기 }
타이밍 공격 방지
// 상수 시간 비교 구현 private boolean constantTimeArrayEquals(byte[] a, byte[] b) { if (a.length != b.length) return false; int result = 0; for (int i = 0; i < a.length; i++) { result |= a[i] ^ b[i]; } return result == 0; }
마치며 🎁
PKCS#1 v1.5는 여전히 많은 시스템에서 사용되고 있지만, 새로운 프로젝트에서는 RSA-OAEP를 사용하는 것이 안전합니다. 보안은 선택이 아닌 필수입니다!
참고문헌:
- "Twenty Years of RSA-OAEP" - Cryptology ePrint Archive, Report 2018/1138
- NIST Special Publication 800-56B Rev. 2
- CVE-2017-17382 상세 보고서
- RSA Laboratories' PKCS #1 v2.2 specification
- "Return of Bleichenbacher's Oracle Threat (ROBOT)" - 2017 USENIX Security Symposium
728x90
'300===Dev Framework > Spring Security' 카테고리의 다른 글
Spring Security 깊이 알아보기 🛡️ (1) | 2024.11.17 |
---|---|
OAuth Introduced (0) | 2024.06.17 |