1번은 오류가 나서 풀 수가 없었다.
주어진 id와 password로 접속한다.
접속했을 때의 request를 repeater에 가져온다.
loginUser를 admin으로 주어진 sessionID로 변경해 다시 request를 보내면 flag 값이 나오게 된다. SessionID를 알고 id를 알면 공격이 가능한 것을 보여준다.
링크를 타고 들어가면 step1.php가 맞이한다.
확인을 누르면 step2.php로 넘어간다. 관리자 인증을 위한 비밀번호가 필요하다.
하지만, 웹 페이지를 통해 step3.php로 넘어가면 인증없이 넘어갈 수 있다.
Fire 버튼을 누르면 flag값이 나오는 것을 알 수 있다. 해당 문제는 해당 페이지에 접근할 수 있는 권한을 확인하는 부분이 존재하지 않아 일어난 문제같다.
일단 login을 해보았다.
그러자 loginProc.php로 로그인을 한다는 것을 알았다. 나는 이것을 repeater로 돌려 password 부분을 빼고 userid를 admin으로 바꾸고 send 해보았다. {result : fail}이라는 값을 얻었다.
하지만, 난 여기서 화면을 새로고침했다. 그러자 위와 같은 flag값을 얻을 수 있었다. 리피터에서 id를 admin으로 보냈을 때 현재 로그인된 mario의 세션에 저장된 변수 'id' 값이 admin으로 바뀌어서 그런 것인가? 5번 미스테이크도 그렇고 잘못된 값이 들어왔을 때 그에 대한 값의 검증을 하지만, 그대로 실행하는 느낌이 들었다.
문제를 풀면서 가장 기묘했던 문제였던 것 같다. 처음에도 repeater를 이용해서 문제를 풀었지만 false가 나와 아니라고 생각했지만, 우연찮게도 새로고침을 하니 문제 답이 떡하니 나와 당황스러웠다.
login할 때 보내는 request부분에 userid를 admin으로 바꾸고 비밀번호를 포함하지 않고 보내보았다. 그랬더니 옆과 같이 오류가 나타나게 되었다.
이번에는 mario 계정에 비밀번호를 입력하고 정상적으로 접속해보았다.
그랬더니 위와 같이 flag값을 얻을 수 있었다. 내 생각이지만 세션id가 admin의 userid와 password 확인보다 먼저 만들어지게 되어 문제가 발생한게 아닐까라는 생각을 하게되었다.
login 버튼을 눌러보자.
위와 같이 PIN code를 넣으라는 말이 나온다. PIN code 0000을 넣어보자
위와 같이 GET으로 optNum 파라미터를 넘겨주는 것을 알 수 있다. 브루트포스로 이 문제를 해결 할 수 있다.
import requests
a = 83 // 로그인 실패의 경우,응답 받았을 때의 response.text의 길이는 83이다.
for i in range(10000):
url = "http://ctf.segfaulthub.com:1129/6/checkOTP.php?otpNum="
url += str(i).rjust(4, "0")
response = requests.get(url)
string = response.text
print(str(i).rjust(4, "0"))
if a != len(string):
print(i)
break
PIN code는 1021임을 알 수 있다.