NearScrub

2026-08-24

스크린샷에서 잘라낸 부분이 파일 안에 그대로 남아 있었다 — aCropalypse 버그가 보여준 것

이 블로그가 다루는 것은 거의 전부 엄밀한 의미의 메타데이터입니다. 이름이 붙은 필드, 의도적으로 기록된 값, 파서가 어디를 봐야 하는지 알고 있는 위치 — EXIF GPS 좌표, docx의 작성자 속성, PDF의 Producer 문자열 같은 것들 말입니다. 2023년 3월에 공개된 aCropalypse 버그는 파일이 전혀 다른 종류의 숨은 짐, 필드 이름조차 없는 짐을 실을 수 있다는 사실을 일깨웠습니다. 파일의 이전 버전에서 남은 데이터가, 모든 일반 뷰어가 읽기를 멈추는 지점 너머에 그대로 남아 있었던 것입니다. 이 경우에 그 남은 데이터는 하필 사용자가 지우려고 했던 바로 그것 — 스크린샷에서 잘라낸 부분 — 이었습니다. 버그 자체는 3년 전에 패치되었습니다. 하지만 그 버그가 만들어낸 파일들은 지금도 채팅 기록과 사진 라이브러리 안에 남아 있고, 그래서 이 이야기는 여전히 알아둘 가치가 있습니다.

실제로는 아무것도 지우지 않았던 자르기

버그는 구글 픽셀 폰의 기본 스크린샷 편집기인 마크업(Markup)에 있었고, 2023년 초 보안 연구자 사이먼 애런스(Simon Aarons)와 데이비드 뷰캐넌(David Buchanan)이 발견했습니다 — 애런스는 단순하게 잘라낸 스크린샷의 파일 크기가 비정상적으로 크다는 점을 수상하게 여겼습니다. 뷰캐넌의 기술 분석글이 원인을 정확히 짚습니다. 마크업이 잘라낸 스크린샷을 원본 파일 위에 저장할 때, 파일을 잘라내는(truncate) 플래그 없이 열었기 때문에, 그의 표현대로 "잘린 이미지가 기록될 때 원본 이미지는 잘려나가지 않았습니다." 자르기를 하면 PNG는 작아지므로, 새 파일은 옛 파일의 앞부분만 덮어썼고 — 그 지점 이후의 원본 데이터 전부가 새 이미지의 공식적인 끝 뒤에 매달린 채 디스크에 남았습니다. 결과물은 어디서 열어도 무해한 잘린 버전으로 보이면서, 물리적으로는 잘리기 전 원본의 대부분을 담고 있는 파일이었습니다. 원인은 2019년 9월에 나온 안드로이드 10의 문서화되지 않은 동작 변경으로 거슬러 올라갑니다. "쓰고 잘라내기"를 의미하던 파일 모드 문자열이 조용히 잘라내기를 멈췄는데, 마크업의 코드는 거기에 맞춰 수정되지 않았던 것입니다. 구글은 2023년 1월에 제보를 받았고 1월 24일에는 내부적으로 수정을 확정했지만, 실제로 픽셀 폰에 도달한 것은 2023년 3월 13일 보안 패치였습니다 — 대략 3년 반 동안의 잘라내기가 영향권에 남은 셈입니다. 이 취약점이 CVE-2023-21036입니다.

"남은 바이트"가 실전에서 얼마나 심각해지는가

PNG의 끝 뒤에 남은 찌꺼기 데이터라면 무해하게 들릴 수도 있습니다. 압축 스트림의 잘린 꼬리이고, 앞부분이 없으니까요. 무해하지 않았습니다. PNG의 압축(zlib)은 일정 간격마다 디코딩 테이블을 다시 기술하기 때문에, 뷰캐넌은 남은 바이트에서 다음 온전한 블록 경계를 찾아 거기서부터 전부 압축을 풀어 원본 이미지의 아랫부분을 복원하는 도구를 만들었습니다. 기억에 남는 것은 그가 직접 보여준 시연입니다. 이베이 주문 확인 화면을 스크린샷으로 찍고, 상품 이미지만 남도록 잘라낸 다음, 파일의 "잘려나간" 나머지에서 자신의 집 주소 전체를 복원해낸 것입니다. 이것이 정확히 최악의 경우의 모양입니다 — 누군가 일부러 잘라낸 영역, 즉 주소, 계좌번호, 대화의 나머지 부분이야말로 남은 데이터가 보존하고 있는 바로 그것입니다.

