사전 피싱
개념

피싱

gabury1고친 사람 github-actions[bot]

피싱은 믿을 만한 곳인 척 꾸민 메시지로 사람을 속여 비밀번호 같은 정보를 스스로 내놓게 만드는 공격입니다. 은행을 사칭한 메일이 진짜와 똑같이 생긴 가짜 로그인 화면으로 이끄는 것이 흔한 예입니다. 서버의 빈틈 대신 사람의 판단을 노립니다. 그래서 암호화와 서버 보안을 다 갖춘 서비스도 이 공격에 뚫립니다.

쉽고 빠른 이해

가짜 로그인 화면으로 비밀번호를 받아 가는 공격입니다. 「계정이 잠겼습니다」라는 메일 속 링크를 누르면 늘 쓰던 서비스와 똑같은 화면이 뜹니다. 거기 넣은 비밀번호는 공격자에게 갑니다.

이 공격에 따로 이름이 붙은 이유는 서버를 지키는 장치로는 잘 안 막히기 때문입니다. 공격자는 훔친 비밀번호로 평범하게 로그인합니다. 서버 쪽에서 보면 주인이 들어온 것과 구별이 안 됩니다.

어떻게 도나:

  1. 공격자가 진짜 서비스를 흉내 낸 메시지를 보냅니다
  2. 받은 사람이 링크를 눌러 가짜 화면에 비밀번호를 넣습니다
  3. 공격자가 그 비밀번호로 진짜 서비스에 들어갑니다

주소를 잘 보라고 가르치는 것만으로는 모자랍니다. 그래서 로그인에 쓰는 키를 진짜 사이트 주소에 묶어 두는 방식을 씁니다. 가짜 주소에서는 그 키가 아예 쓰이지 않습니다.

이 방식의 대가는 절차가 늘어나는 것입니다. 로그인할 기기를 미리 등록해야 합니다. 기기를 잃었을 때 계정을 되찾는 절차도 따로 필요합니다.

상세

이 절은 피싱이 한 번 지나가는 단계를 먼저 봅니다. 이어서 가짜를 진짜처럼 꾸미는 수법을 봅니다. 그다음 암호화된 연결과 브라우저의 보호 장치로는 왜 못 막는지, 무엇이 막는지를 봅니다.

길 건너의 가짜 창구

손님 집에 은행 이름이 찍힌 편지가 온다고 해 봅시다. 계좌가 곧 막히니 적힌 창구로 와서 확인하라는 내용입니다. 적힌 곳은 은행 길 건너에 같은 간판을 단 가게입니다. 손님은 그 창구로 걸어 들어가 통장과 비밀번호를 제 손으로 건넵니다.

진짜 은행의 금고와 창구는 아무 일도 겪지 않았습니다. 손님이 스스로 가짜 창구를 찾아갔을 뿐입니다.

피싱이 노리는 것도 금고가 아니라 사람의 판단입니다. 사람의 믿음과 습관을 노려 보안을 뚫는 수법을 통틀어 사회공학이라고 부릅니다. 피싱은 그 가운데 가짜 메시지로 속이는 갈래입니다.

이름은 낚시(fishing)에서 왔습니다. 미끼를 널리 던져 두고 무는 사람을 기다린다는 뜻입니다.

한 번의 피싱이 지나가는 단계

가장 흔한 경로는 전자메일로 시작해 가짜 로그인 화면에서 끝납니다. 아래 그림은 공격자가 비밀번호를 받아 진짜 서비스에 들어가기까지를 순서대로 보입니다.

sequenceDiagram
    participant A as 공격자
    participant U as 사용자
    participant F as 가짜 사이트
    participant R as 진짜 사이트
    A->>U: "계정이 잠겼습니다" 메일과 링크
    U->>F: 링크를 눌러 접속
    F-->>U: 진짜와 똑같은 로그인 화면
    U->>F: 아이디와 비밀번호
    F->>A: 받은 비밀번호를 넘김
    A->>R: 그 비밀번호로 로그인

