Normaltic 모의해킹 취업반 스터디 8기 - 3주차

containerxox·2025년 4월 26일
post-thumbnail

🚩 3주차 Preview

  • 식별 / 인증
  • 세션 / 쿠키 / 세션ID




💁 로그인을 할 때는 식별인증동시에 이루어진다!
↳ ( 식별 → 인증 → 인가 )
↳ ID를 통해 많은 유저들 중에서 특정 사용자를 식별하고
↳ PW를 통해 해당 사용자가 맞는지 인증한다!
↳예시) ID를 normaltic으로 하여 폼을 전송하면 DB에서 select * from member id='normaltic'쿼리를 통해 사용자를 식별한다. 이후, PW를 DB에 저장된 PW와 비교하여 해당 사용자가 정말 normaltic인지 인증한다!


✅식별(identification) 이란?

: 사용자가 시스템에 접근하기 위해 자신의 정체를 선언하는 행위이다.
💁 나는 normaltic이야!

즉, 사용자는 시스템에 대해 "내가 누구인지"를 주장하고,
이를 통해 시스템은 사용자를 "식별자"를 이용해 구분하게 된다.
ID, 주민등록번호, 학번, 이메일 주소 등이 식별자로 사용됨.


💡식별 정보

어떤 사람을 식별할 수 있는 정보

  • 이름, 전화번호, 이메일, 집 주소
  • 이 자체만으로는 특정인을 완벽히 단독 식별이 불가능할 수 있다.
    (이름이 같은 동명이인이 있을 수 있기 때문)

💡고유 식별 정보

특정 개인을 유일하게 식별할 수 있는 "민감한 개인정보"

  • 주민등록번호, 운전면허번호, 여권번호
  • 고유 식별 정보만으로 특정 개인을 100% 정확하게 식별 가능



▶ 식별의 특징

  • 유일성(Unique) ( 중복되지 않아야 함 )
    ↳ DB에서는 식별자를 PRIMARY KEY로 등록해야 해!
    ↳ 왜냐, 식별자(예들 들어, ID)는 중복되면 안되니까!
  • 식별만으로는 "신뢰성"이나 "보안성"이 생기지 X
    (누구나 자신이 누구인지 거짓말 할 수 있기 때문→인증 필요!)
    ↳ 식별정보는 노출(공개)이 되도 상관 x
    ↳ 하지만, 고유 식별정보는 유출 되면 위험!



✅인증 (Authentication) 이란?

식별된 사용자가 진짜 맞는지 검증하는 과정
💁 진짜 normaltic 맞아?PW을 제출해서 입증할게!

사용자는 자신이 주장한 신원에 대해서 실제로 입증(Verify) 해야하며, 이를 위해 인증정보(Credential)를 제출해야 한다.
PW, OTP, 지문 인식, 얼굴 인식 등의 인증정보를 제출하여 신원을 입증한다.

▶ 인증의 특징

  • 인증은 식별을 전제로 수행함.
  • 식별된 주체에 대해 신뢰성을 확보
  • 인증 강도에 따라 보안 수준이 높아진다.

▶ 인증 수단의 예시

  • 지식 기반(Knowlege-based)
    사용자가 알고 있는 정보를 기반으로 인증
    비밀번호, PIN 번호
  • 소유 기반(Possession-based)
    사용자가 소유한 물리적 수단을 이용하여 인증
    OTP 기기, 스마트 카드
  • 특정 기반(Inherence-based)
    사용자의 고유 생체 특성을 이용하여 인증
    지문 인식, 얼굴 인식



🎯 요약

  • 식별누구인지 밝히는 것 (ID)
  • 인증은 밝힌 사람이 정말 자신이 맞는지 증명하는 것
    (PW, 지문, 얼굴)
  • 인가사용자 별로 허가된 권한을 부여하는 것



✅ 로그인 로직 CASE

💁‍♀️ 로그인의 식별인증을 가지고 어떻게 로그인을 할 수 있는지 로직을 소개해줄게!

1️⃣ 식별/인증을 동시에!

DB 질의를 한 번에 수행해서 로그인을 구현!

▶ pseudocode

SQL쿼리에 "ID와 PW을 동시 넣기" => 식별/인증 동시에 수행

입력한 ID와 비밀번호가 모두 DB에 저장된 저장된 값과
    ↳ 일치하는 경우 "로그인에 성공"하며,
    ↳ 그렇지 않으면 "로그인에 실패"

