
주소 오염: 당신이 엉뚱한 것을 복사하기만 하면 되는 공격
암호화폐 사용자를 노리는 공격은 대개 당신이 실수를 저지르기를 요구합니다. 링크를 누르거나, 시드 문구를 양식에 입력하거나, 읽지도 않은 것을 승인하거나. 주소 오염은 그보다 덜한 것을 요구합니다. 당신이 자기 거래 내역에서 주소 하나를 복사하기만 하면 됩니다.
악성코드도 없고, 피싱 사이트도 없고, 속여서 받아내야 할 서명도 없습니다. 공격자가 하는 일이라고는, 그럴듯해 보이는 문자열 하나를 당신이 나중에 손을 뻗을 자리에 놓아두는 것뿐입니다.
어떻게 작동하나
이것을 가능하게 만드는 것부터 시작합시다. 아무도 주소를 읽지 않습니다. 비트코인이나 이더리움 주소는 의미 없는 서른몇 자의 base58 또는 16진수이고, 눈으로 판별할 수 있는 검사합도 없으며, 머리에 담아둘 이유도 없습니다. 그래서 모든 지갑과 블록 탐색기와 거래소가 표시용으로 그것을 줄입니다 — 0x8f3C…9A063 — 그리고 모든 사용자는 보이는 양 끝을 확인하고 가운데는 건너뛰는 법을 익힙니다.
그 습관이 공격 표면의 전부입니다.
공격자는 무차별 대입으로 주소를 만들어냅니다. 당신이 실제로 쓰는 주소 — 대개 최근에 돈을 보낸 주소 — 와 앞뒤 몇 글자가 겹치는 것이 나올 때까지요. 이것은 쌉니다. 키 쌍 생성은 빠르고, 앞의 네 글자와 뒤의 네 글자쯤 맞추는 데는 평범한 하드웨어로 몇 초면 됩니다. 아무도 무엇을 깨뜨리고 있지 않습니다. 그저 어떤 숫자가 낯익어 보일 때까지 주사위를 굴릴 뿐입니다.
그다음 그 주소를 당신의 내역 안으로 들여보냅니다. 흔한 방법들:
더스팅. 닮은 주소에서 아주 작은 금액 — 몇 사토시, 어떤 토큰의 1센트도 안 되는 조각 — 을 보냅니다. 평범한 입금 거래이므로 다른 어떤 거래와도 똑같이 당신의 내역에 내려앉습니다. UTXO 체인에서는 그 더스트가 지갑 안의 쓸 수 있는 코인이 되기도 하는데, 이는 나중에 문제가 됩니다.
0원 전송. EVM 체인에서 토큰 0개짜리 ERC-20 transfer도 유효한 거래입니다. 공격자는 당신 주소에서 자기 닮은꼴 주소로 0개를 보내고, 일부 인터페이스는 그것을 당신이 한 출금 결제처럼 그립니다. 이제 당신의 내역은, 고른 적도 없는 주소로 당신이 보낸 것처럼 보여줍니다.
가짜 이벤트. 악의적인 토큰 컨트랙트는 일어난 적 없는 Transfer 이벤트를 내보낼 수 있습니다. 이벤트 로그를 믿는 탐색기와 지갑은 그것을 표시합니다. 아무것도 움직이지 않았습니다. 그 기록은 그냥 거짓말입니다.
그러고 나서 기다립니다. 며칠, 때로는 몇 달을. 이 공격이 결실을 맺는 순간은, 당신이 같은 상대에게 다음번 돈을 보내려고 내역을 뒤지며 "지난번에 쓴 그 주소"를 찾다가 엉뚱한 줄을 복사할 때입니다. 둘 다 0x8f3C…9A063처럼 보입니다. 당신은 양 끝을 확인합니다. 양 끝은 맞습니다.
흔한 조언이 버티지 못하는 이유
"주소는 늘 두 번 확인하라"가 표준 조언이고, 그것만으로는 실패합니다. 확인하는 것이야말로 이 공격이 예상한 행동이기 때문입니다. 당신은 확인했습니다. 지갑이 보여준 여섯 글자를 기억 속 여섯 글자와 견주었고, 그것들은 똑같았습니다 — 공격자가 똑같게 만들었으니까요.
검증은 비교 대상을 위조하는 값이 비쌀 때만 작동합니다. 네 글자나 여섯 글자를 맞추는 데는 몇 초면 됩니다. 열여섯 글자를 맞추는 값은 훔쳐낼 것의 가치보다 커집니다. 게임의 전부는 당신의 습관이 그 곡선의 어느 쪽 끝에 앉아 있느냐입니다.
UTXO 체인에는 두 번째 함정이 있습니다. 그 더스트 결제는 이제 지갑 속 코인이고, 지갑이 입력을 자동으로 합친다면 나중 거래에 쓸려 들어갈 수 있습니다 — 더스트를 받은 주소를 당신의 나머지 코인과 이어버리면서요. 이는 도난이라기보다 사생활 문제이지만, 더스트를 정리하지 말고 무시해야 하는 이유이기도 합니다.
실제로 지켜주는 것
절대로 거래 내역에서 주소를 가져오지 마십시오. 이것이 유일하게 의미 있는 변화입니다. 당신의 내역은 무슨 일이 있었는지에 대한 기록이지, 당신이 누구를 신뢰하는지에 대한 목록이 아닙니다 — 그리고 세상 누구나 그곳에 쓸 수 있습니다. 주소는 상대방에게서, 사칭을 알아차릴 수 있는 경로로 받거나, 당신이 직접 채워 넣은 주소록에서 가져오십시오.
주소를 통째로 견주거나, 주소 전체를 요약한 무언가를 견주십시오. 마흔두 글자를 다 읽는 것은 비현실적입니다. 아이덴티콘 — 문자열 전체로부터 결정적으로 생성되는 작은 그림 — 을 견주는 것은 현실적입니다. 가운데 어디든 다른 닮은꼴은 눈에 띄게 다른 그림을 만들어내니까요. 당신의 인내가 하지 않을 일을 눈이 대신 해줍니다.
저장해둔 연락처를 쓰십시오. 한 번 검증한 출처에서 한 번 저장해둔 주소는 나중에 오염될 수 없습니다. 주소록은 바로 그것을 위해 있고, SSP가 연락처를 서버가 아니라 당신 기기에 두는 이유이기도 합니다. 연락처 목록은 다른 누구도 편집할 수 없을 때에만 믿을 만합니다.
금액이 크거나 처음 보내는 상대에게는 시험 송금을 하십시오. 작은 금액을 보내고, 다른 경로로 수령을 확인한 뒤, 나머지를 보내는 겁니다. 수수료 탓에 성가시지만, 잃으면 속이 쓰릴 결제에는 여전히 옳은 방법입니다.
더스트는 무시하십시오. 쓰지 말고, "정리"하지도 말고, 사생활이 중요하다면 자동 합치기도 조심하십시오.
SSP는 이에 대해 무엇을 하나
주소 오염은 보안 문제인 만큼이나 그리기의 문제입니다. 그래서 답의 일부는 주소가 어떻게 그려지느냐에 살고 있습니다.
SSP는 많은 인터페이스가 쓰는 서너 글자가 아니라 앞 여섯 글자와 뒤 여섯 글자로 주소를 줄입니다 — 0x8f3C4b…9A0631. 이것은 미관상의 선택이 아닙니다. 글자 하나가 늘 때마다 일치를 만들어내는 무차별 대입 비용은 곱절로 뛰고, 보이는 열두 글자는 그럴듯한 닮은꼴을 손쉬운 생성의 사정거리 바깥으로 훌쩍 밀어냅니다.
가운데는 지워지는 것이 아니라 흐려집니다. 펼친 형태에서 지갑은 문자열 전체를 보여주되 양 끝을 굵게, 가운데를 옅은 색으로 칠합니다. 그래서 공격자가 당신이 건너뛰기를 기대하는 그 부분이, 무엇이든 숨길 수 있는 말줄임표로 바뀌는 대신 화면에 물리적으로 남아 있습니다.
같은 코드가 두 앱에서 돌아갑니다. SSP Wallet의 splitAddressForDisplay는 SSP Key의 것을 그대로 옮긴 것이고, 브라우저에서든 휴대폰에서든 주소가 똑같아 보이도록 의도적으로 동일하게 유지됩니다. 이것이 중요한 이유는 SSP가 두 기기에서 거래를 두 번 보여주기 때문입니다 — 두 번째 눈길은 두 화면이 같은 것을 같은 방식으로 그릴 때에만 진짜 검사가 됩니다. 줄이는 방식이 둘로 갈리면, 불일치가 그 차이 속에 숨어버릴 수 있습니다.
SSP Key의 승인 화면에서는 수신자가 줄인 텍스트 옆에 전체 주소로부터 생성된 아이덴티콘과 함께 표시되고, 그것을 누르면 전체 주소가 선택 가능한 텍스트로 펼쳐집니다. 문자열 중간의 바꿔치기를 무너뜨리는 것이 바로 이 아이덴티콘입니다. 공격자는 당신의 앞뒤 글자는 맞출 수 있어도, 모든 글자에서 파생된 그림을 맞추려면 훨씬 어려운 문제를 풀어야 합니다.
이 가운데 무엇도 보장은 아닙니다. 오염된 주소를 붙여넣고 두 기기에서 모두 승인한다면 SSP는 그것에 서명합니다 — 그것이 바로 당신의 결정을 의심하는 수탁자가 아니라, 당신이 통제하는 지갑이라는 말의 뜻입니다. 2-of-2 멀티시그는 다른 사람이 당신의 코인을 쓰는 것을 막습니다. 당신이 일부러 엉뚱한 사람에게 보내는 것은 막지 못합니다. 당신이 직접 움직이게 만들어 작동하는 모든 공격이 그렇듯, 방어는 서명 도중이 아니라 서명 이전에 내려앉아야 합니다.
짧게 줄이면
주소 오염이 통하는 이유는 당신이 마흔두 글자가 아니라 여섯 글자를 견주기 때문이고, 공격자는 그것이 어느 여섯 글자인지 알기 때문입니다. 방어는 더 꼼꼼해지는 것이 아닙니다 — 공격자가 쓸 수 있는 곳에서 절대 주소를 가져오지 않는 것, 그리고 당신이 건너뛸 부분을 다시 눈앞에 놓아주는 도구를 쓰는 것입니다.


