블로그로 돌아가기
여행보안

탑승권 인증샷으로 계정이 털린다: QR 가리기를 직접 측정해봤다

게시일18 min read
공유

티켓 한 장에서 어디까지 나올까

가정이 아니라 기록된 실제 사례부터 시작합니다.

보안 기자 Brian Krebs가 2015년에 분석 글을 썼습니다. Cory라는 독자가 친구가 페이스북에 올린 탑승권 사진을 보고, 캡처해서 바코드를 확대한 뒤 인터넷의 무료 바코드 디코더에 넣었습니다. 몇 초 뒤 그 친구의 마일리지 회원 정보가 손에 들어왔습니다.

문제는 그 다음입니다. Cory는 해당 계정에 묶인 모든 향후 항공편을 조회할 수 있었고, 발권된 승객의 좌석을 변경할 수 있었으며, 앞으로의 항공편을 취소하는 것까지 가능했습니다. 게다가 이 정보는 항공사의 "PIN 분실" 재설정 절차 전반부를 통과하기에 충분했습니다.

친구는 그냥 기분 좋게 탑승권을 올렸을 뿐입니다.

많은 분이 놓치는 지점이 여기입니다. 바코드와 QR 코드는 장식이 아니라 기계가 읽는 데이터 용기입니다. 여러분이 보는 건 흑백 사각형이지만, 스캐너가 보는 건 예약 번호, 이름, 편명, 날짜, 좌석입니다. 이 격차가 위험의 본체입니다.

반만 가리면 소용없다: 어디까지 가려야 안 읽히는지 측정했다

가장 쓰고 싶었던 부분입니다. 잘못된 가리기는 아무것도 안 하는 것보다 위험하거든요 — 안전해졌다고 믿고 올려버리니까요.

QR 코드는 규격상 강력한 오류 정정 기능을 갖고 있습니다. 심볼의 일정 비율이 손상·오염·가려져도 스캐너가 완전한 데이터를 복원하도록 설계돼 있죠. 현실에서는 유용한 성질입니다(접힌 티켓이나 인쇄가 흐린 것도 읽힙니다). 그런데 "반쯤 가리면 되겠지" 하는 상황에서는 이게 그대로 취약점이 됩니다.

그래서 직접 측정해봤습니다.

면적을 얼마나 덮어야 정말 안 읽히나

절차는 재현 가능합니다. Python의 qrcode 라이브러리로 예약 번호와 인증 코드가 포함된 URL을 담은 모의 바우처 QR 코드를 생성하고, 오류 정정 레벨 M(15%), Q(25%), H(30%) 세 가지를 준비했습니다. 각각에 4가지 가리기 방식과 7단계 면적 비율을 적용한 뒤 OpenCV의 QRCodeDetector로 복호를 시도했습니다. 원래 URL을 완전히 복원했을 때만 "읽혔다"로 판정했습니다.

결과는 예상보다 나빴습니다.

가리기 방식 M(15%) 실패 임계 Q(25%) 실패 임계 H(30%) 실패 임계
중앙 검은 사각형 면적 15% 면적 20% 면적 25%
우하단 검은 사각형 면적 20% 면적 25% 면적 25%
가로줄로 긋기 면적 10% 면적 20% 면적 20%
중앙 모자이크 면적 15% 면적 20% 면적 25%

표 읽는 법: 그 비율이 "안 읽히기 시작하는" 경계이고, 그 미만은 전부 읽혔습니다.

기록해둘 만한 발견이 셋입니다.

첫째, 오류 정정 레벨이 높은 티켓은 면적의 5분의 1을 가려도 읽힙니다. H 레벨에서 20%를 가렸을 때 중앙 사각형, 모서리 사각형, 모자이크 세 방식이 모두 복원에 성공했습니다. 캡처 위에 제법 큰 사각형을 칠했다고 생각해도 실제로는 아무것도 가려지지 않은 겁니다.

둘째, 모자이크와 검은 칠의 결과가 거의 완전히 일치했습니다. 세 레벨 모두에서 실패 임계가 동일했습니다. "모자이크면 적어도 안 하는 것보단 낫겠지"라는 직관은 성립하지 않습니다. 안전해지지 않고, 처리한 것처럼 보일 뿐입니다.

셋째, 네 방식 중 가로줄이 가장 효과적이었습니다. M 레벨에서는 높이 10%짜리 가로줄 하나로 안 읽히게 됩니다. 가로줄은 심볼의 폭 전체를 가로지르기 때문에 파괴되는 데이터 블록이 여러 부호화 구간에 분산되는 반면, 한곳에 집중된 사각형은 오류 정정이 가장 강한 범위에 딱 들어가버리기 때문입니다.

