<1개월차>
☎ 웹 서버의 이해
1. 정적 페이지/동적 페이지
Web server - WAS - DB
2. SQL
3. 로그인 과정, 로직에 따른 케이스
쿠키, 세션, 세션ID, JWT
4. 웹 프록시 툴
Burp Suite
◈ SQL Injection
(맛보기)
injection : 주입하다, 넣다
→ SQL문을 넣어서 인증을 우회하기도 하고 데이터베이스에서 원하는 정보를 추출할 수도 있는 해킹 기법
사이트의 검색창이나 로그인 폼 등과 같이 SQL문을 사용해야하는 곳에서 써먹음.
< 작동 방식 >
이런 SQL문이 있다고 해보자.
SELECT * FROM user_table WHERE id = '____';
빈칸에 들어가는 값이 있는 행의 데이터를 DB의 테이블에서 찾는 문장이다.
저 빈칸에는 어떤 값이든 들어갈 수 있다.
다르게 말하면 저 안에다 아이디, 비밀번호를 그대로 넣을 필요는 없다는 뜻이다.
(물론 정상적인 로그인을 위해서는 필요하다.)
사용자가 haha 를 입력했다고 쳐보자.
당연히 id가 haha인 행의 정보가 출력된다.
그럼 이번엔 haha'를 입력했다고 쳐보자. 작은 따옴표 하나가 끝에 추가된 것이다.
위와 같이 오류가 발생한다.
준비된 문장은 >> where id='____' << 이런 형식이다. 여기에 haha'를 넣는다는 건
>> where id='haha'' <<라는 문장으로 만들겠다는 뜻이 된다.
작은 따옴표로 시작했으면 작은 따옴표로 끝내야한다. 아니면 저렇게 오류가 발생한다.
의도에 따라 오류를 일으킬만한 입력값을 넣을 수 있다.
그렇다면 준비된 sql문으로 다른 결과를 뽑아낼 수도 있지 않을까?
예를 들어 다른 사람의 정보도 함께 출력시킨다든가 말이다.
저장된 데이터를 모두 가지고올 수 있는 방법이 있다.
입력한 아이디 뿐만 아니라 모든 값이 항상 참이 되도록 만드는 구문을 넣으면 된다.
이런 구문이 있다고 하자.
SELECT * FROM user_table WHERE id= 'haha' or '1'='1';
위의 select문은 사용자가 id 입력란에 >> haha' or '1' ='1 <<을 입력했을 때 완성될 sql 구문이다.
where 조건 절에서 id='haha' 와 '1'='1'라는 조건 두개를 or로 연결하고 있다.
조건절에서 or을 쓸 경우 제시된 조건 중에서 하나라도 참이면 그 조건절은 전부 참으로 결정된다.
'1'='1'이라는 구문은 1은 곧 1이라는 뜻이기에 항상 참이 되는 문장이다.
(1은 곧 1이라는 의미가 성립하면 되므로 'a'='a' 와 같이 굳이 1로 표현할 필요는 없다. )
따라서 저 문장은 조건절이 무조건! 참이기 때문에 user_table에 있는 모든 행을 출력한다.
(항상 참이도록 하는 부분은 '1'='1' 이기 때문에 심지어 'haha' 가 저 테이블에 없는 아이디여도 모든 행을 출력한다.)
모든 사용자의 특정 데이터를 가지고올 수도 있다.
SELECT password FROM user_table WHERE id='아이디없음' or '1'='1';
예를 들어 이 쿼리문을 입력하면 모든 행의 비밀번호를 출력할 수 있다. (물론 비밀번호를 저장한 컬럼명이 password여야한다.)
이런 식으로 sql을 삽입해 나오는 결과에 따라 로그인 로직을 추론할 수도 있고 로그인을 우회할 수도 있다.
이것이 SQL Injection의 기본 원리이다.
이제 배운 내용을 ctf로 실습해보자.
◈ 버프 스위트를 활용해 SQL Injection CTF 풀어보기
† 항~상 선행되어야할 과정 †
1) 버프 스위트로 로그인 성공, 실패 데이터 분석
2) doldol' and '1'='1 / dol1234 입력해서 SQL Injection이 일어날 수 있는지 확인
(주어진 계정)
♪ normaltic1로 로그인 하기
*나는 지금 doldol / dol1234
< 정상 로그인 시 흐름 >
_________________________( ↓ 로그인 성공 )
인덱스 페이지 요청 -> 응답 코드 302 (리디렉션), 로그인 페이지로 리디렉션
-> 로그인 페이지 요청 -> 응답 코드 200 (ok), 로그인 페이지 줌
-> 로그인 페이지에서 POST로 입력 값 전송 (UserId=doldol&Password=dol1234&Submit=Login)
-> 로그인 페이지 (login.php)에서 입력값 검증 후 로그인 성공 시 응답 코드 302 (리디렉션)
-> 인덱스 페이지 요청 (doldol계정) -> 응답 코드 200, 인덱스 페이지 줌
________________________ ( ↓ 로그인 실패 )
(로그아웃 -> 응답 코드 302, 로그인 페이지 리디렉션)
-> 로그인 페이지 요청 -> 응답 코드 200, 로그인 페이지 줌
-> 로그인 페이지에서 POST로 없는 로그인 정보 입력
-> 응답코드 200, js 로그인 경고문 출력
< 입력값으로 DB 문법 추론하기 >
1) doldol' and '1'='1 / dol1234
'1'='1' 은 항상 참이 되는 조건이면서 어떤 조건과 함께 쓰든 그 조건에 영향을 주지 않는다.
'doldol' and '1'='1' 은 12*1 혹은 12+0 처럼 연산 값이 그대로 도출된다. (항등원마냥)
로그인 됨. => 작은 따옴표가 SQL문의 일부로 인식이 되었고 AND 연산자도 추가할 수 있음.
SQL Injection이 일어날 가능성이 있다!!!
"SELECT ___ FROM 회원table WHERE id = '____' and pw = '___'"; 일 경우
2) doldol' # / 아무거나
로그인 안 됨.
where id = '__' and pw = '__'; 이 케이스였으면 id 뒷부분이 주석처리 되어서 로그인되었을 것임.
즉, 서버가 준비한 쿼리문은 이런 형태가 아닐 것.
식별, 인증 동시인지 분리인지는 확인할 수 없지만
동시일 경우 개행 들어갈 가능성 있음.
"SELECT * FROM table WHERE id = '____'
and pw = '____'"; 일 경우
3) doldol' or '1'='1 / 아무거나
select * from table where id='doldol' or '1'='1'
and pw = 'qwer';
로그인 됨.
아이디 : normaltic1' or '1'='1
비밀번호 : 아무거나 _________(플래그 획득)
AND 연산자와 OR 연산자 중 AND의 우선 순위가 더 높음.
따라서 이 경우 '1'='1' and pw = 'qwer' 먼저 처리 => 결과 : 둘 다 참이어야 참이므로 결과는 거짓
id = 'doldol' or '거짓' => 결과 : or 연산자는 하나라도 참이면 참이므로 id가 doldol인 행을 식별해서 결과로 넘김
따라서 이 문제의 서버가 준비한 SQL문은
"SELECT 컬럼 FROM 테이블 WHERE id = '___'
and pw = '___'";
일 것이라 추론 가능함.
♪ normaltic2로 로그인 하기
*나는 지금 doldol / dol1234
< 정상 로그인 시 흐름 > (위와 동일함)
_________________________( ↓ 로그인 성공 )
인덱스 페이지 요청 -> 응답 코드 302 (리디렉션), 로그인 페이지로 리디렉션
-> 로그인 페이지 요청 -> 응답 코드 200 (ok), 로그인 페이지 줌
-> 로그인 페이지에서 POST로 입력 값 전송 (UserId=doldol&Password=dol1234&Submit=Login)
-> 로그인 페이지 (login.php)에서 입력값 검증 후 로그인 성공 시 응답 코드 302 (리디렉션), 인덱스 페이지 리디렉션
-> 인덱스 페이지 요청 (doldol계정) -> 응답코드 200, 인덱스 페이지 줌
________________________ ( ↓ 로그인 실패 )
(로그아웃 -> 응답 코드 302)
-> 로그인 페이지 접근 -> 응답 코드 200
-> 로그인 페이지에서 POST로 없는 로그인 정보 입력
-> 응답코드 200, js 로그인 경고문 출력
< 입력값으로 DB 문법 추론하기 >
1) doldol' and '1'='1 / dol1234
로그인 됨.
기호 sql문으로 인식
SQL Injection 발생 가능성 있음!!
"SELECT ___ FROM 회원table WHERE id = '____' and pw = '__' "; 일 경우
2) doldol' # / 아무거나
로그인 됨.
아이디 : normaltic2' #
비밀번호 : 아무거나 _________(플래그 획득)
where id = '__' and pw = '__'; 이런 조건문에 아이디가 들어가서
id 식별 조건 이후는 모두 주석처리 -> DB에 존재하는 아이디만 입력하면 로그인 가능.
(where id = 'normaltic2' #' and pw = 'qwer';)
따라서 이 문제의 서버가 준비한 SQL문은
"SELECT 컬럼 FROM 테이블 WHERE id = '___' and pw = '___'";
일 것이라 추론 가능함.
◈ 버프 스위트를 활용해 인증 우회 CTF 풀어보기
♪ admin계정으로 접속하기
*나는 지금 doldol / dol1234
< 정상 로그인 시 흐름 > (위와 동일함)
_________________________( ↓ 로그인 성공 )
인덱스 페이지 요청 -> 응답 코드 302 (리디렉션), 로그인 페이지로 리디렉션
-> 로그인 페이지 요청 -> 응답 코드 200 (ok), 로그인 페이지 줌
-> 로그인 페이지에서 POST로 입력 값 전송 (UserId=doldol&Password=dol1234&Submit=Login)
-> 로그인 페이지 (login.php)에서 입력값 검증 후 응답 코드 302 (리디렉션), 인덱스 페이지 리디렉션 인데!!!!
Set-Cookie: loginUser=doldol
-> 인덱스 페이지 요청 (doldol계정) 인데!!!!!!
Cookie: loginUser=doldol
-> 응답 코드 200, 인덱스 페이지 줌
________________________ ( ↓ 로그인 실패 )
(로그아웃 -> 응답 코드 302, 로그인 페이지 줌)
-> 로그인 페이지 요청 -> 응답 코드 200, 로그인 페이지 줌
-> 로그인 페이지에서 POST로 없는 로그인 정보 입력
-> 응답코드 200, js 로그인 경고문 출력
< 로그인 과정으로 인증 케이스 추론하기 >
서버에서 무엇으로 사용자를 인증하고 있는지 발견하는 게 관건!!
로그인 시 쿠키 데이터를 주고 받고 있음을 볼 수 있음.
쿠키에 admin을 입력해서 인증 유도.
이제 남은 건 admin으로 변조된 쿠키를 어떤 페이지를 요청할 때 들고 가야하느냐인데,
로그인 페이지에서 서버가 사용자에게 아이디에 따른 쿠키를 주고
사용자는 인덱스 페이지에서 그걸 갖고 들어간다는 점.
따라서 인덱스 페이지에서 쿠키 값을 변조해야함.
1) doldol로 로그인한 상태에서 버프 스위트의 intercept를 on 시킨다.
2) 인덱스 페이지에서 새로고침(f5)을 누른다.
3) 버프 스위트에서 요청 패킷을 확인한다.
4) 쿠키 값을 doldol 대신 admin으로 변조한다.
5) intercept off 하든가 forward를 눌러 요청 데이터를 보낸다. _________(플래그 획득)
해당 서버에서는 이 사용자가 그 사용자인지 확인하는 과정 (인증)을
쿠키로 하고 있음을 알 수 있다. 아아아주 위험한 인증 방법이구만~!
♪ 핵미사일 발사하기
대체 뭘 시키시는 겁니까(농담)
< 흐름 >
/3/ 페이지 요청 -> 응답 코드 200, /3/페이지 줌
-> fire 클릭 ( <a href = "step1.php"></a> )
-> step1.php 요청 -> 응답코드 200, 관리자만 이용 어쩌구 페이지 보냄
-> 확인 클릭 ( <a href="step2.php"></a> )
-> step2.php 요청 -> 응답코드 200, 비밀번호 입력 페이지 보냄 -> 비밀번호 입력
-> 제출하면 step2.php에 GET방식으로 파라미터 보냄 (step2.php?admin_pass=asdf)
-> 맞지 않으면 js코드로 alert문 출력
< 흐름으로 인증 과정 추론하기 >
추론하기라고 했지만 사실 노말틱님이 힌트를 주시기 전까진 알아차리지 못했다....
추론하는 척 해보자면
해당 서버는 사용자의 동작에 따라 다음 페이지를 요청하게 하는 방식으로 인증 단계를 밟아가고 있다.
fire를 누르면 step1로
확인을 누르면 step2로
비밀번호를 입력해 제출하면 GET요청을 통해 파라미터를 검증하는 방식이다.
그러면 자연스럽게 생각해보게 된다.
step3는 없나?
이쯤에서 알려주신 인증 우회 전략을 정리해보자면
1) Brute Force Attack : 무작위 대입 공격, 조합 가능한 모든 경우의 수를 입력시키는 방법.
---> 입력 횟수를 제한시키는 식으로 대응
2) 사전 대입 공격 : 무작위 대입 공격과 달리 인증으로 쓸 법한 단어를 추려서 그것만 입력시키는 방법.
---> 입력 횟수를 제한시키는 식으로 대응
3) 인증 과정 건너뛰기 : 회원가입 시 약관 동의 -> 본인인증 -> 어쩌구 저쩌구 확인 -> 가입하기의 과정처럼
인증하기에 앞서 여러 단계가 있을 경우 몇 단계를 건너뛰어 인증한 척하는 방법
---> 이전 단계를 거쳤는지 확인하는 과정을 추가하여 대응
이정도가 있다.
이 문제는 3번에 해당한다.
그래서 인증 과정을 건너뛰기 위해
서버에 이전 단계를 거쳤는지 확인하는 코드가 있든 없든 우선 step3.php를 요청해본다.
1) 요청 중 아무거나 선택해서 리피터로 보냄
2) 요청 파일경로를 /3/step3.php로 바꿔서 보냄
3) 응답 본문에서 버튼을 확인. ( <a href="gogoHack.php"></a> )
4) 파일 경로를 /3/gogoHack.php로 바꿔 보냄.
5) 플래그 획득 _________(플래그 획득)
__________________________________________________________
지금까지 CTF로
로그인 우회
㉮ 식별, 인증 동시 + 개행
㉯ 식별, 인증 동시
인증 우회
㉰ 쿠키 변조
㉱ 인증 단계 건너뛰기
를 실습한 걸 정리해보았다.
'모의해킹 스터디 복습' 카테고리의 다른 글
모의해킹 스터디 7주차(1): Error-Based SQL Injection (1) | 2024.12.01 |
---|---|
모의해킹 스터디 6주차: UNION SQL Injection (0) | 2024.11.24 |
모의해킹 스터디 4주차: 웹 프록시 툴 - Burp Suite (5) | 2024.11.12 |
모의해킹 스터디 3주차: 로그인, 쿠키, 세션, 세션ID (3) | 2024.11.06 |
모의해킹 스터디 2주차: Database (4) | 2024.10.29 |