diff --git a/keyword/chapter09/keyword.md b/keyword/chapter09/keyword.md new file mode 100644 index 0000000..6798cdf --- /dev/null +++ b/keyword/chapter09/keyword.md @@ -0,0 +1,155 @@ +### 세션과 토큰의 차이는? + + **세션** : 사용자가 인증에 성공한 상태 + + - 서버에서 유저의 상태를 관리 (서버에 부담) + - 세션 기반 인증 방식 + - 유저가 인증정보를 담아 서버에 로그인 요청을 보냅니다 + - 서버는 데이터베이스에 저장된 유저의 인증정보를 확인합니다 + - 인증에 성공했다면, 해당 유저에 대한 세션을 생성하고, 이를 서버 메모리에 저장합니다 + - 쿠키(매개체)를 통해 해당 유저의 세션 id를 클라이언트에 전달합니다 + - 클라이언트에 세션 id가 저장됩니다 + - 클라이언트에서 서버로 리소스를 요청 할때, 쿠키(매개체)에 세션 id가 함께 전달됩니다 (GET/someinfo) + - 서버는 전달받은 세션 id를 토대로 유저의 세션 데이터를 조회합니다 + - 세션이 유효하다면, 유저의 요청에 대한 응답 데이터를 전송합니다 + + **토큰** : 무언가를 이용할 수 있는 권한이나 자격을 나타내는 징표 + + - 세션 기반 인증이 가지고 있던 한계를 극복하고자 만들어짐 + - 서버에 사용자의 인증 상태를 저장하는 것이 아닌 클라이언트에 이를 저장하는 방법 + - 서버의 과부하나 메모리 부족 문제 줄일 수 있다 + - 토큰 기반 인증 방식 + - 유저가 인증정보를 담아 서버에 로그인 요청을 보냅니다 + - 서버는 데이터베이스에 저장된 유저의 인증정보를 확인합니다 + - 인증에 성공했다면, 서버는 유저에 대한 권한정보를 서버의 비밀키와 함께 토큰을 생성합니다 + - 서버는 Authorization 헤더에 토큰을 담아 클라이언트에 전달합니다 + - 클라이언트는 전달받은 토큰을 브라우저의 세션 스토리지 or 로컬스토리지 에 저장합니다 + - 클라이언트가 서버로 리소스를 요청할때, Authorization 헤더를 통해 토큰이 함께 전달됩니다 + - 서버는 전달받은 토큰을 서버의 비밀키로 검증합니다 이를 통해, 토큰이 위조되었는지 토큰의 유효기간이 지나지 않았는지 등을 확인할 수 있습니다 + - 토큰이 유효하다면, 유저의 요청에 대한 응답 데이터를 전송합니다 + - 무상태성 : 서버는 토큰의 유효성만 검증 (유저의 상태 관리 X) + - 확장성 : 하나의 토큰으로 다수의 서버에 인증 가능 + - 권한 부여에 용이 + +
+ +### 엑세스 토큰과 리프레시 토큰이란? + + **액세스 토큰** : 클라이언트가 가지고 있는 실제로 유저의 정보가 담긴 토큰. 클라이언트에서 요청이 오면 서버에서 해당 토큰에 있는 정보를 활용하여 사용자 정보에 맞게 응답함. + + **리프레시 토큰** : 새로운 액세스 토큰을 발급해주기 위해 사용하는 토큰. 짧은 수명을 가지는 액세스 토큰에게 새로운 토큰을 발급해주기 위해 사용 + + - 액세스 토큰의 유효기간을 짧게 하여 자주 재발급 하도록 만들어 보안을 강화하면서 동시에 사용자에게 잦은 로그인 요구를 하지 않도록 만들기 위해 사용 + - 액세스 토큰 대비 긴 유효 기간을 가진다 + - 클라이언트가 로그인을 요청하고 성공하면 서버는 액세스, 리프레시 토큰을 함께 제공 + - 이후 클라이언트는 인가가 필요한 요청에 액세스 토큰을 실어 보낸다 + - 시간이 흘러 액세스 토큰이 만료 되었다면 클라이언트는 리프레시 토큰을 서버로 전다랗여 새로운 액세스 토큰을 발급 받는다. + - + - 한계 + - 탈취된 액세스 토큰이 유효한 그 짧은 시간 동안 악용 가능 + - 리프레시 토큰 탈취 가능 + - RTR(Refresh Token Rotation)을 사용하면 리프레스 토큰을 1회 사용하고 버리게 되지만, 사용하지 않은 토큰이 탈취되면 위험하다 + + - 토큰 기반 인증 방식은 stateless. 서버는 한번 발급한 토큰에 대해서 제어권을 가지고 있지 않는다. 따라서 제 3자에게 토큰 탈취의 위험성이 있기 때문에 액세스 토큰과 리프레시 토큰을 모두 사용하여 이중으로 나눠서 인증하는 방식 사용 + +
+ +### OAuth 1.0과 OAuth 2.0의 차이는? + + OAuth : 비밀번호를 넘겨주지 않고도 제 3의 앱이 네이버나 카카오 같은 대형 플랫폼의 유저 데이터에 안전하게 접근할 수 있도록 권한을 위임해주는 프로토콜 + + **OAuth 1.0** + + - 토큰을 주고 받을 때 웹 브라우저나 쿠키나 세션처럼 중간에 탈취당할 위험을 방지하기 위해 모든 API 요청마다 HMAC-SHA1같은 복잡한 암호화 서명을 생성해서 보내야함 + - 개발자가 모든 요청마다 서명 알고리즘 코드를 직접 짜야했다. + - 흐름이 단일하고 고정적 + - 토큰의 유효기간을 설정하는 표준이 없어서 관리가 어려움 + - 용어와 역할 정의가 명확하지 않음 + + **OAuth 2.0** + + - 요청할 때마다 복잡하게 암호화 서명을 만드는 것이 아닌 전체 통신 도로 자체를 암호화 해버림 (HTTPS 기반 Bearer 토큰 방식) + - 클라이언트(애플리케이션, 앱), 리소스 소유자(사용자), 권한 부여 서버(사용자 인증 및 토큰 발급), 리소스 서버(보호된 자원 제공)로 역할 분리 + - 웹앱, 네이티브, 서버간 통신 등에 맞춘 여러 Grant Type을 지원 + 훨씬 유연하고 확장 가능 + - 구현이 복잡하고 구현 부주의 시 redirect, 토큰 탈취 등에 공격에 노출 가능 + +
+ +### FIDO란? + + FIDO : 아이디와 비밀번호를 입력하는 대신 지문이나 홍채, Face ID 같은 생체 인증이나 하드웨어 키를 이용해 안전하고 빠르게 인증할 수 있도록 만든 글로벌 표준 기술 + + - **기존 패스워드 방식:** 사용자가 입력한 비밀번호(또는 해시값)가 네트워크를 타고 **서버로 전송되어 DB에 저장**됩니다. 따라서 서버가 해킹당하면 유저들의 비밀번호가 통째로 유출되는 치명적인 위험이 있습니다. + - **FIDO 방식 (공개키 암호화 구조):** 사용자의 생체 정보(지문 등)가 **절대로 서버로 전송되지 않습니다.** 인증은 사용자의 스마트폰(디바이스) 내부의 아주 안전한 독립된 보안 영역(`Secure Enclave` 등) 안에서만 처리됩니다. + + **FIDO의 작동 원리** + + - **등록 단계 (최초 1회):** + - 스마트폰에서 지문을 등록하면, 스마트폰 내부에서 개인키(Private Key)와 **공개키(Public Key)** 쌍을 생성합니다. + - **개인키**는 스마트폰 내부 깊숙한 보안 영역에 절대 나갈 수 없게 꽁꽁 숨겨두고, **공개키**만 우리 백엔드 서버로 보내 서버 DB에 저장합니다. + - **인증 단계 (로그인할 때):** + - 사용자가 로그인을 시도하면, 우리 서버는 난수(Challenge)를 생성해서 스마트폰으로 던집니다. + - 스마트폰은 유저에게 "지문이나 Face ID를 대라"고 요청합니다. + - 사용자가 지문 인증에 성공하면, 스마트폰 내부에 숨겨져 있던 **개인키**가 잠금 해제되면서 서버가 보낸 난수를 암호화(서명)해서 서버로 다시 보냅니다. + - 우리 서버는 DB에 저장해 둔 **공개키**를 꺼내어, 도착한 암호문이 진짜 매칭되는지 검증(Verify)하고 로그인을 통과시킵니다. + + **FIDO의 종류** + + - **FIDO 1.0 (UAF / U2F):** * **UAF:** 스마트폰 앱 환경에서 지문으로 바로 로그인하는 방식입니다. + - **U2F:** 아이디/비번을 치고 난 후, 별도의 USB 보안 키(YubiKey 등)를 꽂아 2차 인증을 하는 방식입니다. + - **FIDO 2.0 (WebAuthn / CTAP):** + - **현대의 표준**입니다. 과거에는 앱에서만 생체 인증이 가능했으나, W3C(웹 표준 기구)와 협력하여 **웹 브라우저(크롬, 사파리 등)에서도 별도의 플러그인 없이 자바스크립트 API(`WebAuthn`)만으로 스마트폰 지문인증을 호출**할 수 있게 만든 기술입니다. 요즘 금융권 웹사이트나 구글 로그인할 때 PC 화면에서 스마트폰 지문 대라고 나오는 기술이 바로 이것입니다. + +
+ +### challenge-response authentication + + **Challenge-Response Authentication(챌린지 응답 인증)** + + - 인증과정에서 비밀번호를 네트워크 상에 그대로 전송하지 않고 서버가 던진 문제를 클라이언트가 맞추는 방식으로 신원을 증명하는 보안 메커니즘 + - 가장 원초적인 인증 방식은 사용자가 아이디와 비밀번호를 서버에 그대로 보내는 것입니다. + 하지만 이 방식은 통신 구간을 누군가 훔쳐보고 있다면(도청/Sniffing), 비밀번호가 그대로 노출되거나 가로챈 비밀번호를 그대로 다시 제출해 로그인하는 재전송 공격(Replay Attack)에 매우 취약합니다. + - 챌린지-응답 방식은 "비밀번호를 통신 선로에 절대 흘려보내지 않으면서, 내가 그 비밀번호를 알고 있다는 사실을 서버에게 증명"하기 위해 고안되었습니다. + + **작동흐름** + + - **요청 (Request):** 사용자가 서버에 "나 로그인할래"라고 아이디를 보냅니다. + - **챌린지 (Challenge):** 서버는 매번 바귀는 무작위 문자열(난수)을 생성하여 클라이언트에게 던집니다. 이 난수를 '챌린지(문제)'라고 부릅니다. + - **응답 (Response):** * 클라이언트는 자신이 가진 실제 **비밀번호**와 서버가 보낸 **챌린지 값**을 합칩니다. + - 이 합친 문자열을 해시 함수(예: SHA-256)로 돌려 나온 결괏값(**응답**)을 서버로 전송합니다. + - **검증 (Verification):** + - 서버도 자기가 보낸 챌린지 값과 DB에 저장된 유저의 비밀번호를 합쳐서 똑같이 해시를 돌려봅니다. + - 서버가 직접 계산한 값과 클라이언트가 보내온 **응답 값**이 정확히 일치하면 인증을 통과시킵니다. + + **안전한 이유** + + - **비밀번호 유출 차단:** 네트워크 선로를 지나간 데이터는 오직 일회성 '챌린지'와 '응답(해시값)'뿐입니다. 진짜 비밀번호는 클라이언트 컴퓨터 밖으로 한 걸음도 나가지 않았기 때문에 도청을 당해도 안전합니다. + - **재전송 공격 방어:** 해커가 중간에서 응답(해시값)을 가로채서 다음 요청 때 똑같이 서버에 던지더라도, 서버는 매 요청마다 완전히 새로운 챌린지(난수)를 만들어 던지기 때문에 과거의 응답 값은 아무짝에도 쓸모없는 쓰레기 데이터가 됩니다. + +
+ +### 왜 비대칭키 암호화 방식이 패스키에 적절한지 + + #### 1. 서버가 해킹당해도 내 계정은 안전하기 때문에 → 공유 주체가 없기 때문 + + - 기존 비밀번호 방식이나 대칭키 방식은 서버와 클라이언트가 '동일한 비밀 정보'를 공유해야 합니다. 아무리 해시 함수(Bcrypt 등)로 암호화해서 DB에 저장하더라도, 백엔드 데이터베이스가 통째로 털리면 해커들이 무차별 대입 공격(Brute Force)을 통해 비밀번호를 알아낼 위험이 항상 존재합니다. + - 반면 비대칭키 기반의 패스키는 구조가 완전히 다릅니다. + - **개인키 (Private Key):** 오직 재준님의 스마트폰이나 노트북 보안 칩셋 내부(지문/Face ID로만 열리는 공간)에만 저장되며, **절대로 서버로 전송되지 않습니다.** + - **공개키 (Public Key):** 서비스 서버(예: 네이버, 구글)로 전송되어 DB에 저장됩니다. + - 공개키는 세상 모든 사람에게 공개되어도 아무런 상관이 없는 껍데기 열쇠입니다. 따라서 **백엔드 서버가 아무리 잔인하게 해킹당해 공개키 목록이 통째로 다 유출되더라도, 해커는 유저의 계정에 로그인할 수 있는 방법이 절대 없습니다.** + + #### 2. 비밀번호를 통신 선로에 흘려보내지 않기 때문에 + + - 해커들이 개인 정보를 빼내는 가장 흔한 수법은 가짜 로그인 사이트를 만들어두고 비밀번호를 타이핑하게 만드는 **피싱(Phishing)** 공격입니다. + - 비대칭키를 활용한 패스키는 **챌린지-응답(Challenge-Response)** 방식을 사용하기 때문에 사용자가 비밀번호를 입력하는 과정 자체가 없습니다. + 1. 로그인할 때 서버가 난수(Challenge)를 던집니다. + 2. 기기에서 지문을 대면, 내 폰 안에 숨겨진 **개인키**가 이 난수를 암호화(전자서명)해서 서버로 보냅니다. + 3. 서버는 가지고 있던 **공개키**로 이 서명이 맞는지 검증만 합니다. + - 이 과정에서 선로를 지나가는 데이터는 매번 바뀌는 서명 값일 뿐이며, 진짜 신원 정보인 개인키는 기기 밖으로 단 한 걸음도 나오지 않습니다. 해커가 중간에서 통신을 가로채거나 가짜 사이트를 만들어 유혹해도 **줄 수 있는 비밀번호 자체가 없으므로 피싱 공격이 원천 차단**됩니다. + + #### 3. 생체 인증과 암호학적 키 잠금 해제 + + - 지문이나 안면 인식은 서버 로그인에 직접 쓰이는 것이 아닌 개인키를 깨우기 위한 일종의 도어락 열쇠 역할만 한다 + - 유저가 지문 → 스마트폰 내부 보안 구역 열림 → 개인키 활성화 → 서버가 준 문제를 풀어서 제출 + - 이 일련의 과정이 비대칭키 구조 덕분에 완벽하게 분리되어 작동하므로, 유저는 복잡한 비밀번호를 외울 필요 없이 스마트폰을 잠금 해제하는 것만큼 빠르고(Fast) 안전하게 웹사이트에 로그인할 수 있게 됩니다. \ No newline at end of file diff --git a/mission/chapter09/1.png b/mission/chapter09/1.png new file mode 100644 index 0000000..989a042 Binary files /dev/null and b/mission/chapter09/1.png differ diff --git a/mission/chapter09/10.png b/mission/chapter09/10.png new file mode 100644 index 0000000..c47a19e Binary files /dev/null and b/mission/chapter09/10.png differ diff --git a/mission/chapter09/2.png b/mission/chapter09/2.png new file mode 100644 index 0000000..9a958d2 Binary files /dev/null and b/mission/chapter09/2.png differ diff --git a/mission/chapter09/3.png b/mission/chapter09/3.png new file mode 100644 index 0000000..10b2139 Binary files /dev/null and b/mission/chapter09/3.png differ diff --git a/mission/chapter09/4.png b/mission/chapter09/4.png new file mode 100644 index 0000000..9e867df Binary files /dev/null and b/mission/chapter09/4.png differ diff --git a/mission/chapter09/5.png b/mission/chapter09/5.png new file mode 100644 index 0000000..4105114 Binary files /dev/null and b/mission/chapter09/5.png differ diff --git a/mission/chapter09/6.png b/mission/chapter09/6.png new file mode 100644 index 0000000..a04e8e0 Binary files /dev/null and b/mission/chapter09/6.png differ diff --git a/mission/chapter09/7.png b/mission/chapter09/7.png new file mode 100644 index 0000000..2bba6cf Binary files /dev/null and b/mission/chapter09/7.png differ diff --git a/mission/chapter09/8.png b/mission/chapter09/8.png new file mode 100644 index 0000000..44277f2 Binary files /dev/null and b/mission/chapter09/8.png differ diff --git a/mission/chapter09/9.png b/mission/chapter09/9.png new file mode 100644 index 0000000..f8c02ef Binary files /dev/null and b/mission/chapter09/9.png differ diff --git a/mission/chapter09/mission.md b/mission/chapter09/mission.md new file mode 100644 index 0000000..fc8bbe0 --- /dev/null +++ b/mission/chapter09/mission.md @@ -0,0 +1,12 @@ +### 미션 기록 + +![mission1](1.png) +![mission2](2.png) +![mission3](3.png) +![mission4](4.png) +![mission5](5.png) +![mission6](6.png) +![mission7](7.png) +![mission8](8.png) +![mission9](9.png) +![mission10](10.png)