
웹 서버는 수많은 클라이언트와 HTTP 프로토콜을 사용해 통신한다
게스트 계정으로 로그인할 경우와 관리자 계정으로 로그인했을 때 다른 서비스를 제공할 수 있다
웹 서버는 수많은 클라이언트를 어떻게 구별하고 서로 다른 결과를 반환해주느냐
HTTP 프로토콜로 웹 서버와 통신할 때에는 웹 서버에 명령을 내리기 위해 GET, POST와 같은 메소드와 자원의 위치를 가리키는 URL 등이 포함되어 있다
이외에도 헤더(Header) 를 통해서 웹 서버에게 요청을 보내고, 웹 서버는 헤더를 읽고 클라이언트에게 결과 값을 반환한다
이때, 헤더에는 클라이언트의 정보와 요청의 내용을 구체화하는 등의 데이터가 포함되는데, 클라이언트의 인증 정보 또한 포함될 수 있다
클라이언트의 인증 정보를 포함하고 있는 Cookie와 Session
Connectionless: 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것
특정 요청에 대한 연결은 이후의 요청과 이어지지 않고 새 요청이 있을 때 마다 항상 새로운 연결을 맺는다
Stateless: 통신이 끝난 후 상태 정보를 저장하지 않는 것
이전 연결에서 사용한 데이터를 다른 연결에서 요구할 수 없다
따라서 이런 HTTP에서 상태를 유지하기 위해 쿠키(Cookie)가 탄생함
쿠키는 Key와 Value로 이뤄진 일종의 단위로, 서버가 클라이언트에게 쿠키를 발급하면, 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 같이 전송한다(자동으로 보내진다)
이때, 서버는 헤더로 날라온 쿠키를 확인해 클라이언트를 구분한다
일반적으로 쿠키는 클라이언트의 정보 기록과 상태 정보를 표현하는 용도로 사용된다
웹 서비스 사용 시 종종 등장하는 팝업 창에 “다시 보지 않기”, “7일 간 표시하지 않기” 웹 서버는 각 클라이언트의 팝업 옵션을 기억하기 위해 쿠키에 해당 정보를 기록하고, 쿠키를 통해 팝업 창 표시 여부를 판단한다
과거에는 클라이언트의 정보를 저장하기 위해 쿠키가 종종 사용되었다
쿠키는 서버와 통신할 때마다 전송되기 때문에 쿠키가 필요 없는 요청을 보낼 때는 리소스 낭비가 발생할 수 있다
쿠키만이 데이터를 클라이언트 측에 저장할 수 있는 유일한 방법이었을 때는 이 방법이 타당했지만, 다음과 같은 제약이 있다
4KB의 데이터 저장 제한
쿠키는 매 HTTP요청에 포함되어 있어 웹을 느려지게 하는 원인이 되었음
같은 쿠키는 도메인 내의 모든 페이지에 같이 전달 됨
HTTP 요청에 암호화 되지 않고 보내기 때문에 보안에 취약함
쿠키는 사용자의 로컬에 텍스트로 저장 되어있어 쉽게 접근, 내용 확인이 가능함
이와 같은 쿠키의 문제점을 보완하기 위해 Modern APIs의 종류인 Web Storage APIs를 통해 데이터를 저장하는 방식을 권장한다
https://park-answer.netlify.app/2019-12-29-web-storage-api/
많은 웹 사이트에서는 회원 가입과 로그인을 통해 개개인에게 맞춤형 서비스를 제공한다 웹 서버에서는 수많은 클라이언트의 로그인 상태와 이용자를 구별해야 하는데, 이때 클라이언트를 식별할 수 있는 값을 쿠키에 저장해 사용한다


중국집 식당에서 탕수육 이벤트를 쿠폰을 발행해 방문할 때 마다 도장을 찍어주는 방식으로 진행하고 있습니다. 도장은 식당이 찍어주지만 쿠폰은 손님이 보관하기 때문에 손님은 쿠폰을 마음대로 할 수 있습니다. 만약 나쁜 마음을 품은 손님이 식당에서 사용하는 도장과 비슷한 도장을 구해 직접 쿠폰에 가짜 도장을 찍게 된다면 식당에서 이를 구분할 방법이 없습니다.
쿠키는 클라이언트의 브라우저(크롬, 네이버)에 저장되고 요청에 포함되는 정보
따라서, 악의적인 클라이언트는 쿠키 정보를 변조해 서버에 요청을 보낼 수 있다
만약 서버가 별다른 검증 없이 쿠키를 통해 이용자의 인증 정보를 식별한다면 공격자가 타 이용자를 사칭해 정보를 탈취할 수 있는 경우가 발생한다

