Get Admin

loginUser라는 쿠키를 admin으로 바꿔치기하자 바로 Flag값이 나와버린다.
취약점
- 쿠키 값을 신뢰해선 안 된다는 것을 보여주는 전형적인 케이스 문제다.
- 클라이언트의 쿠키값을 기반으로 인증을 검증해서는 안 된다.
- 반드시 세션ID나 해시된 토큰을 기반으로 인증을 하여야 한다.
Admin is Mine
주어진 계정으로 로그인을 시도하면 다음과 같이 GET 방식으로 전송이 된다.

그럼 우선 admin에다가 아무 비밀번호나 넣고 보내보자.

이 응답을 보면, "result":"fail" 이라고 되어있다.
우선, 일어난 현상 그대로를 얘기해보자면 이렇게 말할 수 있다.
- 로그인 정보에 admin:{비밀번호 아무거나}를 넣고 보냈다.
- ‘GET /4/loginProc.php?userId=admin&userPw={비밀번호 아무거나}’ 요청에 대한 응답 중 ‘{"result":"fail"}’이라는 요청이 있다.
그럼 일단 {"result":"fail"}을 {"result":"ok"}로 바꿔보자.
Request가 아닌 Reponse를 조작해보자.
Burp Suite에서는 Request뿐만 아니라 Reponse도 Intercept할 수 있다.
우선 Intercept를 건 후, index.php에 접속 시도를 하고 그 요청 신호에 Response Intercept를 건다.
요청 Intercept → 마우스 우클릭 → Do Intercept → Response to this request

결과는?

근데 안 된다. 그런데, 다시 요청을 보면,

Burp의 히스토리를 보면, index.php를 거치고 나서 login.php로 돌아왔다.
그럼 index.php의 요청이 있었고, 여기에서 뭔가 login.php로 가라는 지시가 있었던 것이다.
Response 메시지를 잘 봐보자.

우선, 일어난 현상 그대로를 얘기해보자면 이렇게 말할 수 있다.
- index.php로 접속을 시도했다.
- 그런데 login.php로 가라는 location JS코드가 있다.
- 그래서 login.php로 돌아왔다.
- ⇒ 이 말인 즉, index.php에 login.php로 가게하는 location JS코드에 의해 login.php로 왔다는거다.
Response 메시지를 잘 봐보자.

저 빨간색 동그라미 친 부분을 지워버리자. 저 부분에서 login.php로 location되는 것이다.

<script>
location.href='login.php';
</script>
이 부분인 것 같다. 로그인을 하지 않으면 즉, GET메소드로 id admin과 admin의 패스워드를 입력치 않으면 저렇게 login.php로 location을 보내는 것 같다.
그럼 이 문제를 풀기위해 다시 Reponse를 조작해보자.
이번에는 바로 index.php로 넘어가는 요청을 intercept하고 거기에 대한 Response를 intercept한다.

저 빨간색 동그라미 친 부분을 지워버리자. 저 부분에서 login.php로 location되는 것이다.

지우고 응답을 그대로 보내고 페이지를 보면

취약점
- 클라이언트를 일단 신뢰하는 것이 문제다.
- 요청과 응답을 클라이언트가 Burp를 통해 다 캡쳐 및 조작하여 로그인이 안 되는 정보를 입력했을 때, 즉 올바르지 않은 admin의 password를 입력했을 때 로그인을 막는 장치를 클라이언트가 없애버릴 수 있다.
- 로그인을 하려면 클라이언트가 아닌 서버가 발급하는 세션ID나 토큰 등의 정보를 기반으로 인증하여야 한다.
PIN CODE Bypass
문제 페이지에 들어가보니 다음의 내용이 나온다.

저거 인증코드가 몇자리를 요구하는지도 지금까지 나온 정보들로는 알 수 없으니 일단 History를 보자.


“발사를 원하시면 아래 버튼을 클릭해주세요.”라는 문구의 화면이 나온다.

취약점
- step3.php로 접근할 때, 현재 사용자의 세션이 관리자의 세션이 맞는지 검증하는 로직이 전무하다.
- step2.php에서 올바른 인증코드를 입력했을 때에 관리자에 해당하는 세션ID을 발급하고 그 세션ID를 검증하는 로직을 추가해야한다.
Pin Code Crack