// ① SQL쿼리에 ID와 PW을 동시 넣기 => 식별/인증 동시에 수행
$sql = "select * from memeber where id='___' and pass='___';

#ret = $sql.execute(); #위 sql 쿼리 실행

// ② 입력한 ID와 비밀번호가 모두 DB에 저장된 저장된 값과 
// 일치하는 경우 로그인에 성공하며, 
// 그렇지 않으면 로그인에 실패
if($ret){
	// 로그인 성공
}else{
	//로그인 실패
}

▶ 실습

  • 계정 2개 만들기
    insert into member value ('doldol', '2222', 'doldol', 'student')
    insert into member value ('normaltic', '1234', 'normaltic', 'student')
  • select * from member where user_id='normaltic' and user_pw='1234'
    → user_id가 normaltic이면서 동시에 user_pass가 1234인 레코드가 나옴.

    ❓만약 비밀번호를 틀리게 적었다고 가정
    ‣ user_id : normaltic
    ‣ user_pw : 9999
    select * from member where user_id='normaltic' and user_pw='9999'
    ➡️ 실행하면 아무것도 안나옴!



2️⃣ 식별/인증 분리

▶ pseudocode

SQL쿼리에 "ID만 넣기" => 식별 수행 (인증은 나중에)

② SQL 결과값 중 비밀번호만 가져와서, if문을 이용하여
    DB에 저장된 비밀번호와 사용자가 입력한 비밀번호를 비교하여
    ↳ 일치하는 경우 "로그인에 성공"하며,
    ↳ 그렇지 않으면 "로그인에 실패"
    => 인증 수행

$sql = "select * from memeber where id='___';

$db_pass = sql.ret['pass'] #sql결과값 중 비밀번호만 가져와

# if문이용해서 비밀번호 서로 일치하는지 판별
if($db_pass == $user_pass){
	// 로그인 성공
}else{
	//로그인 실패
}

▶ 실습

  • select * from member where id = 'normaltic'
    → user_id가 normaltic인 레코드 나옴



☑️ HASH (일방향 함수) 알고리즘

• 임의 길이의 데이터를 입력받아서, 고정된 길이의 해시값을 출력하는 수학적 함수
입력이 아무리 길어도 결과는 항상 같은 길이로 나옴!

💁‍♀️ 해시 알고리즘은 어디에 쓰일까?
‣ 비밀번호 저장
‣ 디지털 서명 (데이터가 변조되지 않았는지 검증)
‣ 무결성 검사 (파일이 손상됐는지 확인할 때)
‣ 블록체인
‣ ctf/해킹 문제
 
💁‍♀️ 해시 관련 툴 & 웹사이트
hashcar
John the Ripper
openssl
md5sum / sha256sum
https://www.md5hashgenerator.com/
: MD5, SHA-1, SHA-256 해시 생성해주는 웹사이트

▶ Hash 알고리즘 특징

  • 고정된 크기 출력
    : 입력 데이터 크기에 상관없이 항상 같은 길이의 결과 만듦
    (예: SHA-256 → 항상 256비트 결과 출력)
     
  • 빠른 계산 속도
     
  • 결정론적(Deterministic)
    : 같은 입력은 항상 같은 해시값을 출력!
     
  • 충돌 회피
    : 서로 다른 두 입력이 같은 해시값을 가지는 것을 매우 어렵게 만듦
     
  • 역방향 불가능성
    : 해시값만 보고 원래의 입력값을 알아내는 것이 거의 불가능!
     
  • 민감도
    : 입력을 아주 조금만 바꿔도 완전히 다른 해시값이 나옴

▶ 대표적인 Hash 알고리즘 종류

  • MD5
  • SHA-1
  • SHA-256: 현재 널리 사용되는 안전한 해시 알고리즘(256비트)
  • SHA-3
  • BLAKE2



☑️ Hash vs. Encryption

  • Hash는 결과만 보고는 원래 데이터를 절대 복구 불가 (단방향)
  • Encryption은 복호화 키를 가지고 있으면 원래 데이터로 되돌리기 가능 (양방향)