웹 통신에서 클라이언트가 쿠키를 변조해 서버에 요청을 보낼 수 있다
쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위해 세션(Session) 을 사용한다
세션은 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 키(유추할 수 없는 랜덤한 문자열)를 만들어 클라이언트에 전달하는 방식으로 작동한다
해당 키를 일반적으로 Session ID라고 한다
브라우저는 해당 키를 쿠키에 저장하고 이후에 HTTP 요청을 보낼 때 사용
서버는 요청에 포함된 키에 해당하는 데이터를 가져와 인증 상태를 확인함
중국집 식당의 탕수육 이벤트 쿠폰 도장을 조작하는 손님이 생겼습니다. 손님이 갖고 있는 쿠폰은 손님이 조작할 수 있기 때문에 쿠폰에 도장을 찍지 않고 손님마다 랜덤한 문자열을 적은 쿠폰을 주었습니다. 손님이 쿠폰을 식당에 제시하면 식당에 보관중인 메모장에서 쿠폰에 적힌 문자열과 방문 횟수를 기록하는 방식으로 이벤트를 운영했습니다. 이 때문에 손님은 쿠폰에 적힌 랜덤한 문자열은 조작할 수 있지만 매장에 기록된 방문 횟수는 조작할 수 없게 되었습니다.
서버에 따로 저장된 클라이언트의 정보가 있기 때문에 클라이언트 측에서 쿠키를 조작한들 유효하지 않다

쿠키는 데이터 자체를 이용자가 저장하며, 세션은 서버가 저장한다는 차이가 있음
Q. 세션 아이디는 탈취 불가능한가?
가능함.
쿠키에는 클라이언트의 세션 정보가 저장되어 있고 서버는 이를 통해 이용자 식별하고 인증을 처리한다
공격자가 이용자의 쿠키를 훔칠 수 있으면 세션에 해당하는 이용자의 인증 상태를 훔칠 수 있는데, 이를 세션 하이재킹 (Session Hijacking) 이라고 한다
쿠키를 훔치는 방법 = 세션을 훔치는 방법
1.드림핵 로그인 페이지에서 우클릭 후 검사를 클릭하고 Network 탭을 누릅니다. Preserve log를 체크하고 로그인을 하면 로그인 성공 시 응답을 볼 수 있습니다. 응답을 살펴보면, 서버에서 set-cookie 헤더를 통해 브라우저의 쿠키에 세션 정보를 저장하는 것을 볼 수 있습니다.
2.크롬 검사에서 Application을 누르고 Cookies 목록 안의 https://dreamhack.io 를 누르면 서버의 set-cookie 헤더를 통해 설정된 쿠키를 확인할 수 있습니다.
3.sessionid 헤더의 값을 메모장에 복사합니다. 이후 사진과 같이 sessionid 헤더의 값을 우클릭한 후 Delete를 클릭하면 브라우저의 쿠키에 저장된 세션 값이 삭제됩니다. 세션 값을 삭제하고 드림핵 페이지를 새로고침하면 로그인이 풀려있는 것을 확인할 수 있습니다.
4.쿠키의 빈 칸을 더블 클릭해 sessionid 헤더를 추가하고, 이전에 복사한 세션 값을 입력하면 브라우저의 쿠키에 세션 값이 설정됩니다. 세션 값을 설정하고 드림핵 페이지를 새로고침하면 로그인이 되는 것을 확인할 수 있습니다.
쿠키는 클라이언트에 저장되기 때문에 클라이언트는 저장된 쿠키를 조회, 수정, 추가할 수 있습니다. 클라이언트가 서버에 요청을 보낼 때 저장된 쿠키를 요청 헤더에 넣어 전송하기 때문에 이용자가 요청을 보낼 때 쿠키 헤더를 변조할 수 있습니다. 쿠키를 설정할 때에는 만료 시간을 지정할 수 있고, 만료 시간 이후에는 클라이언트에서 쿠키가 삭제됩니다. 쿠키의 만료는 클라이언트(브라우저)에서 관리됩니다.
쿠키는 서버와 클라이언트 둘 다 설정할 수 있습니다.

