2차 세계대전 암호 분석에서 얻은 교훈을 웹 애플리케이션에 적용할 수 있는 것은 아닙니다. 하지만 오늘은 바로 그 일을 해보려고 합니다. 실제로 앨런 튜링이 당시 가장 강력한 암호화 도구였던 에니그마 머신을 해독하는 데 사용한 것과 동일한 방법으로 가장 강력한 현대 암호화 도구 중 하나라도 구현자가 메시지 전송에서 튜링이 발견한 것과 같은 실수를 저지른다면 어떻게 무력화시킬 수 있는지 살펴보겠습니다.
2차 세계대전에서 연합군이 추축국을 이기는 데 도움이 되었던 문제를 어떻게 피했는지 최근 제가 평가한 API를 살펴보겠습니다.
전자상거래 API: 꿀이 듬뿍 담긴 예쁜 냄비
오늘 살펴볼 예시는 이커머스 회사의 결제 수락을 위한 API입니다. 악의적인 공격자가 신용카드 결제 API보다 더 가치 있는 공격 표적은 많지 않습니다. 그래서 이 회사는 결제 처리를 위해 제출되는 모든 신용카드 정보를 암호화할 수 있는 공개 키를 전 세계에 노출하기로 결정했습니다.
이 양식으로 제출되는 모든 데이터는 암호화되며 일반 텍스트로 전송되지 않습니다. 이는 카드 번호뿐만 아니라 여기에 있는 모든 데이터를 공격으로부터 보호하는 것이 중요하기 때문입니다. 만료일과 CVV는 특정 결제 수단을 고유하게 만드는 패키지의 일부이므로 이 회사는 이를 모두 암호화했습니다. 이 회사는 이 중 어떤 것도 일반 텍스트로 전송하지 않습니다.
다음은 찰스 프록시를 사용하여 중간자 트래픽을 캡처한 샘플 요청이 유선을 통해 전달되는 모습입니다:
이 예제에서 두 개의 해시 값, 즉 paymentHash와 cvvHash가 있음을 알 수 있습니다. 이 두 값에 포함된 데이터에 대해 생각해 보겠습니다.
paymentHash의 경우, 이 API에서 사용하도록 공개된 공개 키를 사용하여 암호화된 16자리 신용 카드 번호가 있습니다. 물론 암호화에 사용할 수 있는 값에는 많은 변화가 있을 것입니다.
cvvHash의 경우, 전혀 같은 상황이 아닙니다! CVV는 3자리 숫자에 불과합니다. 세 자리 조합만 암호화하면 공격자는 1,000개의 서로 다른 값(세 자리 각각에 대해 10개의 값)으로 구성된 완전한 사전을 만들 수 있습니다. 이 사전을 사용하면 이 API를 통해 전송된 모든 카드의 CVV를 찾을 수 있습니다. 다행히도 제 고객은 알려진 일반 텍스트 공격을 피하는 방법을 알고 있었고, 나치를 무너뜨린 것과 같은 공격을 피하기 위해 이미 무작위 패딩을 구현하고 있었습니다.
수수께끼 풀기
에니그마 기계는 메시지를 암호화하는 구조가 매우 복잡하고 설정이 자주 변경되었기 때문에 해독하기가 매우 어려웠습니다. 하지만 이 기계가 군용 메시지에 사용되었기 때문에 블레클리 파크의 튜링 팀은 많은 메시지에서 예상할 수 있는 텍스트를 찾기 시작했습니다.
독일군이 자주 보내는 메시지 유형 중 하나는 일기예보였으며, 모든 메시지에서 같은 위치에 "날씨"를 뜻하는 독일어 단어와 함께 알려진 기상 상태를 포함했습니다. 또 다른 예로는 많은 메시지가 "히틀러 만세"로 끝나고 일부 운영자는 표준 인사말을 사용했습니다. 이러한 사례를 통해 각 날짜의 일반 텍스트와 설정 중 일부를 확인할 수 있었습니다.
이러한 유형의 암호화 취약점은 가능한 값의 수가 매우 적기 때문에 이 전자상거래 회사에서 CVV에 무작위 패딩을 사용하지 않았다면 존재할 수 있는 취약점입니다.
같은 실수 피하기
이 회사는 무작위 패드를 사용하여 동일한 CVV를 가진 두 가지 결제 수단이 전송되는 내용에 대해 아무것도 드러나지 않도록 했습니다. 다음은 패드를 사용하여 동일한 값인 '777'을 다른 값으로 암호화할 수 있는 몇 가지 예시입니다:
$ echo -n 777 | openssl rsautl -inkey public_key.pem -pubin -pkcs |
보시다시피 위에서 실행한 명령은 모두 동일하지만 RSA 암호화 표준으로 인해 출력되는 값은 모두 완전히 다릅니다.
좋은 암호화 알고리즘만으로는 충분하지 않습니다.
이 예시를 통해 좋은 암호화 체계를 구축하는 것만으로는 충분하지 않다는 것을 이해하실 수 있을 것입니다. 고도로 정교한 암호화 알고리즘을 사용하더라도 동일한 입력을 반복해서 사용하면 안전하게 전송하려는 데이터가 노출될 수 있습니다. 특히 결제 정보를 다룰 때는 전송되는 값을 쉽게 추측할 수 없도록 하는 것이 매우 중요합니다.
패딩이 중요한 또 다른 예는 비밀번호 저장입니다. 개발자는 사용자가 제출하는 비밀번호를 읽을 수 없도록 하기 위해 우수한 단방향 해시 함수를 사용해야 한다는 것을 알고 있습니다. 이를 위해 개발자는 비밀번호를 해시하기 전에 임의의 문자열( salt )을 추가해야 합니다.
결론
웹 애플리케이션에 보안을 구축하는 것은 매우 중요한 작업입니다. 사용자의 민감한 데이터가 쉽게 해독되지 않도록 해야 고객의 신뢰를 쌓고 비즈니스의 수명을 보장할 수 있습니다. 결국, 자신의 사이트에서 고객의 결제 정보가 유출되었다는 사실이 언론에 보도되는 것을 원하는 사람은 아무도 없습니다. 똑같은 값을 반복해서 암호화하지 않도록 할 수 있다면 아주 기본적인 오류를 방지하고 고객의 데이터를 안전하게 보호할 수 있습니다.
보안 모범 사례에 대한 자세한 내용은 Linode의 광범위한 보안 가이드를 확인하세요!
내용