솔직히 셋째는 원래 쓰려던 결론과 반대였습니다. "티켓에 줄을 그어도 무효화되지 않는다"는 주의 환기는 맞습니다 — 그건 티켓의 유효성과 데이터 가독성에 대한 지적이니까요. 하지만 "어떤 칠 방식이 스캐너를 더 잘 막느냐"는 질문이라면 이 데이터는 가로줄이 사각형을 이긴다고 답합니다. 실제로 재보지 않으면 모르는 차이입니다.

얼마나 가리느냐보다 어디를 가리느냐

가장 실용적인 발견은 마지막 검증에서 나왔습니다.

QR 코드의 세 모서리에 있는 큰 사각형은 위치 검출 패턴(finder pattern)으로, 스캐너가 방향과 경계를 판정하는 기준입니다. 왼쪽 위 하나를 덮었더니 세 오류 정정 레벨 전부에서 복호에 실패했습니다 — 이 부분은 전체 이미지 면적의 2.0~3.6%에 불과합니다.

바꿔 말하면, 올바른 위치의 2%를 가리는 편이 잘못된 위치의 20%를 가리는 것보다 효과적입니다.

이 검증의 한계도 명시합니다. 사용한 건 OpenCV 디코더, 단일 페이로드, 단일 버전의 QR 코드입니다. 상용 스캐너나 스마트폰 카메라는 구현이 다르고 복원 능력이 더 높을 수 있습니다. 위 임계값은 보장값이 아니라 하한으로 다뤄주세요. 현실의 공격자가 쓰는 디코더는 제 검증 환경보다 관대할 가능성이 높습니다.

실무 기준은 한 줄입니다. 심볼 전체를 불투명하게, 가장자리를 넘어가도록 덮으세요. 모서리만도, 줄 몇 개도, 모자이크도 아닙니다. 도구가 완전한 덮기를 지원하지 않는다면, 최소한 세 위치 검출 패턴 중 하나를 완전히 덮으세요.

깨끗하게 못 가렸다면 안 가린 것과 같습니다.

여행 캡처에 숨은 3개 층

여행에서 찍는 캡처는 위험의 성격도 대처법도 다른 3개 층으로 나뉩니다.

층 주요 출처 새어나가는 것 최악의 경우
1층: 스캔 가능한 교환권 클룩·마이리얼트립 전자 바우처, 공연 티켓, 탑승권 교환권 본체, 예약 번호, 마일리지 계정 단서 먼저 사용됨, 계정 탈취
2층: 문자 식별 정보 아고다·부킹닷컴 예약 확인, 예약 번호, 객실 번호 이름, 숙박일, 숙소 주소 사칭 전화, 사회공학 공격
3층: 이미지에 박힌 데이터 화면을 다른 기기로 촬영한 사진 EXIF의 GPS 좌표, 촬영 시각, 기기 현재 위치나 자택 추정

1층이 가장 급합니다. 전자 바우처의 가치는 코드 자체에 있고, 먼저 스캔당하면 현장에서야 실효를 알게 됩니다. 인터넷에 올라온 공연 티켓 이미지를 훔쳐 변조한 뒤 구매 희망자를 속인 사건도 실제로 있었습니다. 피해자는 올린 본인만이 아닙니다.

2층은 무해해 보이지만 실제로는 사회공학 공격의 연료입니다. 이름과 숙박일과 숙소명이 갖춰지면, 본인인 척 프런트에 전화해 예약을 바꾸게 할 수도, 반대로 숙소인 척 본인에게 전화해 "카드 정보 재확인"을 요구할 수도 있습니다. 이런 사기는 성수기에 늘어납니다.

3층이 가장 많이 놓칩니다. 폰 캡처에는 보통 GPS가 없지만, 화면을 다른 기기로 촬영하면 그 사진에 촬영 당시 좌표가 붙습니다. PC 화면을 누군가에게 보낼 때 흔히 생깁니다.

일행에게 일정을 보여줘야 할 때

현실적으로 가장 곤란한 부분입니다. 일정 정보는 원래 공유가 필요하고, 일행은 집합 시간도 티켓 내용도 숙소 주소도 알아야 합니다.

우선순위는 이렇습니다.