사용자가 하는 일은 모두 평소와 같습니다. 링크를 누릅니다. 익숙한 화면에 늘 넣던 값을 넣습니다. 달라진 것은 주소창에 뜬 주소 하나뿐입니다.

마지막 단계에서 공격자는 받은 비밀번호를 그대로 넣습니다. 진짜 사이트는 맞는 아이디와 비밀번호를 받았으니 들여보냅니다. 서버의 접속 기록에도 주인이 들어온 것과 똑같이 남습니다.

진짜처럼 보이게 꾸미는 수법

속임은 두 군데서 일어납니다. 하나는 메시지의 보낸 사람입니다. 다른 하나는 링크가 여는 사이트입니다.

전자메일의 보낸 사람 칸은 보내는 쪽이 마음대로 적을 수 있습니다. 받는 쪽이 따로 확인하지 않으면 은행 이름이 적힌 메일은 은행에서 온 것처럼 보입니다. 이 확인 장치는 뒤의 「백엔드가 피싱을 돕게 되는 경우」에서 봅니다.

가짜 사이트는 화면을 베끼기 쉽습니다. 진짜 로그인 페이지를 내려받아 제 서버에 올리면 겉모양이 똑같아집니다. 그러면 가짜를 알아볼 단서는 주소밖에 남지 않습니다.

베끼는 화면으로는 다른 서비스 계정으로 로그인하게 해 주는 연동 로그인 화면이 자주 쓰입니다. 계정 하나를 얻으면 그 계정으로 로그인하는 서비스 전부에 들어갈 수 있기 때문입니다. 사용자도 여러 서비스에서 같은 화면을 자주 보아 그 화면에 익숙합니다.

공격자는 그 주소도 비슷하게 꾸밉니다. 주소에서 사이트의 주인을 가르는 것은 도메인 이름입니다.

도메인 이름은 서버에 붙인, 사람이 읽는 이름입니다. 점으로 나뉜 조각을 오른쪽 끝부터 읽습니다. 오른쪽 끝 조각들을 등록한 사람은 그 왼쪽에 무엇이든 붙일 수 있습니다.

아래는 진짜 주소 하나와 그것을 흉내 낸 가짜 셋입니다.

https://bank.example/login      // 진짜
https://bamk.example/login      // 가짜
https://bank.example.evil.test  // 가짜
https://bank-login.test/        // 가짜

세 가짜는 서로 다른 방법으로 눈을 속입니다. 아래 표가 하나씩 짚습니다.

가짜 주소 속이는 방법
bamk.example 글자 하나를 비슷한 글자로 바꿨습니다. 잘못 치기 쉬운 이름을 미리 등록해 두는 수법이 타이포스쿼팅입니다
bank.example.evil.test 진짜 이름을 왼쪽에 붙였습니다. 주인은 오른쪽 끝의 evil.test 입니다
bank-login.test 진짜 이름에 그럴듯한 낱말을 붙여 새 이름을 지었습니다

눈으로는 아예 못 가르는 가짜도 있습니다. 도메인 이름에는 영문 말고 다른 문자도 쓸 수 있습니다. 라틴 문자 a 와 모양이 같은 키릴 문자를 섞으면 화면에서는 똑같은 주소가 됩니다. 이 수법이 동형 문자 공격입니다.

메시지의 문구도 수법입니다. 계정이 곧 잠긴다거나 결제가 실패했다는 말로 서두르게 만듭니다. 서두르는 사람은 주소를 들여다보지 않습니다.

자물쇠가 켜져도 가짜인 이유

많은 사람이 주소창의 자물쇠를 안전하다는 표시로 읽습니다. 자물쇠는 HTTPS 로 연결됐다는 표시입니다. HTTPS 는 HyperText Transfer Protocol Secure 의 줄임말입니다. 브라우저와 서버 사이의 통신을 잠그는 방식입니다.

자물쇠가 보증하는 것은 두 가지입니다. 오가는 내용을 남이 못 읽는다는 것, 그리고 상대 서버가 주소창에 뜬 도메인 이름의 주인이 맞다는 것입니다. 그 도메인이 사용자가 가려던 곳인지는 보증하지 않습니다.