윈도우에도 같은 버그가 있었다

픽셀 건이 공개되고 며칠 지나지 않아, 연구자들은 마이크로소프트의 스크린샷 편집기 — 윈도우 10의 캡처 및 스케치(Snip & Sketch)와 윈도우 11의 캡처 도구(Snipping Tool) — 에서 동일한 결함을 발견했습니다. 모양도 같습니다. 이미지를 자르고 원본 위에 저장하면, 파일은 공식적인 끝 뒤에 잘려나간 데이터를 그대로 간직합니다. 마이크로소프트는 CVE-2023-28303을 부여하고 마이크로소프트 스토어를 통해 긴급(out-of-band) 수정을 배포했습니다(캡처 및 스케치 10.2008.3001.0, 캡처 도구 11.2302.20.0). 심각도는 낮음(Low)으로 매겼는데, 스크린샷을 찍고, 저장하고, 자르고, 같은 파일 위에 다시 저장하는 흔치 않은 순서가 필요하다는 이유였습니다 — 하지만 그 순서는 전혀 별난 행동이 아닙니다. 편집기가 원본 덮어쓰기를 기본값으로 삼고 있을 때 "보내기 전에 얼른 잘라야지"가 바로 그 모양이니까요.

2023년의 패치가 2021년의 파일을 청소해주지 않는 이유

두 패치 모두 편집기를 고쳤습니다. 어느 패치도 — 당시 보도들이 거듭 강조한 부분이 이것입니다 — 그 편집기들이 이미 만들어낸 파일에는 아무것도 하지 않았습니다. 2021년에 픽셀에서 잘라낸 스크린샷은, 그 뒤로 어디에 복사되었든, 담고 있던 것을 그대로 담고 있습니다. 공유된 사본이 여전히 복원 가능한지는 파일이 기기를 떠난 뒤 무슨 일을 겪었는지에 달려 있었습니다. 업로드된 이미지를 다시 인코딩하는 플랫폼은 새 파일을 만들어내므로 뒤에 붙은 데이터가 사라지지만, 업로드된 바이트를 그대로 저장하고 그대로 내보내는 플랫폼은 그것을 보존했습니다. 파일을 손대지 않고 내보내던 디스코드는 2023년 1월 17일 자체 완화 조치를 넣었습니다 — 하지만 그 전에 업로드된 이미지들은, 어떤 보관함이나 메시지 기록 속 파일들이 그렇듯, 만들어졌을 때의 모습 그대로 남아 있습니다.

영향을 받은 편집기가 디스크에 남긴 것 유효한 잘린 PNG 시그니처 · 청크들 · IEND (공식적인 끝) 원본의 남은 바이트 잘려나간 바로 그 영역 뷰어는 IEND에서 멈추고 잘린 이미지를 보여줍니다. 복원 도구는 계속 읽습니다. 청크를 걸어가며 다시 쓴 뒤 (NearScrub의 PNG 경로) 복사된 청크만, IEND에서 끝남 텍스트/EXIF 청크는 동시에 제거 뒤에 붙은 바이트: 복사되지 않음 (어떤 유지 범위에도 없음) PNG에 한함 — NearScrub의 JPEG 경로는 이미지 데이터부터 파일 끝까지 통째로 복사합니다.
영향을 받은 파일은 유효한 잘린 PNG 뒤에 원본의 남은 데이터가 붙어 있는 형태입니다. 걸어간 청크만 복사하는 다시 쓰기 — NearScrub이 PNG를 처리하는 방식 — 는 구조적으로 뒤에 붙은 바이트를 옮길 방법 자체가 없습니다.