☑️ Salt와 Pepper 차이

  • Salt 사용 예시
    : "1234"라는 비밀번호에 각각 사용자마다 다른 Salt를 적용해서 해시!
    → user1의 비번이 1234이면, 1234 + r3#f$2 → 해시값1
    → user2의 비번이 1234이면, 1234 + p1*9z!a → 해시값2
      
  • Pepper 사용 예시
    : 서버에 비밀로 숨겨놓은 "Pepper"를 마지막에 적용
    1234 + pepper_secret → 해시값
     




    ➡️ Pepper없이 해시와 Salt만 사용한다면, 해커가 비밀번호 대입을 쉽게 해시값 맞출 수 있다.
    ➡️ Pepper가 있으면 해커는 비밀번호를 맞춰도 해시값이 안 맞아서 혼란
    ➡️ 하지만 만약 Pepper까지 털리면, 해커는 다시 쉽게 대입 공격이 가능



💁 네이버 로그인을 한 번 하면, 네이버라는 웹 서버는 내가 누구인지를 알고 있다. (로그인이 유지되고 있다)
그러면, 웹 서버는 어떻게 내가 나인걸 알까?
IP주소를 알고 있어서 일까? NO
만약 IP주소를 알고 있어서라면, 카페에서는 로그인이 불가능하다.
카페에서 공용Wifi를 사용하는케 카페의 모든 손님이 같은 IP주소를 사용하기 때문에
웹 서버 입장에서는 손님들의 모든 IP주소가 다 같아보인다.
따라서, 이 방법은 좋지 않다.

💁‍♀️로그인 상태를 유지시키는 방법 없을까?
➡️ 이 3가지 개념에 대해서 알아보자!

  • 쿠키 (Cookie)
  • 세션 (Session)
  • 세션 ID (Session ID)
     
    ( Tip ) 쿠키와 세션을 통해 관리할 수 있으며, 특히 세션 ID의 개념을 이해하는 것이 중요!

✅ 쿠키

: 쿠키는 웹 브라우저가 서버로부터 받아서 브라우저 안에 저장하는 작은 데이터 조각

📌 쿠키는 HTTP 헤더에 실어서 서버와 주고 받는다.
1️⃣ 서버클라이언트로 쿠키 설정할 때
: 서버가 클라이언트(브라우저)한테 쿠키를 심어주려면,
HTTP 응답 헤더에 아래처럼 적는다.

HTTP/1.1 200 OK
Set-Cookie: session_id=abc123;
Path=/; 
Expires=Wed, 01 May 2025 00:00:00 GMT; 
HttpOnly

➡️Set-Cookie라는 헤더를 통해 서버가 쿠키를 설정함.
➡️ 브라우저는 이걸 보고 쿠키를 저장!
-----------------------------------------------------------

2️⃣ 클라이언트서버로 쿠키 설정할 때
: 클라이언트(브라우저)가 서버로 요청을 보낼 때,
HTTP 요청 헤더에 이렇게 쿠키를 자동으로 첨부해서 보냄.

GET /dashboard HTTP/1.1
Host: example.com
Cookie: session_id=abc123

➡️브라우저가 자동으로 Cookie: 헤더에 저장된 쿠키를 실어서 보냄.
➡️ 서버는 이걸보고 아 이 유저구나!하고 로그인 상태를 확인


💁 추가 공부
Expires: 언제 만료되는지
HttpOnly: 자바스크립트로 못 읽게 해서 보안 강화
Secure: HTTPS 연결에서만 전송되게!
SameSite: CSRF 공격 방지용
Path=/ : 어떤 경로에 대해 적용할지

▶ 쿠키의 특징

  • 저장 위치
    : 클라이언트(브라우저)
  • 크기 제한
    : 한 쿠키당 4KB 정도 (엄청 작음)
  • 자동 전송
    : 같은 사이트에 요청할 때 "자동으로 쿠키를 같이 보냄"
  • 사용 목적
    : 로그인 상태 유지, 사용자 설정 기억 등
  • 수명 (만료)
    : 설정한 만료 시간까지 유지 (만료되면 자동 삭제)
    (설정기간까지는 브라우저를 닫아도 유지됨)

▶ 실습

  • 첫 로그인 시도 성공
     
  • 서버 → 클라이언트로 쿠키 설정할 때, HTTP 응답을 보면, loginUser=normaltic이라고 쿠키를 설정함!
  • 나중에, 브라우저가 loginUser=normaltic이라고 쿠키를 적어서 요청을 보내면 서버는 normaltic임을 확인!(인증)

  • 새로고침하고
  • 클라이언트 → 서버로 요청을 보낼 때, HTTP 요청을 보면 ,
    loginUser=normaltic이라고 적어서 서버로 요청을 보내고 있다.
  • 그럼 이제 서버는 loginUser=normaltic이라는 쿠키를 확인하고 normaltic유저임을 확인(인증)함!
  • 이런 방식을 통해 로그인 상태가 유지되는 것이다!