공격자도 자기 도메인의 인증서를 받을 수 있습니다. 인증서는 서버가 그 도메인의 주인임을 믿을 만한 제3자가 보증해 주는 문서입니다. bamk.example 의 주인은 bamk.example 의 인증서를 정상 절차로 받습니다. 가짜 사이트에도 자물쇠가 똑같이 켜집니다.

HTTPS 가 막는 것은 통신 경로 가운데 누가 끼어드는 일입니다. 통신하는 두 쪽 사이에 끼어 말을 엿듣거나 옮기는 공격을 중간자 공격이라고 부릅니다. 피싱은 경로에 끼어들지 않습니다. 사용자가 제 발로 공격자의 서버에 접속합니다. HTTPS 는 그 연결을 성실하게 잠급니다.

브라우저의 격리로도 못 막는 이유

브라우저는 사이트끼리 서로의 데이터를 못 건드리게 떼어 놓습니다. 사이트마다 프로세스를 따로 돌려 떼어 놓는 장치가 사이트 격리입니다. 이 장치는 한 사이트의 코드가 다른 사이트의 내용을 몰래 읽는 것을 막습니다.

피싱에는 그런 몰래 읽기가 필요 없습니다. 가짜 사이트는 사용자가 제 페이지에 직접 넣어 준 값을 받을 뿐입니다. 브라우저가 보기에는 사용자가 한 사이트의 로그인 양식을 제출한 평범한 일입니다.

일회용 숫자까지 넘어가는 경우

비밀번호 하나만으로는 불안하니 로그인할 때 하나를 더 확인하는 방식이 널리 쓰입니다. 이것을 다중 인증이라고 부릅니다. 비밀번호가 새어 나가도 두 번째 확인이 남아 있으니 계정이 바로 넘어가지 않습니다.

두 번째 확인으로 흔히 쓰는 것은 휴대폰 앱이나 문자로 받은 몇 자리 숫자입니다. 이런 숫자를 일회용 비밀번호라고 합니다. 짧은 시간만 유효합니다.

피싱은 이 숫자도 받아 갑니다. 가짜 사이트는 받은 값을 곧바로 진짜 사이트에 넣어 봅니다. 진짜 사이트가 무언가를 더 물으면 사용자에게 똑같이 되묻습니다. 아래 그림이 그 중계입니다.

sequenceDiagram
    participant U as 사용자
    participant F as 가짜 사이트
    participant R as 진짜 사이트
    U->>F: 아이디와 비밀번호
    F->>R: 같은 값을 넣는다
    R-->>F: 확인 숫자를 넣으라
    F-->>U: 확인 숫자를 넣으라
    U->>F: 확인 숫자
    F->>R: 같은 숫자를 넣는다
    R-->>F: 로그인 성공과 세션 쿠키

숫자가 짧은 시간만 유효해도 소용이 없습니다. 공격자는 그 시간 안에 중계를 끝내면 됩니다. 가짜 사이트가 사용자와 진짜 사이트 사이에서 양쪽 말을 옮깁니다. 앞에서 본 중간자 공격이 피싱에 겹친 것입니다.

그림 마지막 줄의 세션 쿠키는 로그인한 상태를 기억하려고 브라우저에 맡겨 두는 값입니다. 이 값을 쥔 쪽은 다시 로그인하지 않고도 그 계정으로 요청을 보냅니다. 중계가 끝나면 이 값이 가짜 사이트 손에 남습니다.

주소에 묶인 로그인

사람에게 주소를 잘 보라고 가르치는 방어는 한계가 있습니다. 동형 문자처럼 눈으로 못 가르는 가짜가 있습니다. 서두르게 만드는 문구는 주의를 흩뜨립니다. 이 한계를 넘으려고 주소를 가르는 일을 사람 대신 기계에 맡깁니다.

일회용 숫자가 중계되는 이유는 어느 사이트에 넣든 같은 숫자이기 때문입니다. 확인 값을 사이트 주소마다 다르게 만들면 중계가 무너집니다. 가짜 사이트에서 만든 확인 값은 진짜 사이트에서 통하지 않습니다.

