SegFault CTF - 5주차 - 2

2025. 5. 6. 20:03·Study/with normaltic

5. Login Bypass 1

Login Bypass 1

normaltic1으로 로그인하는 것이 목표인 문제인듯 하다.

Login In

어디서 본듯한 로그인 창이다. 처음 제공받은 ID: doldol, PW: dol1234로 로그인을 해보겠다.

Login Request & Response

저번처럼 쿠키를 이용한 방식은 아닌듯 하다. 보통 로그인 정보는 DB에 보관하니, 혹시 로그인 창에서 SQL Injection이 가능한지 시도해보겠다.

ID에 `doldol' and '1'='1`을 적어, SQL Injection이 가능한지 판별한다. 만약 불가능하다면 로그인이 되지 않고, 가능하다면 로그인이 될 것이다.

로그인이 됐다. SQL Injection이 먹힌다는 것을 알 수 있다.

로그인 로직은 여러가지 다양한 방법으로 구현할 수 있는데, 그 중 가장 단순한 방법으로 생각해보겠다.

$id = $_POST['id'];
$pw = $_POST['pw'];

$sql = "SELECT * FROM member WHERE id='{$id}' and pw='{$pw}'";

테이블명은 `member`, id와 pw에 관한 칼럼명은 `id`, `pw`로 가정했다.

만약 이런 식으로 SQL문이 작성돼있다면 SQL Injection 코드는 다음과 같이 짤 수 있다.

ID: normaltic1' #

이 값이 ID에 들어간다면 SQL문은 다음과 같이 완성될 것이다.

SELECT * FROM member WHERE id='normaltic1' #' and pw='aaaa'

# 이후부터는 주석 처리되어 id만을 가지고 로그인을 할 수 있게 된다.

First SQLi Try

안 된다. 내가 생각한 SQL문이 아닌 것이다.

그렇다면 SQL문이 이렇게 작성돼있을 수도 있다.

// 위와 동일

$sql = "SELECT * FROM member WHERE id='{$id}' \n and pw='{$pw}'";

SQL문이 이렇게 작성돼 있으면 아까 시도했던 SQLi는 이런 식으로 들어간다.

SELECT * FROM member WHERE id='normaltic1' #'
and pw='f'

개행이 되어있어 비밀번호 검사를 무시할 수 없는 것이다.

이런 식으로 개행이 들어가있게 된다면 다른 방식으로 SQLi를 진행할 수 있다.

SQLi 1

ID: normaltic1' or '1'='1

이 SQLi를 이용하면 SQL문은 이렇게 된다.

SELECT * FROM member WHERE id='normaltic1' or '1'='1'
and pw='f'

`'1'='1' and pw='f'`의 결과는 항상 False일 것이다. 그럼 `id='normaltic1' or False`가 되어, `id`가 `normaltic1`일 때 True가 되기 때문에 비밀번호 검증 없이 `id`가 `normaltic1`인 계정으로 로그인할 수 있다.

SQLi 2

ID: normaltic1' /*
PW: */ #

이 방식을 이용하면 SQL문은 이렇게 된다.

SELECT * FROM member WHERE id='normaltic1' /*
and pw='*/ #'

비밀번호 검사 부분을 전부 주석처리하는 방법이다. `/* */`를 이용하면 여러줄을 주석처리할 수 있다는 점을 이용한 것이다.

 

이 중 첫번째 방식으로 SQLi를 진행해보겠다.

Second SQLi Try
Flag

SQLi가 성공적으로 진행됐다.

이러면 아마 php 코드는 

$id = $_POST['id'];
$pw = $_POST['pw'];

$sql = "SELECT * FROM member WHERE id='{$id}' \n and pw='{$pw}'";

이런 식으로 작성돼 있었을 것이다.

6. Login Bypass 2

Login Bypass 2

아까와 같은 방식인 것 같다.

Check SQLi availability

바로 SQLi가 가능한지 확인해보겠다.(패킷 송수신 과정에서는 취약점을 발견하지 못했다)

SQLi available

SQLi가 가능한 것을 확인했다.

First SQLi Try

아까와 같은 방식으로 로그인 로직이

$id = $_POST['id']
$pw = $_POST['pw']

$sql = "SELECT * FROM member WHERE id='{$id}' and pw='{$pw}'"

인 것으로 가정하고 가장 기본적인 SQLi를 시도해보겠다.

Flag