여기 GET 메소드 파라미터의 otpNum기반으로 인증하는 것 같다.
Intruder로 보내보자.


1018을 입력해서 풀어냈다.
그런데, 사실 전화번호에 힌트가 있었다. 010-1414-1018이라고 하였으니, 끝자리인 1018가 정답이었다.
주요 정보를 웹에 그냥 노출하면 안 된다는 것이 보안적 교훈이라면 교훈일 것이다.
Payload Script
import requests
FAIL_STRING = "Login Fail"
cookies = {
"PHPSESSID": "0b93047a27cff1eb6ea9e388cd268b24",
"session": "e8a815c5-0ff3-47ae-854c-abef391dcea9.X957i0t58uUpCShDNMZFJCSpcc0"
}
headers = {
"User-Agent": "Mozilla/5.0",
"Referer": "http://ctf.segfaulthub.com:1129/6/login.php"
}
for i in range(0, 10000): # 0000~9999
otp = f"{i:04d}" # 항상 4자리 유지
url = f"http://ctf.segfaulthub.com:1129/6/checkOTP.php?otpNum={otp}"
r = requests.get(url, cookies=cookies, headers=headers)
print(f"Try : {otp}")
if FAIL_STRING not in r.text:
print(f"[+] Found OTP: {otp}")
break

Login Bypass 5

일단 주어진 계정으로 로그인부터 해보자.

Burp로 히스토리를 보자.

Cookie 값에 doldol이라는 값이 있다.
혹시 저 Cookie값을 사이트가 신뢰하고 저거로 인증을 해버리는게 아닌가 싶어 저 값을 admin으로 바꿔치기 해봤다.

위에서 먼저 풀이한 Get Admin문제와 똑같은 원리다.
- 쿠키 값을 신뢰해선 안 된다는 것을 보여주는 전형적인 케이스 문제
- 클라이언트의 쿠키값을 기반으로 인증을 검증해서는 안 됨
- 반드시 세션ID나 해시된 토큰을 기반으로 인증 필요
Session 탈취
한 줄 요약
그냥 세션이라는 것의 개념을 알고있는지, 그리고 세션을 설정할 때 개발자의 입장에서 어떻게 설계해야 되는지에 대해 묻는 문제다.


이 세션 ID를 로그인 페이지의 PHPSESSID에 넣어 보자.


취약점
- 사용자가 로그인을 했을 때, PHP 세션 아이디가 발급된다. 그러나, 이 세션에 만료기한을 지정을 하지 않았다.
- 만료기간을 지정했으면 세션을 탈취했다 하더라고 이렇게 오랜 시간 동안 계속 유효하지 않는다.
- 세션의 만료기간을 적절히 지정하여 탈취되더라도 최소한의 안전성을 확보 하여야 한다.
Stupid Stupid

옆에 응답에 location: index.php 라고 되어있다. 이게 승인이 안 된다면, login.php로 location이 되는게 맞다.
그럼 저 응답을 브라우저 세션으로 열어보자.
응답에서 우클릭 → Request in browser → in original session

취약점
- POST 메시지의 Data에서 UserId가 그냥 admin이여버리면 그 값을 신뢰해 버린다.
- Data에서 Password 값을 전혀 검증하지 않고 있다.
- DB에 있는 Userid값과 password값을 비교해야 한다. 이때, password값은 해시된 상태로 저장되어야 하고, 서버 내부 로직에서 사용자로부터 입력받은 password값 또한 해시하여 그 값을 DB에 있는 password 해시 값과 비교해야 한다.
끝.
'Normaltic 취업반 > 인증 및 인가 취약점' 카테고리의 다른 글
| CTF 풀이 - Authentication Bypass (0) | 2026.03.20 |
|---|---|
| 권한 상승 취약점 구현 시나리오 (0) | 2026.03.20 |
| JWT 서명 검증 우회를 통한 관리자 권한 탈취 분석 (0) | 2026.03.20 |
| 비밀번호 변경 토큰 취약점 (0) | 2026.03.20 |
| 인증/인가 취약점 (0) | 2026.03.20 |