WebAuthn은 그렇게 만든 로그인 방식입니다. 이름은 Web Authentication 의 줄임말입니다. 비밀번호를 넣는 대신 기기 안에 든 키로 서명해 로그인합니다. 흔히 패스키라고 부르는 로그인이 이 방식입니다.

이 키는 공개 키 암호의 키 한 쌍입니다. 사이트에 가입할 때 기기가 그 사이트 전용 쌍을 만듭니다. 한쪽인 비밀 키는 기기 밖으로 나가지 않습니다.

다른 쪽인 공개 키는 사이트에 맡깁니다. 공개 키로는 서명이 맞는지 확인만 할 수 있습니다.

로그인할 때 브라우저는 지금 열린 페이지의 도메인 이름을 봅니다. 그리고 그 도메인에 등록된 키만 쓰게 합니다. 그래서 bamk.example 에서는 bank.example 의 키가 아예 쓰이지 않습니다. 중계해서 넘길 값이 처음부터 생기지 않습니다.

오리진은 주소 앞부분의 프로토콜과 호스트 이름과 포트를 묶은 것입니다. 도메인 이름에 프로토콜과 포트까지 더해 사이트를 더 잘게 가르는 단위입니다. 서명에는 로그인한 페이지의 오리진이 함께 담깁니다. 진짜 사이트는 브라우저의 제한을 믿기만 하지 않고, 서명에 담긴 오리진이 제 것인지 한 번 더 봅니다.

비밀번호 관리자도 비슷한 일을 조금 합니다. 저장해 둔 비밀번호를 등록한 도메인에서만 자동으로 채웁니다. 늘 채워지던 칸이 비어 있으면 그것이 경고가 됩니다.

이 방식의 대가는 키를 담은 기기에 로그인이 걸린다는 점입니다. 그 기기를 모두 잃으면 로그인할 길이 막힙니다. 서비스는 기기를 여럿 등록하게 하거나 계정을 되찾는 절차를 따로 둡니다. 되찾는 절차가 허술하면 공격자는 그쪽을 노립니다.

백엔드가 피싱을 돕게 되는 경우

피싱은 사용자 쪽 문제로 보이기 쉽습니다. 그런데 서버를 짓는 쪽의 설정이 공격자에게 재료를 대 주기도 합니다. 흔한 것이 셋입니다.

첫째는 되돌려 보내기 기능입니다. 로그인 뒤 원래 보던 페이지로 사용자를 돌려보내는 ?next= 같은 매개변수가 흔한 예입니다. 이 기능이 목적지를 가리지 않으면 오픈 리다이렉트가 됩니다.

오픈 리다이렉트가 있으면 공격자는 진짜 도메인으로 시작하는 링크를 만듭니다.

https://bank.example/go?to=evil.test

사용자는 앞부분의 bank.example 만 보고 누릅니다. 진짜 서버가 그 사용자를 evil.test 로 보냅니다. 막으려면 돌려보낼 곳을 자기 도메인 안이나 미리 정한 목록으로 묶어 둡니다.

둘째는 다른 서비스 계정으로 로그인하게 해 주는 연동입니다. 이런 연동의 규약이 OpenID Connect입니다. 여기서는 되돌려 보내기가 로그인 결과를 싣고 갑니다. 돌려보낼 주소를 느슨하게 맞추면 그 로그인 결과가 공격자의 주소로 실려 갑니다.

그래서 돌려보낼 주소를 미리 등록해 둡니다. 그리고 등록한 주소와 글자까지 같은 곳에만 보냅니다.

셋째는 메일 발신 도메인의 인증을 안 걸어 둔 경우입니다. 앞에서 본 것처럼 보낸 사람 칸은 아무나 적을 수 있습니다. 이것을 막는 기록은 DNS에 올립니다. DNS 는 Domain Name System 의 줄임말입니다. 도메인 이름을 서버 주소로 바꿔 주는 체계입니다. 도메인 주인이 여기에 기록을 올려 두면 받는 쪽이 진짜 발신을 가려낼 수 있습니다.

