Normaltic Study/CTF

[Week5/CTF] Login Bypass 1,2

min8282 2024. 5. 22. 16:23

SQL Injection을 이용한 로그인 로직 취약점 문제다.

문제) Login Bypass 1

로그인 페이지로 이동

로그인 페이지에서 문제에서 알려준 아이디와 비밀번호로 로그인을 시도

burp suite으로 웹에서 서버로 보내는 request와 response를 확인해 봤다. POST 방식으로 전송을 하며 UserId, Password, Submit의 내용을 같이 전송한다. 아마 UserId 부분을 건드리면 해결할 수 있을 것 같다.

 

주어진 아이디로 로그인 성공시 index.php로 redirect된다.

 

이제 로그인 로직에 대해 예측해 보고 그에 맞는 sql injection을 시도해 본다.

SELECT * 
FROM User 
WHERE UserId='doldol' AND Password='dol1234'

식별과 인증을 동시에 하는 로직을 위와 같이 예측해 봤다. 이런 경우는 아이디와 비밀번호가 동시에 참이어야 한다. 그렇다면 'or' 연산자를 사용해서 비밀번호 부분의 AND 앞에 항상 참인 값을 추가하여 어떤 비밀번호를 입력하든 둘 중하나 만 참이면 true를 반환하게 하여 아이디만 가지고 로그인이 성공하는지 시도해 봤다.

아이디 입력란에 위와 같이 입력하면

SELECT *
FROM user
WHERE UserId='doldol' OR '1'='1' AND Password='aaa'

실제로 위와 같이 sql이 작성된다. AND 연산자가 OR 연산자보다 실행 순서가 먼저 진행되기 때문에 보기 쉽게 바꿔보면

SELECT *
FROM user
WHERE UserId='doldol' OR ('1'='1' AND Password='aaa')

이렇게 작성할 수 있다. 비밀번호를 아무 입력이나 넣어도 1 = 1이라는 항등식 때문에 괄호 부분은 항상 참(true)이 반환된다. 따라서 웹 서버 DB에 'doldol'이라는 아이디만 있으면, 웹 서버는 'doldol'이라는 사용자가 로그인을 시도한 것으로 인식하고 로그인을 성공시켜 준다.

실제 위처럼 로그인을 시도해 보면 doldol 사용자로 로그인이 성공했다. 이번 문제에는 로그인 로직이 식별과 인증이 동시에 적용되는 경우인 것으로 예측할 수 있다.

그럼 결국에는 아이디만 가지고 로그인을 성공시킨 것이다. 그럼 힘들게 OR 연산자와 항등식을 추가하지 않고 아이디를 제외한 뒷부분을 주석처리 시켜보면 로그인이 되나 확인해 봤다.

아이디에 'doldol', 비밀번호에 'dol1234'를 입력하게 되면

SELECT *
FROM user
WHERE UserId='doldol' # AND Password='dol1234'

웹 서버에서는 이렇게 전달받게 된다고 예측할 수 있다. 이렇게 로그인을 시도해보면

로그인이 성공했다.

SELECT * 
FROM User 
WHERE UserId='doldol' AND Password='dol1234'

로그인 로직이 위와 같이 처리된다고 예측할 수 있다.

그럼 normaltic1로 로그인을 하려면 아이디를 제외한 뒷부분을 주석처리시켜 로그인을 시도하면 될 것 같다.

아이디에 normaltic1' #, 비밀번호는 어차피 주석처리되니까 아무거나 입력하고 로그인을 시도하면?

로그인이 실패했다. 분명 앞에서는 #을 이용해 비밀번호를 주석처리하면 로그인이 성공했었다. 그럼 내가 예측한 로그인 로직이 틀린 것이다.

SELECT * 
FROM User 
WHERE UserId='doldol' AND Password='dol1234'

내가 생각한 로그인 로직은 위처럼 쿼리가 작동한다 예측했지만 틀렸다.

그럼 OR 연산자를 사용해서 normaltic1로 로그인 시도를 해보면?