⚠️ 쿠키의 문제점

쿠키는 클라이언트(사용자)쪽에서 생성되고 관리되는 값이다
따라서 해커 역시 클라이언트가 될 수 있다.
 
웹 요청을 보낼 때, 해커가 쿠키 값을 조작하여
loginUser=normaltic이 아닌 loginUser=doldol로 변경하면 doldol이라는 사용자로 로그인할 수 있게 된다.
➡️ 이러한 행위를 '쿠키 변조'라고 한다!




💁 그래서 로그인 상태를 유지하는 방식으로 '쿠키'를 사용하는 것은 적절한 방식이 아니라고 생각!
왜냐하면, 쿠키가 클라이언트 측에서 저장되기 때문에 조작이 가능하기 때문이다.
이를 해결하기 위해, "클라이언트가 조작할 수 없게 서버에 저장하자!'라는 아이디어가 나왔다.
➡️ 그렇게 탄생한 게 바로 세션



✅ 세션

  • 클라이언트가 아닌 서버에 로그인 상태같은 정보를 저장하는 기술
  • 서버가 사용자에 대해 기억하고 있는 정보 덩어리

    < 세션세션 ID 관계>

    • 세션
      : 서버에 저장된 사용자 데이터
    • 세션 ID
      : 서버가 저장한 세션을 찾기 위한 key
       
      ➡️ 세션 = 사물함 안에 들어 있는 개인 물건
      ➡️ 세션 ID = 그 사물함을 열 수 있는 고유한 열쇠 번호
       
       
      < 세션에 저장하는 정보 예시 >
      서버는 세션에 이런 걸 저장할 수 있다.
      ‣ 이 사용자는 누구인가? (userId = doldol)
      ‣ 로그인했는가? (isLoggedIn = true)
      ‣ 권한이 무엇인가? (role = admin)
      ‣ 쇼핑몰이라면 장바구니 내용 (cart = [item1, item2])
      ➡️ 이런 상태(state) 정보를 세션에 저장해 두는 거예요.

▶ 세션의 특징

  • 저장 위치
    : 서버
  • 크기 제한
    : 서버 메모리/DB에 따라 다름
  • 자동 전송
    : 클라이언트는 세션 ID를 쿠키에 저장하고,
    요청할 때마다 자동으로 전송함

    (Cookie: sessionId=xxx 헤더)
  • 사용 목적
    : 사용자 로그인 상태 유지, 장바구니 정보 저장,
    사용자별 데이터 관리 등
  • 수명(만료)
    : 세션에는 만료 시간(timeout)이 설정
    : 일정 시간 동안 요청이 없으면 세션이 자동으로 삭제됨 (예: 30분, 1시간 등)

▶ 세션 흐름

사용자 로그인 요청
: 사용자가 서버에 로그인 (ID/PW 입력) 요청을 보낸다.
사용자 확인 (회원 DB 조회)
: 서버는 회원DB에 가서 입력된 ID/PW가 맞는지 확인한다.
회원 정보로 세션 생성
: 로그인 성공 시, 서버는 사용자 정보를 모아서 새로운 세션 데이터를 생성.
세션 ID 발급
: 서버는 생성된 세션 데이터에 대해 세션 ID를 생성하고, 클라이언트에게 발급할 준비를 한다.
응답 (세션 ID 포함)
: 서버는 클라이언트에게 로그인 성공 응답을 보내면서, 세션 ID를 쿠키에 담아 보낸다.
사용자가 데이터 요청 (세션 ID 쿠키 포함)
: 사용자는 이후 서버에 요청을 보낼 때, 브라우저가 세션 ID가 담긴 쿠키를 자동으로 포함해서 보낸다.
서버가 쿠키 검증
: 서버는 클라이언트가 보낸 요청에서 세션 ID 쿠키를 읽고, 유효한지 검증한다.
세션 저장소에서 사용자 정보 조회
: 서버는 세션 저장소에서 해당 세션 ID에 연결된 세션 데이터(사용자 정보)를 가져온다.
응답 (+ 요청 데이터)
: 서버는 사용자 요청을 처리한 뒤, 필요한 데이터와 함께 응답을 보낸다.

▶ 실습