그 기록이 세 가지입니다. 아래 표는 각각이 받는 쪽에 무엇을 알려 주는지 짝지었습니다.

이름 하는 일
SPF(Sender Policy Framework) 이 도메인으로 메일을 보내도 되는 서버 목록을 적어 둡니다
DKIM(DomainKeys Identified Mail) 보내는 서버가 메일에 전자 서명을 붙입니다. 확인에 쓸 공개 키를 이 기록에 적어 둡니다
DMARC(Domain-based Message Authentication, Reporting and Conformance) 앞의 두 확인에 실패한 메일을 받는 쪽이 어떻게 다룰지 정해 둡니다

받는 쪽 서버가 이 기록을 확인하면, 남이 이 도메인 이름을 보낸 사람 칸에 베껴 적은 메일을 가려냅니다. 비슷하게 지은 가짜 도메인은 공격자가 주인이라 이 기록을 제대로 갖춥니다. 셋이 막는 것은 진짜 도메인 이름을 베껴 적는 경우까지입니다.

통로와 표적에 따라 갈리는 이름

피싱은 통로가 바뀌어도 같은 수법입니다. 문자 메시지로 오면 스미싱, 전화로 오면 보이스 피싱이라고 부릅니다. 한 사람이나 한 회사를 골라 그쪽 사정에 맞춘 미끼를 쓰면 스피어 피싱입니다.

이 이름으로 부르지 않는 것

중간자 공격은 사용자가 가려던 진짜 주소로 가는 길 가운데 끼어듭니다. 피싱은 사용자가 가짜 주소로 스스로 가게 만듭니다. 앞의 중계처럼 둘이 겹치는 경우가 있어도 출발점이 다릅니다.

다른 곳에서 새어 나간 아이디와 비밀번호 목록을 여러 사이트에 넣어 보는 공격은 크리덴셜 스터핑입니다. 사람을 속이는 단계가 없습니다. 같은 비밀번호를 여러 곳에 쓰는 습관을 노립니다.

클릭재킹은 공격자의 페이지 위에 진짜 사이트를 보이지 않게 겹쳐 올려 두는 공격입니다. 사용자는 눈에 보이는 공격자 페이지의 버튼을 누른다고 믿습니다. 실제로 눌리는 것은 그 위에 겹친 진짜 사이트의 버튼입니다. 사용자가 비밀번호를 가짜 사이트에 넘기지 않는다는 대목이 피싱과 다릅니다.

관련 항목

피싱이 속하는 공격 분류

사회공학 · 스푸핑 · 가장 공격 · 공격 표면 · 보안

피싱의 하위 종류

스피어 피싱 · 스미싱 · 보이스 피싱 · 웨일링 · 비즈니스 이메일 침해 · 중간자 피싱

피싱이 미끼를 나르는 통로

전자메일 · SMTP · SMS · 메신저 · QR 코드 · URL 단축기

피싱이 가짜 주소를 꾸미는 수법

타이포스쿼팅 · 동형 문자 공격 · 퓨니코드 · 오픈 리다이렉트 · 서브도메인 · 도메인 이름 · URL

피싱이 빼내려는 값

비밀번호 · 자격 증명 · 일회용 비밀번호 · 세션 쿠키 · 액세스 토큰 · 리프레시 토큰

피싱을 막는 로그인 방식

다중 인증 · WebAuthn · 패스키 · FIDO2 · 공개 키 암호 · 비밀번호 관리자 · 오리진

피싱 메일을 걸러 내는 발신 인증

SPF · DKIM · DMARC · DNS · 전자 서명

피싱이 비켜 가는 통신 보호 장치

HTTPS · TLS · 인증서 · 인증 기관 · 사이트 격리 · 동일 출처 정책 · 브라우저

피싱이 흉내 내는 로그인 연동

OpenID Connect · OAuth 2.0 · 싱글 사인온 · 인증과 인가 · 리다이렉트

피싱과 헷갈리는 이웃 공격

중간자 공격 · 크리덴셜 스터핑 · 클릭재킹 · 세션 하이재킹 · 무차별 대입 공격

다른 이름: phishing · 피싱 공격