STAGE 3
1) Cookie & Session
HTTP 프로토콜 특징
- Connectionless: 하나의 요청에 하나의 응답을 한 후 연결을 종료
- Stateless: 통신이 끝난 후 정보를 저장하지 않는 것- 위 두 가지 특성을 갖는 HTTP에서 상태를 유지하기 위해 쿠키 사용
쿠키 (Cookie)
- Key와 Value로 이루어진 일종의 단위
- 서버가 클라이언트에게 쿠키를 발급하면 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 같이 전송
- 서버는 클라이언트의 요청에 포함된 쿠키로 클라이언트 구분
- 클라이언트의 정보 기록, 상태 정보 표현 용도로 사용
쿠키 변조
- 악의적인 클라이언트는 쿠키 정보를 변조하여 서버에 요청 가능
- 별다른 검증 없이 쿠키를 통해 이용자의 인증 정보를 식별할 경우 타 이용자 사칭으로 정보 탈취 가능
세션 (Session)
- 쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위함
- 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 키를 만들어 클라이언트에 전달하는 방식
- 브라우저는 해당 키를 쿠키에 저장, 이후 HTTP 요청을 보낼 때 사용
- 서버는 요청에 포함된 키에 해당하는 데이터로 인증 상태 확인
- 키: Session ID
1. 다음 중 세션이 인증 정보를 저장하는 곳은?
→ 서버
[풀이] 세션은 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 키를 만들어 클라이언트에 전달하는 방식으로 작동한다.
2. 다음 중 서버에 요청을 보내는 역할을 하는 것은?
→ 클라이언트
[풀이] 클라이언트가 쿠키를 변조하여 서버에 요청을 보낼 수 있다.
3. 통신이 끝난 후 상태 정보를 저장하지 않는 특성을 가리키는 용어는?
→ stateless
[풀이] stateless는 통신이 끝난 후 상태 정보를 저장하지 않는 것을 의미하며 이전 연결에서 사용한 데이터를 다른 연결에서 요구할 수 없다.
2) Same Origin Policy
1. 다음 중 SOP의 동일 출처 기준을 판단하는 URI의 요소는? (모두 선택)
→ Host, Port, Schema
[풀이] Origin은 프로토콜(Schema), 포트(Port), 호스트(Host)로 구성되며, 이 구성 요소가 모두 일치하면 동일한 Origin이라고 한다.
2. 다음 중 SOP의 제한을 완화하여 다른 Origin의 웹 리소스를 가져오는 방식은?
→ CORS
[풀이] Cross Origin Resource Sharing의 약자로, 교차 출처 리소스 공유를 의미한다. 사이트들의 오리진이 다를 때 SOP를 적용받지 않고 리소스를 공유할 수 있는 방법이다.
3. 다음 중 CORS 헤더 방식에서 HTTP 메소드 중 OPTIONS를 통해 수신측 웹 리소스의 접근 관련 질의를 하는 과정은?
→ CORS preflight
[풀이] CORS preflight란 수신측에 웹 리소스를 요청해도 되는지 질의하는 과정을 의미한다.
4. 다음 중 SOP는 어디로부터 온 데이터를 브라우저가 읽지 못하게 하는 정책인가?
→ Cross Origin
[풀이] SOP는 Cross Origin이 아닌 Same Origin일 때만 정보를 읽을 수 있도록 해준다. 외부 출처에서 불러온 데이터를 읽으려고 할 때는 오류가 발생하여 읽을 수 없다. (데이터를 쓰는 것은 문제 없이 동작)
[Flag 찾기] Cookie
해당 문제는 쿠키로 인증 상태를 관리하는 간단한 로그인 서비스이다.
admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있음
(연습용으로 출제된 문제)
문제 파일로 Python 파일이 주어졌다.
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
users = {
'guest': 'guest',
'admin': FLAG
}
@app.route('/')
def index():
username = request.cookies.get('username', None)
if username:
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')
return render_template('index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
try:
pw = users[username]
except:
return '<script>alert("not found user");history.go(-1);</script>'
if pw == password:
resp = make_response(redirect(url_for('index')) )
resp.set_cookie('username', username)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
app.run(host='0.0.0.0', port=8000)
1. 접속 정보에 주어진 링크에 접속하기
2. 접속한 사이트의 초기 화면
3. 로그인 화면에서 Python 코드에 주어진 guest 사용자로 로그인한다.
4. 로그인에는 성공했으나 admin이 아니라고 문장이 출력됨
5. F12 단축키로 개발자 도구를 열어 응용 프로그램 창을 띄운다.
6. username의 값을 admin으로 바꾼다.
7. 새로고침을 하면 admin으로 로그인이 되면서 Flag를 알려줌
8. Flag 입력
정답!
[Flag 찾기] Session-basic
해당 문제는 쿠키와 세션으로 인증 상태를 관리하는 간단한 로그인 서비스이다.
admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있음
문제 파일로 Python 파일이 주어졌다.
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
users = {
'guest': 'guest',
'user': 'user1234',
'admin': FLAG
}
# this is our session storage
session_storage = {
}
@app.route('/')
def index():
session_id = request.cookies.get('sessionid', None)
try:
# get username from session_storage
username = session_storage[session_id]
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"}')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
try:
# you cannot know admin's pw
pw = users[username]
except:
return '<script>alert("not found user");history.go(-1);</script>'
if pw == password:
resp = make_response(redirect(url_for('index')) )
session_id = os.urandom(32).hex()
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
@app.route('/admin')
def admin():
# what is it? Does this page tell you session?
# It is weird... TODO: the developer should add a routine for checking privilege
return session_storage
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'
print(session_storage)
app.run(host='0.0.0.0', port=8000)
* 코드 파일에서 app.route()로 힌트를 얻을 수 있었다.
초기 사이트는 '/', 로그인 화면은 '/login'
그 다음으로 /admin이 주어져있으므로 이것을 활용하는 것이라고 생각함
1. 접속 정보에 주어진 링크로 접속하기
2. 로그인 화면에서 Python 코드에 주어진 user 사용자로 로그인한다.
3. 로그인에는 성공했으나 admin이 아니라고 문장이 출력됨
4. F12 단축키로 개발자 도구를 열어 응용 프로그램 창을 띄운다.
5. URL 주소 수정 (/admin 활용)
6. 수정한 주소로 접속하면 세션 값이 출력된다.
7. admin 사용자의 세션 값을 복사한다.
8. sessionid의 값을 위에서 복사한 admin의 세션 값으로 수정한다.
9. 새로고침을 하면 admin으로 로그인이 되면서 Flag를 알려줌
10. Flag 입력
정답!
'Dreamhack > Web Hacking' 카테고리의 다른 글
[Web Hacking] STAGE 7 (0) | 2022.08.19 |
---|---|
[Web Hacking] STAGE 6 (0) | 2022.08.11 |
[Web Hacking] STAGE 5 (0) | 2022.08.04 |
[Web Hacking] STAGE 4 (0) | 2022.07.25 |
[Web Hacking] STAGE 2 (0) | 2022.07.20 |