?

7. Login Bypass 3

Login Bypass 3

또 똑같은 패턴이다.

이번엔 `normaltic3' #`에 뚫리지 않길 바란다.

First SQLi Try

이번엔 실패했다.

그렇다면 Login Bypass 1에서 시도했던 것처럼 `normaltic3' or '1'='1`로 시도해보겠다.

Second SQLi Try

이번엔 그리 호락호락하지 않은 문제인듯 하다.

Login Bypass 1과 2에서 보여주진 않았지만, 사실 두 문제에서는 비밀번호 입력창에서도 SQLi이 가능했다.

비밀번호 입력창에서의 SQLi 가능 여부 또한 다음과 같은 입력으로 확인할 수 있다.

ID: doldol
PW: dol1234' and '1'='1

Check PW input's SQLi availability

로그인이 안 되는 것을 보면 비밀번호 입력창에서는 SQLi이 안 된다. 

그럼 혹시, ID 입력 창에서도 안 되는건 아닐까?

Check ID input's SQLi availability
ID input's SQLi is available

다행히 ID 입력창에서는 SQLi이 가능하다.

ID 입력창에서는 되는데 PW 입력창에서는 안 된다.. 그렇다면 로그인 로직이 이런 식으로 돼있을 수 있다고 생각할 수 있다.

 $id = $_POST['id'];
 $pw = $_POST['pw'];
 
 $sql = "SELECT pw FROM member WHERE id='{$id}'";
 $result = $db_conn->query($sql);
 
 $row = $result->fetch_array();
 if($row['pw'] == $pw) {
 	// Login Success
 } else {
 	// Login Fail
 }

4번째 줄에서 `pw`만을 SELECT한다고 예상했지만, 그에 대한 근거는 아직 없다. `pw` 말고도 다른 칼럼 또한 가져올 수도 있다.

 

이렇게 ID와 PW를 따로, 즉, 식별과 인증을 분리해서 하는 경우에도 SQLi이 가능하다.

' UNION SELECT 'blah

이 SQLi가 들어가면 SQL문은 다음과 같이 된다.

SELECT pw FROM member WHERE id='' UNION SELECT 'blah'

이 SQL문에 대해 설명하기 전, 정상적으로 작동했을 때의 동작 과정을 먼저 살펴보겠다.

ID: doldol, PW: dol1234로 로그인을 한다면 `SELECT pass FROM member WHERE id='doldol'`을 통해 다음과 같은 테이블이 불러와졌을 것이다.

pw
dol1234

그럼 이 안에 있는 pass 값, `dol1234`를 사용자 입력 `dol1234`와 비교하여 로그인이 정상적으로 처리된다.

그럼 다음과 같은 SQL문이 실행된다면 어떻게 될까?

SELECT pw FROM member WHERE id='doldol' UNION SELECT 'blah'
pw
dol1234
blah

이렇게 되어도 일단 가장 위에 있는 값인 `dol1234`로 비교할 것이다. 그럼 `dol1234`를 없애보자. 그러기 위해서는 SQL문에서 id에 없는 값을 넣으면 된다. 그게 바로 아까 소개한 SQL문이다.

SELECT pw FROM member WHERE id='' UNION SELECT 'blah'
pw
blah

이렇게 되면 `blah`라는 값과 사용자 입력을 비교할 것이다. 즉, SQLi를 이런 식으로 작성하면 된다.

ID: ' UNION SELECT 'blah
PW: blah

Third SQLi Try

실패다.

하지만 간과한 것이 하나 있다.

아까 말했듯이 실제로 어떠한 칼럼을, 몇 개의 칼럼을 가져오는지 모른다.

만약 칼럼의 수가 안 맞는다면 쿼리가 실패하게 되어 로그인도 실패하게 된다.

이를 이용해 칼럼의 수를 알아낼 수 있다.

ID: doldol' UNION SELECT 1,2,3,4,5 #
PW: dol1234

1,2,3,4,5 -> 1,2,3,4 -> 1,2,3 -> 1,2 -> 1 이런 식으로 개수를 줄여가면서 로그인이 되는 점을 찾는다.

Find count of columns

이런 식으로 하다가

count of columns: 2

1, 2에서 로그인이 되는 것을 확인할 수 있다.

즉, 가져오는 칼럼의 수가 두 개라는 것이다.

?? pw
?? dol1234

