김승현

[Dreamhack : Web] csrf-2 본문

Web/Dreamhack : Web

[Dreamhack : Web] csrf-2

kshind 2023. 2. 22. 15:15

문제

url을 확인하는 기능과 여러 기능이 구현된 서비스인데 여기에서 CSRF 취약점을 이용해서 플래그를 얻으라고 한다.

 

 

풀이

접속해보면 앞선 문제들을 섞은 듯이 vuln page, flag, login이 있고 please login이라고 출력되어있다. 일단 vuln부터 보자.

csrf-1 문제와 마찬가지로 필터링이 되어있는 것 같다. 다음 flag 페이지로 가보자.

지금까지 나온 flag 엔드포인트와는 딱히 다른 점이 없는 것 같다. login으로 가보자.

로그인 창이 있다. 이번엔 사이트의 코드를 보자.

딱히 주석으로 된 힌트는 없는 것 같으니까 이번엔 소스코드를 분석해보자.

코드 초반부

Flask, selenium의 webdriver, urllib, os를 import 했다.

 

app = Flask(__name__)으로 플라스크 객체 생성

app.secert_key변수에 unsigned random 값을 저장

 

FLAG 변수에 flag.txt를 읽어서 저장 만약 이 과정 중 오류가 발생하면 FLAG 변수에 [**FLAG**] 문자열 저장

 

users 딕셔너리에 name:value를 id:password로 이용해서 guest:guest와 admin:flag를 저장했다.

 

실제로 guest / guest로 로그인을 하면 guest 계정으로 로그인 할 수 있다.

 

마지막으론 session_storage 딕셔너리에(추측, 리스트일 수도 있지만 딕셔너리일 확률이 높음)로

아마도 cookie에서처럼 session_id : username 형식으로 저장할 것 같다.

 

라우트하는 부분 중 vuln부터 보도록 하자!

 

@app.route("/vuln") == https://host3.dreamhack.games/vuln 

param 변수에 사이트에서 입력받은 파라미터들을 저장

xss_filter 변수에 frame, script, on을 저장

xss_filter를 모두 돌면서 param에 위 셋 중 포함되는 게 있다면 *로 대체한다.

@app.route("login")  == https://host3.dreamhack.games/login

코드 전체

만약 메소드가 GET이라면,

render_template함수를 이용해서 login.html을 띄움.

만약 메소드가 POST라면,

username 변수에 사이트에서 전달받은 폼 username을 저장

password 변수에 사이트에서 잔달받은 폼 password를 저장

 

그리고 pw변수에 users[username]을 저장

만약 이 과정에서 실패한다면 not found user이라는 경고창을 띄우며 뒤로 보냄

users는 코드 초반부에 나온 딕셔너리, 그러니까 username에 guest나 admin이 아닌 id가 입력되면 not found user을 띄움

 

만약 pw (users 딕셔너리에 저장된 암호) == password (사이트에서 이용자가 입력한 암호)라면,

resp = index(host3.dreamhack.games/)의 주소값을 넘겨주도록 값을 저장

session_id 변수에 unsigned 랜덤값을 16진수로 저장 

session_storage[session_id]의 위치에 username을 저장

resp.set_cookie를 통해서 쿠키(sessionid)를 전달

그리고 마지막으로 username은 일치하지만 password가 틀릴 경우 wrong password 경고창 출력

 

 

위에서 나온 resp=index내용은 아래 /를 라우트한 것을 의미하는 것 같다.

↓↓↓↓↓↓

@app.route("/")  == https://host3.dreamhack.games/

session_id 변수에 사이트에서 요청해서 쿠키의 sessionid값을 저장

username = session_storage[session_id]값을 집어넣는데 에러가 발생하면 (= 로그인을 한 적이 없었다면),

→로그인을 하지 않았다면 해당하는 session_storage의 위치에 값이 없기 때문에 에러가 발생한다.

host3.dreamhack.games/에 please login이라는 text를 출력함

만약 로그인을 했는데 admin이라면,

Hello [유저이름], flag is "FLAG를 출력

만약 로그인을 했는데 admin이 아니라면,

you are not admin을 출력

 

@app.route("/change_password")  == https://host3.dreamhack.games/change_password

pw변수에 전달받은 pw값을 저장

session_id 변수에 전달받은 sessionid에 해당하는 쿠키값 저장

 

username에 session_storage[session_id]를 저장하는 데 실패하면 (= 로그인을 안 했으면) 

index.html로 가며 please login 출력

 

그게 아니라면 users 딕셔너리 내에 있는 우리가 입력한 username의 value값으로 pw를 저장

 

@app.route("/flag", methods=["GET", "POST"]) == host3.dreamhack.games/flag

메소드가 GET이라면 flag.html을 보여줌

메소드가 POST라면 아래의 코드들을 실행한다.

param 변수에 전달받은 param 파라미터(flag 엔드포인트에서 우리가 입력한 값)를 저장
session_id엔 unsigned 랜덤 값을 16진수로 저장
session_storage의 sessionid위치에 admin을 저장
만약 check_csrf 함수가 참이라면 wrong을 출력하고 아니라면 good을 출력함.

이때 check_csrf의 파라미터를 param 변수와 ,name엔 sessionid를, valye엔 session_id 변수값인 딕셔너리로 함

 

cehck_csrf()

url 변수에 http://127.0.0.1:8000/vuln?param=에다가 csrf가 발생할 수 있는 url로 변경한 param저장

마지막으로 read_url 함수를 반환하는데 url과 쿠키값 중 sessionid를 파라미터로 했다.

 

read_url()

 

cookie를 localhost로 업데이트 한다.

그리고 아래 webdriver이 적혀있는 코드는  selenium에서 사용하는 건데 크롬, 웨일 등등 다양한 환경을 테스트할 수 있게 해주는 그런 프레임 웹 자동화 프레임워크라고 한다.

대충 요약하면 해당 코드는 admin의 권한으로 localhost에서 우리가 입력한 주소로 접속을 하도록하는 것이다.

근데 실행 중 오류가 발생하면 return으로 False를 출력하고 오류가 없다면 True를 반환한다.

여기서 에레가 발생하면 False가 check_csrf로 가고, 그 false가 flag로 가서 not과 만나 true가 돼서 wrong을 출력한다.

 

코드 분석은 여기까지가 끝이다....!

 

우리가 집중해서 봐야 될 건 /change_password이다.

/flag 엔드포인트를 통해 전달하면 admin의 계정으로 localhost에서 해당 주소로 진입하는데 그렇다면 session_id엔 admin의 sessionid가 저장되고 username이 admin과 일치하고 sessionid도 admin의 sessionid일 테니까

try구문의 username = session_storage[session_id]를 무사히 넘길 수 있다.

그렇게 되면 users에 있는 admin의 password를 우리가 입력한 pw 값으로 바꿀 수 있다.

 

그렇다면 우리는 flag에 /change_password 엔드포인트와 pw를 명시해서 입력줘야 된다.

<img src="/change_password?pw=1">

위의 코드를 flag에 입력하면 admin의 비밀번호가 1로 바뀐다.

짠...! 

 


코드 분석을 하나하나 하니까 진짜 시간이 너무 오래 걸렸다.....방법을 다시 바꿀까 고민된다 흑흑

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

[Dreamhack : Web] mango  (0) 2023.02.22
[Dreamhack : Web ] simple_sqli  (0) 2023.02.22
[Dreamhack : Web] csrf-1  (0) 2023.02.22
[Dreamhack : Web] xss-2  (0) 2023.02.22
[Dreamhack : Web] xss-1  (0) 2023.02.22