엔드포인트: /
아래 코드는 인덱스 페이지를 구성하는 코드입니다. 해당 페이지에서는 세션을 통해 이용자를 식별합니다. 먼저 쿠키의 sessionid의 값을 통해 session_storage에서 해당 Session ID의 username을 조회합니다.
index 페이지 코드
@app.route('/') # / 페이지 라우팅
def index():
session_id = request.cookies.get('sessionid', None) # 쿠키에서 sessionid 조회
try:
username = session_storage[session_id] # session_storage에서 해당 sessionid를 통해 username 조회
except KeyError:
return render_template('index.html')
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')
엔드 포인트: /admin
admin 페이지 코드는 관리자 페이지를 구성하는 코드입니다. developer’s note 아래 주석처리된 소스코드는 인덱스 페이지와 비슷한 구조로 세션을 통해 현재 접속한 이용자가 admin인지 확인하려고 했음을 볼 수 있습니다.
admin 세션 생성은 서비스 실행 시 os.urandom(32).hex()를 통한 무작위 값 생성을 통해 username이 admin인 세션 정보를 session_storage에 생성합니다. 해당 session_storage 정보를 조회할 수 있다면 무작위 값을 추론하지 않고도 곧바로 Session ID를 획득할 수 있음을 알 수 있습니다.
admin 페이지 코드
@app.route('/admin')
def admin():
# developer's note: review below commented code and uncomment it (TODO)
#session_id = request.cookies.get('sessionid', None)
#username = session_storage[session_id] session_storage에 저장된 username을 불러옴
#if username != 'admin': # username이 admin인지 확인
# return render_template('index.html')
return session_storage
admin 세션 생성
if __name__ == '__main__':
import os
# create admin sessionid and save it to our storage
# and also you cannot reveal admin's sesseionid by brute forcing!!! haha
session_storage[os.urandom(32).hex()] = 'admin' # username이 admin인 Session ID를 무작위로 생성
print(session_storage)
app.run(host='0.0.0.0', port=8000)
취약점 분석
admin 페이지 코드를 다시 살펴보면 전체 세션 정보가 포함된 session_storage는 username이 admin인 관리자만 조회할 수 있도록 의도되었습니다.
@app.route('/admin')
def admin():
# developer's note: review below commented code and uncomment it (TODO)
#session_id = request.cookies.get('sessionid', None)
#username = session_storage[session_id]
#if username != 'admin':
# return render_template('index.html')
# 인증을 수행하는 위의 코드가 주석처리되어 인증을 하지 않고도 session_storage 조회 가능
return session_storage
Same Origin Policy (SOP)
브라우저는 인증 정보로 사용될 수 있는 쿠키를 브라우저 내부에 보관합니다. 그리고 이용자가 웹 서비스에 접속할 때, 브라우저는 해당 웹 서비스에서 사용하는 인증 정보인 쿠키를 HTTP 요청에 포함시켜 전달합니다. 이와 같은 특징은 사이트에 직접 접속하는 것에만 한정되지 않습니다. 브라우저는 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 쿠키를 함께 전송하는 특징을 가지고 있습니다.
Same Origin Policy의 오리진 (Origin) 구분 방법
이제 브라우저가 가져온 정보의 출처인 오리진 (Origin)을 어떻게 구분하는지 알아보겠습니다. 먼저, 오리진은 프로토콜 (Protocol, Scheme), 포트 (Port), 호스트 (Host) 로 구성됩니다. 구성 요소가 모두 일치해야 동일한 오리진이라고 합니다
Same Origin Policy 실습
SOP는 Cross Origin이 아닌 Same Origin일 때만 정보를 읽을 수 있도록 해줍니다.
Same Origin
sameNewWindow = window.open('https://dreamhack.io/lecture');
console.log(sameNewWindow.location.href);
// 결과: https://dreamhack.io/lecture
Cross Origin
crossNewWindow = window.open('https://theori.io');
console.log(crossNewWindow.location.href);
// 결과: Origin 오류 발생
Cross Origin 데이터 읽기/쓰기
위와 같이 외부 출처에서 불러온 데이터를 읽으려고 할 때는 오류가 발생해 읽지 못합니다.
crossNewWindow = window.open('https://theori.io');
crossNewWindow.location.href = "https://dreamhack.io";
Same Origin Policy 제한 완화
SOP는 클라이언트 사이드 웹 보안에서 중요한 요소입니다. 하지만, 브라우저가 이러한 SOP에 구애 받지 않고 외부 출처에 대한 접근을 허용해주는 경우가 존재합니다. 예를 들면, 이미지나 자바스크립트, CSS 등의 리소스를 불러오는 <img>, <style>, <script> 등의 태그는 SOP의 영향을 받지 않습니다.
위 경우들 외에도 웹 서비스에서 동일 출처 정책인 SOP를 완화하여 다른 출처의 데이터를 처리 해야 하는 경우도 있습니다. 예를 들어 특정 포털 사이트가 카페, 블로그, 메일 서비스를 아래의 주소로 운영하고 있다고 합시다. 각 서비스의 Host가 다르기 때문에 브라우저는 각 사이트의 오리진이 다르다고 인식합니다.
Cross Origin Resource Sharing (CORS)
교차 출처 리소스 공유 (Cross Origin Resource Sharing, CORS)는 HTTP 헤더에 기반하여 Cross Origin 간에 리소스를 공유하는 방법입니다. 발신측에서 CORS 헤더를 설정해 요청하면, 수신측에서 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정합니다.
JSON with Padding (JSONP)
좀 전에 이미지나 자바스크립트, CSS 등의 리소스는 SOP에 구애 받지 않고 외부 출처에 대해 접근을 허용한다고 하였습니다. JSONP 방식은 이러한 특징을 이용해 <script> 태그로 Cross Origin의 데이터를 불러옵니다. 하지만 <script> 태그 내에서는 데이터를 자바스크립트의 코드로 인식하기 때문에 Callback 함수를 활용해야 합니다. Cross Origin에 요청할 때 callback 파라미터에 어떤 함수로 받아오는 데이터를 핸들링할지 넘겨주면, 대상 서버는 전달된 callback으로 데이터를 감싸 응답합니다.
Q1. 다음 중 CORS 헤더 방식에서 HTTP 메소드 중 OPTIONS를 통해 수신측 웹 리소스의 접근 관련 질의를 하는 과정은?
A. CORS preflight
Q2. 다음 중 SOP는 어디로부터 온 데이터를 브라우저가 읽지 못하게 하는 정책인가?
A.Cross Origin
Q3. 다음 중 SOP의 제한을 완화하여 다른 Origin의 웹 리소스를 가져오는 방식은?
A. CORS
Q4. 다음 중 SOP의 동일 출처 기준을 판단하는 URI의 요소는? (모두 선택)
A. Host, Port, Schema