아이디에 normaltic1' or '1'='1, 비밀번호는 항등식 때문에 무조건 참이 되니까 아무거나 입력했다.

normaltic1로 로그인이 성공했다. ??!

분명 #을 이용해서 normaltic1로 로그인 시도를 했을 때는 실패했고, doldol로 로그인 시도를 했을 때는 성공했다. 다시 내가 시도했던 방법을 천천히 살펴보면 normaltic1로 시도했을 때는 비밀번호를 아무거나 입력했고, doldol로 시도할 때는 doldol에 맞는 비밀번호를 입력했다. 즉, 비밀번호를 알맞게 입력했을 때는 로그인 성공, 틀리게 입력했을 때는 실패했다. 

그럼 추가 테스트로 아이디에 doldol' #을 입력하고 비밀번호를 틀리게 넣어보면

로그인이 실패했다. 이렇게 되면 로그인 로직이 식별/인증 분리라고 생각할 수 있지만 우리는 앞서 OR 연산자와 항등식을 이용해서 로그인 시도를 했을 때 로그인을 성공시켰다. 즉, 식별/인증 동시에 진행되지만 주석처리가 되지 않은 것을 예측할 수 있다. 이런 경우는 신별/인증 동시 개행인 경우 같다. 개행이란 페이지의 끝에 다다르거나 문장이 끝나기 전에 줄 바꿈을 넣어서 문장을 다음 줄로 보내는 행위로 아래처럼 쿼리가 작성되어 있다고 예측할 수 있다.

SELECT * 
FROM User 
WHERE UserId='doldol'
	AND Password='dol1234'

이 경우처럼 작성되어 있다고 하면 #을 이용해 아이디 뒷부분 전체를 주석처리시켜 로그인 시도가 안 되는 것이 납득 가능하다.

SELECT * 
FROM User 
WHERE UserId='doldol' #
	AND Password='dol1234'

#은 해당 줄만 주석으로 변경시키기 때문에 비밀번호 부분이 그대로 실행된다. 따라서 이번 로그인 로직은 식별/인증 동시 개행으로 예측가능하다. 

SELECT * 
FROM User 
WHERE UserId='doldol' or ('1'='1'
	AND Password='dol1234')

이런 취약점을 통해 항등식을 사용한 로그인을 시도하면 위와 같이 작성되어 실행되며, 비밀번호를 몰라도 아이디만 가지고 로그인을 할 수 있다.


문제) Login Bypass 2

normaltic2로 로그인을 성공시켜야 한다.

이번 문제도 Login Bypass 1과 비슷하게 같은? 화면에서 진행한다. 실제 주소는 다르다.

주어진 아이디와 비밀번호로 로그인을 해봤다.

1번 문제와 동일하게 아이디, 비밀번호, submit을 전달한다.

1번과 동일한 요청과

1번과 동일한 응답을 보낸 것을 알 수 있다.

먼저 로그인 로직이 식별/인증이 분리인지 테스트했다. 아이디는 doldol' #, 비밀번호는 dol1234로 알맞게 입력했다.

 

로그인이 성공했다.

SELECT * 
FROM User 
WHERE UserId='doldol' # AND Password='dol1234'

실제 서버에서는 이 쿼리처럼 작동했을 것 같다.

이번에는 비밀번호를 틀리게 적어봤다.

이번에도 성공했다. 즉, 식별/인증이 동시에 진행되며 개항문이 아니라고 예측할 수 있으며

SELECT * 
FROM User 
WHERE UserId='doldol' # AND Password='11111111111'

위 쿼리처럼 작동할 수 있다 예측 가능하다. 

그럼 #을 이용해서 normaltic2로 로그인을 시도해 보면?

로그인 성공..! 이번에는 비교적 쉽게 나왔다.


summary

이번 문제를 통해 식별/인증 분리, 식별/인증 동시, 식별/인증 동시 개행 등 여러 방식의 로직을 생각할 수 있었다. 굳굳^^