김승현

[Dreamhack : Web] session-basic 본문

Web/Dreamhack : Web

[Dreamhack : Web] session-basic

kshind 2023. 2. 21. 21:37

문제

쿠키와 세션으로 인증해서 로그인 서비스를 제공하는 사이트이고 admin 계정으로 로그인하면 flag를 얻을 수 있다고 한다.

flag의 형식은 DH{}이다.

 

dreamhack 문제는 코드 하나하나 보면서 어떤 역할을 하는지도 기록하면서 완전히 공부한 거 기록하는 느낌으로

쓰려고 합니다. 그러다 보니까 보기에는 여기 갔다가 저기 갔다가 되게 혼란스러울 수도 있습니다! 

그리고 만약 읽으실 때 제가 찾아보긴 하지만 대부분의 코드 분석은 추측입니다..!

특히 ...인 것 같다와 같은 문장은 정말로 추측입니다.

 

풀이

사이트에 접속하면이런 식으로 home, about Login 메뉴와 Welcome!이라는 문장이 뜬다.

Home과 About을 눌렀을 땐 아무 반응 없고 Login을 누르면 Login할 수 있는 페이지로 이동한다.

주소는 host3.dreamhack.games:포트/login path가 login으로 되어있다. 

이건 사이트의 코드를 개발자도구 - Elements로 봤을 때 나타나는 화면이다. 초록색 주석들을 보면 기본 계정으로

id :guest

password : guest

와 같이 주어졌다. 저대로 한번 로그인을 해보자. 

guest/guest로 로그인 하면 인사를 하고 우리는 admin이 아니라고 뜬다. cookie를 확인해보자.

개발자 도구 - Application을 하고 Cookies에 있는 걸 더블클릭 해보니까 sessionid가 있고 값이 있다.

지금은 guest로 로그인 했기 때문에 guest의 sessionid 값일 것이다. 로그인 하기 위해서 admin의 sessionid 값을 찾아서

저기에 붙여넣기를 하고 새로고침을 하면 admin으로 로그인해서 flag를 얻을 수 있을 것이다. 이젠 다운로드 파일을 보자.

홈페이지에 있는 다운로드 파일을 보면 일단 flask 프레임워크를 이용해서 제작한 것을 알 수 있다.

파이썬의 기본 문법인 try except 예외처리 구문으로 FLAG = open....read()에서 오류가 발생하면

FLAG를 출력하는 방식으로 오류를 방지했는 것 같다.

users 딕셔너리에 guest의 value엔 guest를 user엔 user1234를 admin엔 FLAG가 있는데 id, pw 같아서 로그인 해봤다.

user/user1234로 로그인 하니까 로그인이 된 걸 보니 users 변수는 아이디, 비밀번호를 저장하는 변수이다.

그리고 코드 젤 밑 session_storage는 이름 그대로 session을 저장하는 변수인 것 같다.

app.route('/')

app.route는 데코레이터라고 하며 함수에서 함수자체를 인자로 받아서 명령을 실행한 뒤

다시 함수의 형태로 반환하는 거라고 한다. 

www.naver.com로 예시를 들면
app.route('/')의 경우 www.naver.com/에 에 대한 내용을 말한다. 

app.route('/login') 경우 www.naver.com/login

 

그 함수 아래 들여쓰기 된 내용들은 그 경로로 들어갔을 때 발생하는 이벤트를 알려준다.

기본적인 host3.dreamhack.games/에 들어가면 session_id 변수에 쿠키의 sessionid를 요청하고 받아서  저장하는 것 같다.

username 변수에 session_storage[session_id] 리스트의 내용을 저장하는데 여기서 에러가 발생하면

index.html의 템플릿을 보여주는 것 같다.

만약 에러가 없으면 username이 addmin일 경우 Hello {username}, flag is FLAG를 출력, 아니면 you aren`t admin 출력함.

 

app.route('/login')

login path에 대한 내용이다. request 하는 게 GET이면 login.html을 렌더링하고

POST면 username엔 우리가 사이트에 username을 요청해서 가져오고 password 변수엔 password를 요청해서 가져온다. 이때 pw변수엔 users[username]을 가져온다.

코드 초반의 users

 

코드 초반에 guest는 guest, user는 user1234이던 그 변수에서 가져온다는 거다.

여기서 에러가 발생하면 not found user 경고창을 출력하고 한 칸 뒤로 가게 한다.

만약 pw가 password와 일치하면 resp 변수에 make_response()를 저장한다고 하는데 make_response는 서벌 동작시킬 때

http status와 함께 원하는 값을 전송하기 쉽게 해주는 거라고 하는데 뭐 사이트 정보 그런 건가 보다..

session_id를 난수를 생성해서 저장하고 이 저장된 값을 위치로서 session_storage 변수 작용하게 하고 그 위치엔

username을 저장한다. 쉽게 설명하면 guest의 sessionid가 1234면 session_storage[1234]엔 guest가 저장됨.

resp.set_cookie... sessionid로 쿠키를 생성하는 거라고 한다.

 

app.route('/admin')

사이트에서 찾을 수 없던 admin이라는 path가 있다.

개발자의 노트 : 주석된 내용과 주석되지 않은 내용을 복습해라

sessionid는 sessionid를 가져와서 저장

username에 session_storage[session_id]에 저장 

근데 만약 이름이 admin이 아니면 그냥 index.html로 다시 보낸다. (index.html은 host3.dreamhack.games/인듯)

그리고 마지막엔 session_storage를 반환하길래 사이트에서 들어가 봐야겠다.

들어가보니까 session_storage 변수에 저장된 admin, guest, user의 session_id가 저장되어 있다. 만약 user나 guest를 

로그인하지 않았다면 admin만 있을 것이다. 어 근데 나는 admin을 로그인 한 적이 없는데 왜 admin이 있지...?라고 생각 할 수 있다. 이때 코드의 마지막 부분을 봐야 한다.

 

__name__ == __main__

if문의 경우 모듈을 import해서 사용하는 경우인지 직접 실행한 경우인지를 구분하기 위한 거라고 하는데

그냥 파일이 실행되면 실행되는 그런 거인 것 같다.

session_storage 임의의 위치에 admin을 저장하는 걸 볼 수 있다. 

그래서 우리가 로그인 하지도 않은 admin의 sessionid를 볼 수 있었던 거다!

 

admin의 sessionid

06f02bf50f2d9b660d6c84e134168d01890ecfe34498947fd0145975f613c1af

개발자 도구에서 sessionid를 admin의 sessionid로 고치 새로고침을 하면

짠 flag를 얻을 수 있다.

 


엄청 쉬운 문젠데 생각보다 시간이 엄청 오래 걸렸다...

작성 방식에 대해서 조금 더 고민 좀 해봐야 될 것 같다...ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

'Web > Dreamhack : Web' 카테고리의 다른 글

[Dreamhack : Web] csrf-1  (0) 2023.02.22
[Dreamhack : Web] xss-2  (0) 2023.02.22
[Dreamhack : Web] xss-1  (0) 2023.02.22
[Dreamhack : Web] cookie  (0) 2023.02.21
[Dreamhack : Web] devtools  (0) 2023.02.21