Infra & Security Eng/Semi Project
세미 프로젝트 - OSI 7계층 취약점 분석: 5계층 Session Fixing(세션 고정) (보고서작성용x, 공부용)
엔지니어 E
2026. 2. 25. 12:17
반응형

| ※ 이 과정은 외부와 격리된 독립적인 가상 네트워크 내에서 실습 하였습니다 주제 OSI 7계층 중 **5계층(세션 계층)**의 세션 식별자 관리 결함을 이용한 Session Fixing(세션 고정) 공격 분석 목적 로그인 전후로 세션 식별자(Session ID)가 갱신되지 않는 취약점을 악용하여, 공격자가 사용자에게 미리 특정 세션 ID를 주입하고 로그인 후의 권한을 탈취하는 공격을 실증함. 공격 메커니즘 세션 식별자 고정: 웹 서버가 익명 사용자에게 발급한 세션 ID를 로그인(인증) 후에도 교체하지 않고 그대로 유지하는 설계를 악용함. 권한 탈취: 공격자는 자신이 생성한 세션 ID가 포함된 링크를 사용자에게 전달(주입)함. 사용자가 해당 ID를 가진 채로 로그인을 완료하면, 공격자는 동일한 ID를 사용하여 사용자의 인증된 세션에 무단 접근함. 네트워크 구성도 Attacker (Router 1): 192.168.11.13 (공격자, 세션 주입 및 탈취 주체) Victim (WAS): 192.168.11.12 (피해 사용자 역할, 기본 설정 상태) Target (WEB): 192.168.11.11 (취약한 웹 서비스 운영 서버) |
| 웹 서버 먼저 취약한 환경을 구축해야 한다. 세션 고정 취약점이 있는 웹 어플리케이션을 구동 한다 * flask 서버를 띄어야 하므로 아파치 서버는 잠시 중지 시켜 놓는다 # systemctl stop http 패키지 설치 # dnf install -y python3-flask * 명령어를 통해 Flask라는 파이썬 웹 프레임워크를 설치 * Flask: 파이썬으로 가볍고 빠르게 웹 서버를 만들 수 있게 해주는 도구 * python3 -c "import flask; print(flask.__version__)" - 버전 숫자가 출력되면 성공 * 패키지 설치 안될 시 DNS 서버 켰는지 확인 한다 취약한 웹 소스 작성(# vi /root/session_fix.py) ![]() ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ from flask import Flask, request, make_response app = Flask(__name__) @app.route('/') def index(): sid = request.args.get('sid') resp = make_response("<h1>Session Fixing Test Page</h1><p>Check your Cookie!</p>") if sid: resp.set_cookie('session_id', sid) return resp @app.route('/login') def login(): return "<h2>Login Success!</h2><p>Your session is now AUTHENTICATED.</p>" if __name__ == '__main__': app.run(host='0.0.0.0', port=80) ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ from flask import Flask, request, make_response app = Flask(__name__) @app.route('/') - 취약점1) 메인페이지: URL에 포함된 sid 값을 강제로 브라우저 쿠키에 심음 def index(): sid = request.args.get('sid') - URL 에서 ?sid=xxxx 부분을 읽어옴 resp = make_response("<h1>Session Fixing Test Page</h1><p>Check your Cookie!</p>") - 사용자에게 보여줄 응답 메세지 생성 if sid: resp.set_cookie('session_id', sid) - 만약 URL에 sid가 있다면, 그 값을 그대로 세션 쿠키('session_id')로 구움 return resp @app.route('/login') - 취약점2) 로그인 페이지: 인증 후에도 기존 세션ID를 그대로 유지함(매우 위험) def login(): - 원래는 여기서 sid를 새로 발급(Regenerate) 해야 하지만 이 코드는 기존 sid를 그대로 써서 공격자가 가로채기 쉬움 return "<h2>Login Success!</h2><p>Your session is now AUTHENTICATED.</p>" if __name__ == '__main__': app.run(host='0.0.0.0', port=80) - 모든 IP(0.0.0.0)에서 접속 허용, 기본 웹 포트(80)로 서버 실행 EOF ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ # systemctl stop http - flask 서버를 띄어야 하므로 아파치 서버는 잠시 중지 시켜 놓는다 # sudo fuser -k 80/tcp - 혹시나 돌아가고 있을지 모르는 다른 프로세스 확인 및 종료 웹 서버 실행 # sudo python3 /root/session_fix.py 라우터 서버 공격자는 사용자(WAS서버)에게 전달할 공격용 URL 을 준비 한다 공격용 주소: http://192.168.11.11/?sid=HACKER_SECRET_SESSION - 이 링크를 사용자가 클릭하게 만드는 것이 공격의 시작이다 실증 확인 WAS 서버 정확한 데이터 추출을 위해 curl의 상세출력(-v) 모드를 사용하여 세션 고정 현상을 증명한다 ![]() 실증 1) 공격자가 보낸 링크 접속(세션 주입 당하기) # curl -v "http://192.168.11.11/?sid=HACKER_SECRET_SESSION" [프로세스] 1. 사용자가 공격자가 보낸 악성 URl을 클릭 2. WEB 서버 응답: 서버는 사용자의 요청을 받고 Set-Cookie: session_id=HACKER_SECRET_SESSION 헤더를 내려보냄 3. 결과: 사용자의 브라우저(curl)에 공격자가 미리 알고 있는 세션 ID가 강제로 저장(Fixing) 됨 WEB 서버 상황 (실행 명령어 - curl -v "http://192.168.11.11/?sid=HACKER_SECRET_SESSION") ![]() ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ ![]() 실증 2) 해당 세션을 유지한 채 로그인 수행(인증 권한 부여) # curl -v --cookie "session_id=HACKER_SECRET_SESSION" http://192.168.11.11/login [프로세스] 1. 사용자가 자신의 아이디/패스워드를 입력하여 로그인을 수행함(실습에서는 해당 페이지 접속으로 대체) 2. 핵심 취약점 발생: 서버는 사용자가 로그인했음에도 불구하고, 기존의 HACKER_SECRET_SESSION을 폐기하지 않고 해당 ID에 '인증됨(Authenticated)' 권한을 부여함 3. 이제 HACKER_SECRET_SESSION이라는 열쇠는 서버 내부의 중요 데이터에 접근할 수 있는 권한을 가지게 됨 WEB 서버 상황(실행 명령어 - curl -v --cookie "session_id=HACKER_SECRET_SESSION" http://192.168.11.11/login) ![]() ROUTER 서버 ![]() 실증 3) 공격자의 세션 탈취 및 권한 도용(공격 성공) # curl -v --cookie "session_id=HACKER_SECRET_SESSION" http://192.168.11.11/login WEB 서버 상황 ![]() |
| 보안 대책 단순한 세션 탈취 확인 실습에 그치지 않고, 세션 계층의 보안 취약점을 근본적으로 보완하여 네트워크 서비스의 **가용성(Availability)**과 **신뢰성(Reliability)**을 확보하기 위한 해결책을 다음과 같이 제시합니다 1. 네트워크 및 서비스 계층 1) Session Regeneration (세션 재발급): 사용자가 로그인(인증) 성공 시, 기존 세션 ID를 즉시 폐기하고 무작위로 생성된 새로운 세션 ID를 발급하도록 애플리케이션 로직을 수정합니다. (가장 근본적인 해결책) 2) URL Parameter 기반 세션 전달 금지: 세션 ID는 오직 HTTP Header의 Cookie를 통해서만 전달되도록 설정하며, URL 파라미터(?sid=...)로 유입되는 세션은 무효화 처리합니다 실증 결과 분석 1. 한계점 증명: 세션 ID를 강제로 주입하더라도, 사용자가 웹사이트에서 **'로그인(인증) 액션'**을 취하지 않으면 해당 세션 ID로는 보호된 자원에 접근할 수 없음을 확인하였습니다 2. 공격 성공의 조건: 서버가 '인증되지 않은 상태'와 '인증된 상태'에서 동일한 세션 식별자를 유지하는 보안 로직의 부재가 5계층 취약점의 핵심 원인임을 실증하였습니다 결론 1. 세션 라이프사이클 관리의 중요성: 5계층 세션 관리에서 식별자의 생명주기(발급→인증 시 갱신→파기)가 명확히 분리되지 않을 때 시스템 전체의 인증 체계가 무너질 수 있음을 확인하였습니다 2. 심층 방어 전략: 단순히 네트워크 단의 방화벽에 의존하기보다, 애플리케이션 레벨의 **세션 재발급(Regeneration)**과 같은 안전한 프로그래밍 기법이 병행되어야 함을 입증 하였습니다 |