첫 번째 선택은 플랫폼 자체 공유 기능. 클룩, 마이리얼트립, 아고다 등 다수가 예약을 일행에게 공유·양도하는 기능을 갖고 있습니다. 공식 경로라면 교환권의 유효성이 플랫폼 쪽에서 관리되고, 돌아다니는 캡처가 생기지 않습니다.

두 번째는 이미지가 아니라 텍스트를 보내는 것. "9/26 오전 9시, 정문 집합, 티켓은 제가 갖고 있습니다" — 필요한 정보는 다 들어 있고 위험은 없습니다.

세 번째가 보호를 건 이미지 공유. 복잡한 일정표나 지도처럼 화면이 꼭 필요한 경우에는 접근 제어가 되는 방법을 쓰고, 공개 게시물에 붙이지 마세요.

lpic.cc라면 업로드 시 열람 비밀번호를 설정할 수 있어서, 단축 링크가 전달되더라도 비밀번호가 없으면 열리지 않습니다. 비밀번호는 bcrypt로 해싱해 저장하며 평문 비교가 아닙니다. "이 다섯 명에게만 보여주고 싶은" 일정 이미지라면, 단톡방에 던져 자유롭게 유통시키는 것보다 통제가 됩니다.

제한도 먼저 적습니다. 이미지 한 장 8MB까지, 파일은 마지막 열람 후 30일에 삭제, 업로드 시 자동 최적화되므로 원본은 보관되지 않습니다. 그리고 — 비밀번호는 보면 안 되는 사람을 막을 뿐, 열람 권한이 있는 사람이 캡처해서 전달하는 건 막지 못합니다. 어떤 공유 수단에도 이 천장이 있습니다. 만능이라고 생각하지 마세요.

마지막 방어선은 결국 이겁니다. 정말 민감한 교환권은 애초에 이미지 파일로 만들지 않는 것.

자주 묻는 질문

Q1: 탑승권을 한참 전에 올렸습니다. 지금 지워도 소용 있나요?

삭제하면 이후 노출은 줄지만, 아무도 가져가지 않았다고 가정할 수는 없습니다. 그보다 중요한 게 둘입니다. 해당 항공사 계정의 비밀번호와 보안 질문 답을 즉시 변경하고, 향후 예약에 무단 변경이 없는지 확인하는 것. Krebs 사례에서 공격자가 가장 먼저 할 수 있었던 게 좌석 변경과 항공편 취소였습니다.

Q2: 클룩 바우처를 남이 스캔했다면 현장에서 입장할 수 있나요?

티켓 종류에 따라 다릅니다. 1회용 교환권이 먼저 사용됐다면 현장에서는 사용 완료로 표시됩니다. 즉시 플랫폼 고객센터에 연락해야 하지만 결과가 보장되지는 않고, 성수기에는 대응도 느립니다. 예방이 압도적으로 확실한 영역입니다.

Q3: QR 코드에 모자이크를 걸면 충분한가요?

부족하고, 제가 측정했습니다. 세 오류 정정 레벨 전부에서 모자이크와 검은 칠의 실패 임계가 동일했습니다 — 높은 레벨의 티켓은 면적의 25%를 가려야 안 읽힙니다. 코드 영역 전체를 불투명하게 덮거나, 더 확실하게는 촬영 시점에 물리적으로 가리세요.

Q4: 예약 확인에 예약 번호와 이름만 있어도 위험한가요?

위험합니다. 이름과 예약 번호 조합은 일부 플랫폼에서 예약 상태 조회에 충분합니다. 거기에 숙박일이 더해지면 사회공학 공격의 재료로는 충분합니다. 실제 사례에서 반복되는 패턴은, 공격자가 비밀번호를 필요로 하지 않고 상담원을 설득할 만큼의 조각 정보만 모은다는 것입니다.

Q5: 여행 사진 자체는 어떤가요?

위험의 성격이 다릅니다. 사진 쪽의 주된 문제는 EXIF의 GPS 좌표입니다. 다수의 SNS는 업로드 시 EXIF를 제거하지만, 클라우드 드라이브나 "원본 파일 전송" 경로에서는 온전히 보존되는 게 보통입니다. 각 서비스의 처리 방식은 8개 이미지 서비스의 EXIF 보존을 항목별로 검사한 글에 정리했습니다.

참고 자료

#QR 코드#탑승권#여행 프라이버시#전자 바우처#계정 탈취#정보 유출#보안 검증
K

작성자

Kevin Wu

보안 컨설턴트

개인정보 보호와 데이터 보안에 주목하여 이미지 공유의 숨겨진 위험을 피할 수 있도록 돕습니다.