NearScrub이 우연히 닿는 곳 — 그리고 정직하게 밝혀둘 두 가지

NearScrub은 메타데이터 스크러버이고 aCropalypse는 메타데이터가 아니므로, 실제로 무슨 일이 일어나는지 정확히 해둘 필요가 있습니다. NearScrub은 PNG를 처리할 때 파일을 제자리에서 수정하지 않습니다. 시그니처부터 청크 목록을 걸어가며, 제거 목록에 없는 청크를 유지하고, IEND 청크에서 멈춘 뒤, 유지한 범위만 담은 새 파일을 써냅니다. IEND 뒤에 있는 것은 어떤 유지 범위에도 속하지 않으므로, 출력으로 복사될 일이 아예 없습니다. 우리는 이를 scrub-core.js를 상대로 직접 검증했습니다 — IEND 뒤에 바이트를 덧붙인 PNG는 스크럽을 거치면 정확히 깨끗한 파일과 같은 크기로 나옵니다. 그래서 NearScrub을 거친 PNG는 텍스트·EXIF·타임스탬프 청크가 제거된 채로, 그리고 구조적인 부수 효과로 aCropalypse류의 뒤에 붙은 데이터도 없이 나갑니다.

정직하게 밝혀둘 것이 두 가지 있습니다. 첫째, 이것은 PNG에만 해당하는 부수 효과입니다. NearScrub의 JPEG 경로는 압축된 이미지 데이터의 시작부터 버퍼의 끝까지를 한 덩어리로 복사하므로, JPEG 뒤에 붙은 바이트는 스크럽을 살아남습니다. 위에서 말한 우연한 보호는 실재하지만, 형식을 넘어 일반화되지는 않습니다. 둘째, NearScrub의 검사 화면은 뒤에 붙은 데이터를 알려주지 않습니다. 탐지 단계는 청크 목록을 걸어가는 — IEND에서 멈추는 바로 그 — 방식이므로, 텍스트 청크는 하나도 없지만 원본 이미지가 1메가바이트쯤 남아 있는 잘린 스크린샷은 정직하게 "발견된 것 없음"으로 표시됩니다. 그래도 다시 쓰기는 파일을 재구성하고 뒤에 붙은 바이트를 버립니다. 다만 보고서에 그것을 위한 항목이 없을 뿐입니다. "이미지 끝 뒤의 남은 데이터"를 탐지 항목으로 보여주는 스크러버는 합리적인 향후 개선이겠지만, 지금의 보고서가 보여주지 않는 것을 보여준다고 주장하지는 않겠습니다.

이 이야기가 습관에 대해 바꾸는 것

이 블로그의 일관된 조언은, 기기를 떠나는 파일을 마지막으로 그 파일을 건드린 무언가를 믿는 대신 스스로 처리한 결과물로 만들라는 것입니다 — 그리고 aCropalypse는 그 조언의 가장 날카로운 실제 사례입니다. 사람들을 배신한 것이 다름 아닌, 정보를 지우려고 쓴 바로 그 편집기였기 때문입니다. 스크린샷 도구는 최신으로 유지하세요. 여기 나온 두 편집기 모두 고쳐진 지 몇 년이 됐습니다. 하지만 이미 존재하는 파일들 — 아직 채팅 업로드에 남아 있는 2021년의 잘린 스크린샷, 오래된 폴더 속 "가려놓은" 이미지 — 에 대한 해법은 이 도구가 딛고 선 것과 같은 일방통행문입니다. 파서가 실제로 읽은 것만 가지고, 자신의 기기에서, 파일을 다시 짓는 것. 플랫폼의 재인코딩은 그 재구축을 우연히 해주고, 청크를 걸어가는 스크럽은 그것을 설계상 해줍니다. 어느 쪽이든 그 결과물이 절대 아닌 것 하나가 있습니다 — 편집기가 원본 위에 얹어 저장해버린 바로 그 파일입니다.

광고
← NearScrub

이 페이지는 동의하신 경우에만 광고를 표시합니다.