상식적으로 생각하면 나머지 하나의 칼럼은 아마 id일 것이다.

id pw
normaltic3 blah

그럼 이러한 테이블을 가져오도록 하면 된다. 아까 UNION을 이용한 것처럼 하면 된다.

ID: ' UNION SELECT 'normaltic3','blah
PW: blah

Fourth SQLi Try
Flag

사실 난 처음에 이 방법을 전혀 몰랐어서 다른 방법으로 풀었다. 그 다른 방법은 글을 따로 작성하겠다.(엄청 먼 길을 돌아가는 방식이다)

8. Login Bypass 4

Login Bypass 4

여러가지 시도해보면, Login Bypass 3와 같이 식별 / 인증을 분리해서 한다는 것을 알 수 있다.

그럼 아까와 같이 이 SQLi를 시도해보자.

ID: ' UNION SELECT 'normaltic4','blah
PW: blah

First SQLi Try

흠... 내가 생각한 로직이 아닌가 싶어 다음의 SQLi를 써본다.

ID: ' UNION SELECT 'doldol','dol1234
PW: dol1234

Logic check

id pw
doldol dol1234

이 테이블이 안 먹힌 것이다.

혹은 칼럼의 순서가 틀렸을 수도 있다.

pw id
dol1234 doldol

Logic Check 2

확실히 칼럼의 수는 2개다.(아까처럼 해보면 2개인 것을 알 수 있다)

그렇다면 비밀번호를 평문으로 저장하지 않았을 가능성을 생각해볼 수 있다.

$id = $_POST['id'];
$pw = $_POST['pw'];

$sql = "SELECT id,pw FROM member WHERE id='{$id}'";
$result = $db_conn->query($sql);

$row = $result->fetch_array();
if(md5($row['pw']) === $pw) {
	// Login Success
} else {
	// Login Fail
}

로그인 로직이 이렇게 되어있다면 UNION을 통해 자신이 임의로 쓸 비밀번호를 암호화할 필요가 있다.

직접 암호화해서 해볼 수도 있지만 SQL은 기본적으로 Hash 함수를 제공한다. 따라서 SQLi를 이렇게 작성해볼 수 있다.

 ID: ' UNION SELECT 'normaltic4',MD5('blah') #
PW: blah
ID: ' UNION SELECT 'normaltic4',SHA2('blah') #
PW: blah

어떤 방식으로 암호화됐는지 모르니 여러가지로 시도해봐야 한다.

또한, 아까 위에서 의심했던 것처럼 id와 pw의 순서가 바뀌었을 수도 있다는 점을 의심해야한다.

Second SQLi Try
Flag

다행히도 그렇게 꽁꽁 숨겨져 있진 않았다.

9. Login Bypass 5

Login Bypass 5

만약 Burp Suite로 패킷 송수신 과정부터 꼼꼼하게 살펴보는 습관이 있다면 이 문제는 굉장히 쉽게 풀 수 있다.

 

login.php Request & Response

옛날옛적 문제처럼 또 `Set-Cookie`를 이용해 쿠키를 지정해준다.

이번에도 쿠키 변조를 시도해보겠다.

Cookie Poisoning
Request as normaltic5
Flag

굉장히 쉽게 Flag를 따낼 수 있다.

 

'Study > with normaltic' 카테고리의 다른 글

SegFault CTF - 5주차 - 번외  (0) 2025.05.07
SegFault CTF - 5주차 - 1  (0) 2025.05.06
SegFault CTF - 4주차  (0) 2025.04.24
로그인 유지: 쿠키 & 세션  (0) 2025.04.23
PHP와 MySQL  (0) 2025.04.16
'Study/with normaltic' 카테고리의 다른 글
  • SegFault CTF - 5주차 - 번외
  • SegFault CTF - 5주차 - 1
  • SegFault CTF - 4주차
  • 로그인 유지: 쿠키 & 세션
renia256
renia256
  • renia256
    나른한 고양이
    renia256
  • 전체
    오늘
    어제
    • 분류 전체보기 (12)
      • Study (10)
        • 컴파일러 (0)
        • 잡다한 것들 (2)
        • FTZ (0)
        • with normaltic (8)
      • 자료구조 (0)
      • writeup in kr (1)
      • writeup in en (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    suckless2
    writeup
    CTF
    UMass
    UMASSCTF
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
renia256
SegFault CTF - 5주차 - 2
상단으로

티스토리툴바