① PHP에서 세션을 사용하겠다는걸 알리려면 session_start();
② 세션에다가 id라는 키에 normaltic이라는 값을 저장.
    $_SESSION['id'] = 'normaltic';

<?php
	session_start();
    $_SESSION['id'] = 'normaltic';
?>

 
php -i | grep session.save_path
php -i: PHP 설정 전체를 출력하는 명령어
| grep session.save_path: 그 중에서 session.save_path 라는 설정만 골라서 보여줘
↳ 결과: session.save_path => /var/lib/php/sessions => /var/lib/php/sessions
→ 현재 PHP 서버는 세션 파일은 /var/lib/php/sessions 폴더에 저장하도록 설정되어 있다는 의미

ls /var/lib/php/sessions
↳ 결과: sess_nq4frbpdkbldfgfvu8hviq7mes
→ 이 파일 하나가 한 명의 세션 데이터를 저장하고 있는 파일이다.

cat /var/lib/php/sessions/sess_nq4frbpdkbldfgfvu8hviq7mes
↳ 세션 파일 내용을 출력해서 보여줌
↳ 결과:id|s:9:"normaltic";
id: 세션에 저장된 변수 이름
s:9:"normaltic";
: s는 string, 길이는 9글자, 값은 "normaltic"
 
➡️ 즉, 이 세션은 id=normaltic이라는 데이터를 가지고 있음




💁 서버에 저장되는 세션들은 각각 어떤 사용자의 것인지 식별할 수 있어야 한다.
이때 세션을 식별하기 위해 부여하는 고유한 ID를 Session ID라고 한다.

Session ID는 클라이언트에게 전달되어 요청할 때마다 함께 보내지며,
서버는 이 Session ID를 통해 세션 저장소에 있는 해당 사용자의 세션 데이터를 찾아낸다.



✅ 세션ID

: 서버에 저장된 세션 데이터를 식별하기 위해, 서버가 클라이언트에게 발급하는 고유한 식별자
 

  • 사용자가 로그인같은 요청을 보내면 서버는 세션을 생성하고,
    이 세션을 찾기 위해 긴 무작위 문자열(Session ID)을 만들어 클라이언트에 전달
  • 클라이언트(브라우저)는 이 세션 ID를 쿠키에 저장하고,
    이후 서버에 요청할 때 자동으로 이 세션 ID를 함께 보냄
  • 서버는 세션 저장소에서 "이 세션 ID는 누구꺼지?"를 찾아보고 그에 맞는 사용자 데이터를 읽어서 요청을 처리
     
     

    • sessionid: 클라이언트(브라우저)에게 발급된 고유 식별자
    • value: 서버에 저장된 세션 데이터
       
      ➡️ 클라이언트는 sessionid=zzZdohflw0f54e를 쿠키로 가지고 다니고,
      ➡️ 서버는 이 sessionid를 기준으로 value(normaltic)을 찾아서 "이 세션은 normaltic이구나!" 라고 인식한다.

▶ 세션ID 특징

  • 고유성
    : 세션 ID는 각 사용자의 세션마다 고유하게 생성됨.
    (서로 중복되면 X)
  • 무작위성
    : 세션 ID는 보안을 위해 예측 불가능하게 랜덤하게 생성
  • 비밀성
    : 세션 ID자체를 외부에 노출시키면 안됨.
    : 탈취되면 세션 하이재킹 위험 有
  • 자동 전송
    : 브라우저는 세션 ID를 쿠키에 담아. 매 요청마다 서버로 자동 전송
  • 서버 기반 매칭
    : 서버는 세션 ID를 보고 세션 저장소에 접근해 사용자 데이터를 조회
  • 수명(만료)
    : 세션 ID는 세션의 수명에 따라 함께 만료됨.
  • Secure 옵션 사용 가능
    : HTTPS 연결에서만 세션 ID를 주고받게 할 수 O



☑️ 쿠키 & 세션 & 세션ID 총정리

  • 쿠키
    ↳ 클라이언트(브라우저)에 저장하는 작은 데이터 조각
     
  • 세션
    ↳ 서버에 저장하는 사용자 정보 저장 공간
     
  • 세션 ID
    : 세션을 식별하기 위해 부여한 고유한 ID
     

    💡 보통 쿠키에 세션 ID를 저장해서,
    브라우저가 서버에 세션 ID를 보내주면서
    로그인 유지가 된다!



✅ jwt

0개의 댓글