크롬 Console을 활용하는 법
크롬 페이지에서 우클릭했을 때 표시되는 검사 버튼을 누른 후 Console 탭을 누릅니다. document.cookie를 입력하면 쿠키 정보를 확인할 수 있습니다.
쿠키 옵션(HttpOnly)에 따라 자바스크립트에서 쿠키 확인이 불가능 할 수 있습니다.

크롬 페이지에서 우클릭했을 때 표시되는 검사 버튼을 누른 후 Application 탭을 누릅니다. 좌측에 나열된 목록에서 Cookies를 펼치면 Origin 목록을 확인할 수 있습니다. Origin(https://dreamhack.io)을 누르면 설정 된 쿠키 정보를 확인 / 수정할 수 있습니다.


쿠키에는 인증 상태를 나타내는 민감한 정보가 보관되며, 브라우저 내부에 저장된다
그리고 브라우저가 웹 서비스에 접속할 때 브라우저는 자동으로 쿠키를 헤더에 포함시켜 요청을 보낸다
이 덕분에 우리는 포털 사이트, SNS와 같은 웹 서비스에 한 번 로그인한 후 일정 기간은 로그인하지 않고도 바로 서비스를 사용할 수 있다
하지만 이용자가 악의적인 페이지를 접속했을 때, 페이지가 자바스크립트를 사용해 이용자의 SNS 웹 서비스로 요청을 보낸다면?
브라우저는 요청을 보낼 때 헤더에 해당 웹 서비스 쿠키를 포함시킴
따라서 자바스크립트로 요청을 보낸 페이지는 로그인 된 이용자의 SNS 응답을 받을 것이다
이에 더해 마음대로 페이지 접속자의 SNS에 글을 올리거나, 삭제하고, SNS 메신저를 읽는 것도 가능할 것
이와 같은 문제를 방지하기 위해 동일 출처 정책, Same Origin Policy (SOP) 보안 메커니즘이 탄생함
실제로 클라이언트 사이드 공격은 이 SOP를 우회하기 위한 것
잠재적으로 해로울 수 있는 문서를 분리해, 공격받을 수 있는 경로를 줄인다
Q. 같은 출처라고 해서 악의적인 사이트로부터의 공격이 없는 건 아닌데 그냥 확률적으로 낮추려고 하는 건가
오리진은 프로토콜 (Protocol, Scheme), 포트 (Port), 호스트 (Host) 로 구성됨


이미지나 자바스크립트, CSS 등의 리소스를 불러오는
<img>, <style>, <script>
등의 태그는 SOP의 영향을 받지 않는다
외에도 웹 서비스에서 동일 출처 정책인 SOP를 완화하여 다른 출처의 데이터를 처리 해야 하는 경우가 있다
위와 같은 상황에서 자원을 공유하기 위해 사용할 수 있는 공유 방법이 교차 출처 리소스 공유 (Cross Origin Resource Sharing, CORS)
교차 출처의 자원을 공유하는 방법은 CORS와 관련된 HTTP 헤더를 추가하여 전송하는 방법, JSON with Padding (JSONP) 방법을 통해 CORS를 대체하는 방법 등.
CORS는 HTTP 헤더에 기반하여 Cross Origin 간에 리소스를 공유하는 방법
발신측에서 CORS 헤더를 설정해 요청하면, 수신측에서 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정
지금까지 했던 reflected와는 달리 stored방식은 공격자가 서버에 HTML 태그를 저장시키고 이후에 사용자가 해당 태그에 저장된 페이지를 열람할 경우 공격자의 태그가 실행되는 방식이다
<form action="/bWAPP/htmli_post.php" method="POST">
<p><label for="firstname">First name:</label><br>
<input type="text" id="firstname" name="firstname"></p>
<p><label for="lastname">Last name:</label><br>
<input type="text" id="lastname" name="lastname"></p>
<button type="submit" name="form" value="submit">Go</button>
</form>
를 textarea에 입력해 submit한다
생성된 form에
<h1>SUCCESS</h1> <img src="http://[ip]/bWAPP/images/bee_1.png>
를 입력해 데이터를 보내면 된다
form 태그를 입력해도 form이 생기지 않고 글자 그대로 반환된다
/var/www/bWAPP/htmli_stored.php를 봤을 때 medium은 xss_check_3() 함수에서 입력값을 처리하는 걸 알 수 있다 이 함수의 내용은 functions_external.php에서 확인할 수 있다
xss_check_3() 를 보면 htmlspecialchars() 함수를 이용하여 HTML에서 사용하는 < > 등을 필터링하고 있기 때문에 html 태그 적용이 불가능하다