STAGE 3. Background: Cookie & Session
์ฟ ํค ๐ช
HTTP ํ๋กํ ์ฝ ํน์ง
1) Connectionless
: ํ๋์ ์์ฒญ์ ํ๋์ ์๋ต์ ํ ํ ์ฐ๊ฒฐ์ ์ข ๋ฃํ๋ ๊ฒ
2) Stateless
: ํต์ ์ด ๋๋ ํ ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ์ง ์๋ ๊ฒ
์ด๋ฌํ ํน์ฑ์ ๊ฐ๋ HTTP์์ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ฟ ํค๊ฐ ํ์ํจ.
์ฟ ํค
: Key์ Value๋ก ์ด๋ค์ง ์ผ์ข ์ ๋จ์๋ก, ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ฟ ํค๋ฅผ ๋ฐ๊ธํ๋ฉด, ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์์ฒญ์ ๋ณด๋ผ ๋๋ง๋ค ์ฟ ํค๋ฅผ ๊ฐ์ด ์ ์กํจ. ์๋ฒ๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ํฌํจ๋ ์ฟ ํค๋ฅผ ํ์ธํด ํด๋ผ์ด์ธํธ๋ฅผ ๊ตฌ๋ถํ ์ ์์.
: HTTP์์ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉํ๋ Key-Value ํํ์ ๊ฐ
์ฟ ํค์ ์ฉ๋
1) ํด๋ผ์ด์ธํธ์ ์ ๋ณด ๊ธฐ๋ก
ex) ์น ์๋ฒ๋ ๊ฐ ํด๋ผ์ด์ธํธ์ ํ์ ์ต์ ์ ๊ธฐ์ตํ๊ธฐ ์ํด ์ฟ ํค์ ํด๋น ์ ๋ณด๋ฅผ ๊ธฐ๋กํ๊ณ , ์ฟ ํค๋ฅผ ํตํด ํ์ ์ฐฝ ํ์ ์ฌ๋ถ๋ฅผ ํ๋จํจ
2) ํด๋ผ์ด์ธํธ์ ์ํ ์ ๋ณด ํํ
- ์น ์๋ฒ์์๋ ์๋ง์ ํด๋ผ์ด์ธํธ์ ๋ก๊ทธ์ธ ์ํ์ ์ด์ฉ์๋ฅผ ๊ตฌ๋ณํด์ผ ํ๋๋ฐ, ์ด๋ ํด๋ผ์ด์ธํธ๋ฅผ ์๋ณํ ์ ์๋ ๊ฐ์ ์ฟ ํค์ ์ ์ฅํด ์ฌ์ฉํจ
์ฟ ํค๊ฐ ์๋ ํต์ ์ ๊ฒฝ์ฐ
์ฟ ํค๊ฐ ์๋ ํต์ ์ ๊ฒฝ์ฐ
์ฟ ํค๋ ํด๋ผ์ด์ธํธ์ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋๊ณ ์์ฒญ์ ํฌํจ๋๋ ์ ๋ณด์.
๋ฐ๋ผ์ ์ ์์ ์ธ ํด๋ผ์ด์ธํธ๋ ์ฟ ํค ์ ๋ณด๋ฅผ ๋ณ์กฐํด ์๋ฒ์ ์์ฒญ์ ๋ณด๋ผ ์ ์์.
ex) ๊ณต๊ฒฉ์๊ฐ ํ ์ด์ฉ์ ์ฌ์นญํด ์ ๋ณด ํ์ทจ
์ธ์
: ์ฟ ํค์ ์ธ์ฆ ์ํ๋ฅผ ์ ์ฅํ์ง๋ง ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ณ์กฐํ ์ ์๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉํจ.
: ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ์ฅํ๊ณ ํด๋น ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ ํค(์ ์ถํ ์ ์๋ ๋๋คํ ๋ฌธ์์ด)๋ฅผ ๋ง๋ค์ด ํด๋ผ์ด์ธํธ์ ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก ์๋ํจ. ํด๋น ํค๋ฅผ ์ผ๋ฐ์ ์ผ๋ก Session ID๋ผ๊ณ ํจ. ๋ธ๋ผ์ฐ์ ๋ ํด๋น ํค๋ฅผ ์ฟ ํค์ ์ ์ฅํ๊ณ ์ดํ์ HTTP ์์ฒญ์ ๋ณด๋ผ ๋ ์ฌ์ฉํจ. ์๋ฒ๋ ์์ฒญ์ ํฌํจ๋ ํค์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์ธ์ฆ ์ํ๋ฅผ ํ์ธํจ.
: ์ฟ ํค์ ํฌํจ๋ Session ID๋ฅผ ์ฌ์ฉํด ์๋ฒ์ ์ ์ฅ๋ ์ธ์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ๋ฐฉ์
์ฟ ํค vs. ์ธ์
์ฟ ํค - ๋ฐ์ดํฐ ์์ฒด๋ฅผ ์ด์ฉ์๊ฐ ์ ์ฅํจ
์ธ์ - ์๋ฒ๊ฐ ์ ์ฅํจ
์ฟ ํค ์ ์ฉ๋ฒ
์ฟ ํค๋ ํด๋ผ์ด์ธํธ์ ์ ์ฅ๋จ
-> ํด๋ผ์ด์ธํธ๊ฐ ์ ์ฅ๋ ์ฟ ํค๋ฅผ ์กฐํ, ์์ , ์ถ๊ฐํ ์ ์์. ๋ง๋ฃ ์๊ฐ ์ง์ ๋ ๊ฐ๋ฅ. ๋ง๋ฃ ์๊ฐ ์ดํ์๋ ํด๋ผ์ด์ธํธ์์ ์ฟ ํค๊ฐ ์ญ์ ๋จ.
์ฟ ํค๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๋ ๋ค ์ค์ ํ ์ ์์.
์๋ฒ - HTTP ์๋ต ์ค ํค๋์ ์ฟ ํค ์ค์ ํค๋(Set-Cookie)๋ฅผ ์ถ๊ฐํ๋ฉด ํด๋ผ์ด์ธํธ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ฟ ํค๋ฅผ ์ค์ ํจ.
HTTP/1.1 200 OK
Server: Apache/2.4.29 (Ubuntu)
Set-Cookie: name=test;
Set-Cookie: age=30; Expires=Fri, 30 Sep 2022 14:54:50
GMT;
...
ํด๋ผ์ด์ธํธ - ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด ์ฟ ํค๋ฅผ ์ค์ ํจ.
document.cookie = "name=test;"
document.cookie = "age=30; Expires=Fri, 30 Sep 2022 14:54:50 GMT;"
ํฌ๋กฌ Console ํ์ฉ
ํฌ๋กฌ Application ํ์ฉ
ํฌ๋กฌ ํ์ด์ง์์ ์ฐํด๋ฆญ - ๊ฒ์ฌ - Application ํญ - Cookies
์ฐ์ต: ๋๋ฆผํต ์ธ์
์ธ์ ํ์ด์ฌํน
: ํ ์ด์ฉ์์ ์ฟ ํค๋ฅผ ํ์ณ ์ธ์ฆ ์ ๋ณด๋ฅผ ํ๋ํ๋ ๊ณต๊ฒฉ. ๊ณต๊ฒฉ์๊ฐ ์ด์ฉ์์ ์ฟ ํค๋ฅผ ํ์น ์ ์์ผ๋ฉด ์ธ์ ์ ํด๋นํ๋ ์ด์ฉ์์ ์ธ์ฆ ์ํ๋ฅผ ํ์น ์ ์์.
STAGE 3. Exercise: Cookie
/
- ์ด์ฉ์์ username์ ์ถ๋ ฅํ๊ณ ๊ด๋ฆฌ์ ๊ณ์ ์ธ์ง ํ์ธํจ
- ์์ฒญ์ ํฌํจ๋ ์ฟ ํค๋ฅผ ํตํด ์ด์ฉ์๋ฅผ ์๋ณํจ
- ๋ง์ฝ ์ฟ ํค์ ์กด์ฌํ๋ username์ด admin์ผ ๊ฒฝ์ฐ FLAG๋ฅผ ์ถ๋ ฅํจ
/login
- username, password๋ฅผ ์ ๋ ฅ๋ฐ๊ณ ๋ก๊ทธ์ธํจ
- GET : username๊ณผ password๋ฅผ ์ ๋ ฅํ ์ ์๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ์ ๊ณตํจ
- POST : ์ด์ฉ์๊ฐ ์ ๋ ฅํ username๊ณผ password ์ ๋ ฅ ๊ฐ์ users ๋ณ์ซ๊ฐ๊ณผ ๋น๊ตํจ
์ทจ์ฝ์ ๋ถ์
- ์ด์ฉ์์ ๊ณ์ ์ ๋ํ๋ด๋ username ๋ณ์๊ฐ ์์ฒญ์ ํฌํจ๋ ์ฟ ํค์ ์ํด ๊ฒฐ์ ๋์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํจ. ์ฟ ํค๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ํฌํจ๋๋ ์ ๋ณด๋ก, ์ด์ฉ์๊ฐ ์์๋ก ์กฐ์ํ ์ ์์. ์๋ฒ๋ ๋ณ๋ค๋ฅธ ๊ฒ์ฆ ์์ด ์ด์ฉ์ ์์ฒญ์ ํฌํจ๋ ์ฟ ํค๋ฅผ ์ ๋ขฐํ๊ณ , ์ด์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ณํ๊ธฐ ๋๋ฌธ์ ๊ณต๊ฒฉ์๋ ์ฟ ํค์ ํ ๊ณ์ ์ ๋ณด๋ฅผ ์ฝ์ ํด ๊ณ์ ์ ํ์ทจํ ์ ์์.
์ต์คํ๋ก์
- ์ฟ ํค์ ์กด์ฌํ๋ username์ admin ๋ฌธ์์ด๋ก ์กฐ์ํด์ผ ํจ. ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฟ ํค์ ์ ๋ณด๋ฅผ ํ์ธํ๊ฑฐ๋ ์์ ๊ฐ๋ฅํจ. username์ admin์ผ๋ก ๋ณ๊ฒฝํด ์๋ฒ์ ์์ฒญํ๋ฉด FLAG ํ๋ ๊ฐ๋ฅ.
>>> Cookie ๋ฌธ์ ๋ฅผ ํตํด, ์๋ฒ๊ฐ ๊ฒ์ฆ ์์ด ์ฟ ํค๋ฅผ ์ ๋ขฐํ๊ณ ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ณํ ๋ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์ ์ ๋ํด์ ์์๋ณด์์. ํด๋น ์ทจ์ฝ์ ์ ์ด์ฉํ์ฌ ๋ค๋ฅธ ๊ณ์ ์ ๊ถํ์ ํ๋ํ ์ ์์์.
>>> ์ด๋ฌํ ๋ฌธ์ ์ ์ ์ธ์ ์ ์ฌ์ฉํด ํด๊ฒฐํ ์ ์์. ์ธ์ ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ์ฅํ๊ณ , ๋๋คํ ํค๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ๊ธํจ. ํด๋ผ์ด์ธํธ๋ ํด๋น ํค๋ฅผ ํฌํจํด ์๋ฒ์ ์์ฒญํ๊ณ , ์๋ฒ๋ ์ ์ฅํ ์ธ์ ํค์ ๋์ํ๋ ํด๋ผ์ด์ธํธ์ธ์ง ํ์ธํ๋ฏ๋ก ์์ ํ ์๋น์ค๋ฅผ ๊ตฌํํ ์ ์์.
STAGE 3. cookie
#!/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)
admin์ผ๋ก ๋ก๊ทธ์ธํ๋ฉด FLAG๊ฐ ์ถ๋ ฅ๋๋ ๊ฒ ๊ฐ๋ค.
users ๋์ ๋๋ฆฌ๋ฅผ ๋ณด๊ณ , username guest, password guest๋ก ๋ก๊ทธ์ธ์ ์๋ํด๋ดค๋ค.
๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์ฟ ํค๋ฅผ ์ดํด๋ณด๋ฉด,
index() ๋ฅผ ๋ณด๋ฉด, username ์ ์ฟ ํค ๊ฐ์์ ๊ฐ์ ธ์ค๊ณ ์์ผ๋ฏ๋ก, ์ฟ ํค ๊ฐ์ admin์ผ๋ก ๋ฐ๊ฟ๋ณด์๋ค.
์๋ก๊ณ ์นจํ ๊ฒฐ๊ณผ, ํ๋๊ทธ๋ฅผ ์ป์ ์ ์์๋ค.
STAGE 3. session-basic
์ฟ ํค์ ์ธ์ ์ผ๋ก ์ธ์ฆ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ๋จํ ๋ก๊ทธ์ธ ์๋น์ค์ ๋๋ค.
admin ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด ํ๋๊ทธ๋ฅผ ํ๋ํ ์ ์์ต๋๋ค.
#!/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 = { #3๊ฐ์ ๊ณ์
'guest': 'guest',
'user': 'user1234',
'admin': FLAG
}
session_storage = {
}
@app.route('/')
def index():
session_id = request.cookies.get('sessionid', None)
try:
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:
pw = users[username] #์
๋ ฅ๋ฐ์ username์ ํจ์ค์๋๋ฅผ pw์ ์ ์ฅ
except:
return '<script>alert("not found user");history.go(-1);</script>'
if pw == password: #ํจ์ค์๋๊ฐ ์ผ์นํ ๊ฒฝ์ฐ
resp = make_response(redirect(url_for('index')) ) #index๋ก ์๋ต ๋ง๋ค๊ธฐ
session_id = os.urandom(32).hex() #๋์ ์์ฑ ํ hex ๊ฐ์ session_id์ ์ ์ฅ
session_storage[session_id] = username #๋ก๊ทธ์ธํ username์ ์ธ์
์ค์
resp.set_cookie('sessionid', session_id) #์ฟ ํค ์์ฑ
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
@app.route('/admin')
def admin():
return session_storage
if __name__ == '__main__':
import os
session_storage[os.urandom(32).hex()] = 'admin' #admin์ ์ธ์
์ค์
print(session_storage)
app.run(host='0.0.0.0', port=8000)
session_storage[session_id]๊ฐ admin๊ณผ ๊ฐ์ ๋ FLAG ์ถ๋ ฅ.
pw == password ์ผ ๋ index
set_cookie() ๋ก ์ด๋ฆ์ด session_id ์ด๊ณ ๊ฐ์ด ๋ฌธ์์ด session_id ์ธ ์ฟ ํค๋ฅผ ์์ฑ
@ : ์ฅ์์(decorator)๋ฅผ ๋ํ๋ด๋ฉฐ, flask์์ url ์ฐ๊ฒฐ์ ํ์ฉ๋จ
/admin ์ ์ ๊ทผํ๋ฉด session_storage ๋ฅผ ๋ฆฌํดํจ
guest๋ก ๋ก๊ทธ์ธ
/admin์ผ๋ก ์ด๋
user๋ก ๋ก๊ทธ์ธ
์ฟ ํค ๊ฐ์ ๋ณ๊ฒฝ
์๋ก๊ณ ์นจ ํ, ํ๋๊ทธ๊ฐ ์ถ๋ ฅ๋์๋ค.
STAGE 3. Mitigation: Same Origin Policy
๋ธ๋ผ์ฐ์ ๊ฐ ์น ์๋น์ค์ ์ ์ํ ๋ ๋ธ๋ผ์ฐ์ ๋ ์๋์ผ๋ก ์ฟ ํค๋ฅผ ํค๋์ ํฌํจ์์ผ ์์ฒญ์ ๋ณด๋
-> ํฌํธ ์ฌ์ดํธ, SNS์ ๊ฐ์ ์น ์๋น์ค์ ํ ๋ฒ ๋ก๊ทธ์ธํ ํ ์ผ์ ๊ธฐ๊ฐ์ ๋ก๊ทธ์ธํ์ง ์์๋ ๋ฐ๋ก ์๋น์ค ์ฌ์ฉ ๊ฐ๋ฅ
์ ์์ ์ธ ํ์ด์ง๊ฐ ํด๋ผ์ด์ธํธ์ ๊ถํ์ ์ด์ฉํด ๋์ ์ฌ์ดํธ์ HTTP ์์ฒญ์ ๋ณด๋ด๊ณ , HTTP ์๋ต ์ ๋ณด๋ฅผ ํ๋ํ๋ ์ฝ๋๋ฅผ ์คํํ ์ ์์ -> ์ ๋ณด ์ ์ถ๊ณผ ๊ฐ์ ๋ณด์ ์ํ์ด ์๊ธธ ์ ์๋ ์์๊ฐ ๋จ.
๋ฐ๋ผ์ ํด๋ผ์ด์ธํธ๋ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ์ ์์ ์ธ ํ์ด์ง์์ ์ฝ์ ์ ์๋๋ก ํด์ผ ํจ.
๋์ผ ์ถ์ฒ ์ ์ฑ (Same Origin Policy, SOP)
: ํ์ฌ ํ์ด์ง์ ์ถ์ฒ๊ฐ ์๋ ๋ค๋ฅธ ์ถ์ฒ๋ก๋ถํฐ ์จ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ง ๋ชปํ๊ฒ ํ๋ ๋ธ๋ผ์ฐ์ ์ ๋ณด์ ๋ฉ์ปค๋์ฆ
- Same Origin์ผ ๋๋ง ์ ๋ณด๋ฅผ ์ฝ์ ์ ์๋๋ก ํด์ค
- ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ๊ฒ์ ๋ฌธ์ ์์ด ๋์ํจ
ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๊ณต๊ฒฉ
: SOP๋ฅผ ์ฐํํ๊ธฐ ์ํ ๊ณต๊ฒฉ
์ค๋ฆฌ์ง ๊ตฌ์ฑ ์์
1) ํ๋กํ ์ฝ (Protocol, Scheme)
2) ํฌํธ (Port)
3) ํธ์คํธ (Host)
>>> ๊ตฌ์ฑ ์์๊ฐ ๋ชจ๋ ์ผ์นํด์ผ ๋์ผํ ์ค๋ฆฌ์ง
ex) https://same-origin.com/ ๊ณผ ๋น๊ต
https://same-origin.com/frame.html -> Path๋ง ๋ค๋ฅด๋ฏ๋ก Same Origin
https://cross.same-origin.com/frame.html -> Host๊ฐ ๋ค๋ฅด๋ฏ๋ก Cross Origin
* window.open()
: ์๋ก์ด ์ฐฝ์ ๋์ฐ๋ ํจ์
* object.location.href
: ๊ฐ์ฒด๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ url ์ฃผ์๋ฅผ ์ฝ์ด์ค๋ ์ฝ๋
๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (Cross Origin Resource Sharing, CORS)
: SOP์ ์ ํ์ ๋ฐ์ง ์๊ณ Cross Origin์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ก ํด์ฃผ๋ ๋ฉ์ปค๋์ฆ
์ง์ ์์ ์ฝ๋๋ค์ ๋ฐ๋ผ์ ํ์ดํ ํด๋ณด๋ฉด์ ํ๋์ฉ ์๋ฆฌ๋ฅผ ์ดํดํ๊ณ ๋์ด๊ฐ๋ ๊ฒ์ ์ถ์ฒํ๋ค๋๋ฐ ํ๋๋ ์ ํ์ฃต?ใ ใ
'Web' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Dreamhack] Web Hacking STAGE 5 (CSRF) (0) | 2022.02.07 |
---|---|
[Dreamhack] xss-2 (0) | 2022.02.06 |
[Dreamhack] Web Hacking STAGE 4 (XSS) (0) | 2022.01.30 |
[Dreamhack] Web Hacking STAGE 2 (0) | 2022.01.15 |
[bWAPP] SQL Injection (GET/Search) (0) | 2021.09.16 |