// 불펌스크립트시작 // 불펌스크립트 끝

1. SQL Injection 공격 원리

- SQL Injection 공격을 이해하기 위해서는 데이터가 어떤 과정으로 저장되고 사용되는지 알아야 한다.

- 게시판에서 회원가입을 할 때 아이디와 패스워드를 입력한 정보는 모두 어디에 저장이 되었을까?

- 이 게시판에서는 회원가입 정보를 board 데이터베이스의 member 테이블에 저장한다.

- 아이디는 bId 열에, 패스워드는 bPass 열에 각각 저장되어있다.

 

 

- 로그인 페이지 파일명은 default.htm이다.

- 등록된 사용자의 아이디와 패스워드를 입력 받아 member 테이블에서 동일한 아이디와 패스워드를 가진 레코드를 찾아 사용자가 게시판에 접근하는 것을 허용한다.

- 계정이 존재하지 않거나 패스워드가 올바르지 않으면 잘못된 로그인임을 알려줄 것이다.

- 아래 소스를 보면 login_ck.asp 파일로 정보를 보내고 있음을 확인할 수 있다.

 

 

- login_ck.asp 파일을 열어보면 아이디(memberid)와 패스워드(pass1)를 받아서 SQL 쿼리문(strSQL)을 만들고 실행시켜 member 테이블의 정보를 가져온다.

- 입력된 아이디와 패스워드에 대한 결과 값이 있다면, 즉 실제로 등록된 사용자라면 board_list.asp가 실행되고, 아이디와 패스워드를 잘못 입력하거나 등록되지 않은 사용자라면 잘못된 로그인입니다라는 메시지를 보낸다.

 

 

2. 공격 방법

▶ 인증 우회 ( Authentication Bypass )

⊙ 인증 우회

- 가장 널리 이용되는 SQL Injection 방법은 OR 연산을 사용하는 것이다.

- 입력 폼에 `or '1'='1 문을 입력하여 결과 값을 참으로 만들어 우회하는 방법이다.

- 예를 들어, 로그인 화면에서 아이디는 TEST_ID로 하고, 패스워드는 test로 해서 로그인을 시도할 경우 패스워드가 틀려서 잘못된 로그인이라는 메시지를 받게 된다.

- 하지만, 패스워드에 test' or '1'='1을 입력하면 login_ck.asp 파일에서 회원 로그인을 처리하기 위해 데이터베이스에 요청하는 쿼리문을 최종적으로 select * from member where bId = 'TEST_ID' and bPass = 'test' or '1'='1'과 같이 전달되고 이 때 where 절 뒤쪽에 임의로 삽입된 oR 조건에 의해서 OR 앞이나 뒤의 두 조건 중에 하나라도 참이면 참이 되어 결과 값을 반환한다. 여기에서 1과 1은 같은 값이므로 앞에 어떠 값이 오더라도 항상 참.

- 여기서 한 가지 더 주의할 점은 홑따옴표(')의 사용이다. 아래의 소스 코드에서 알 수 있듯이 아이디와 패스워드로 SQL 문을 생성

 

 

- 이 때, TEST_ID와 test은 홑따옴표 안에 들어간다. 이미 알고 있는 것처럼 문법상 홑따옴표는 2개를 쌍으로 사용해야 한다.

- 따라서, SQL 문을 조작할 때도 에러가 나지 않도록 주의해야 한다.

- test' or '1'='1을 입력하면 아래와 같은 SQL 문이 만들어진다.

 

 

- 모든 사이트가 동일한 형식으로 쿼리문을 생성하는 것은 아니다. 여기에서도 test' or '1'='1 뿐만 아니라 'or 1=1도 공격에 이용할 수 있다.

 

 

⊙ 패스워드 우회

- 패스워드가 틀려도 로그인에 성공할 수 있는지 확인하기 위해 로그인 창에 쿼리문을 입력해보자

 

 

 

- 로그인에 성공하였지만 TEST_ID가 아니고 admin으로 로그인 되었을까..

- SQL 문을 한번 더 보게 되면, 연산자  우선순위로 볼 때, AND는 OR보다 먼저 계산된다.

- 따라서, (bId='TEST_ID' and bPass='test')가 먼저 계산되어 그 결과가 FALSE로 되고, FALSE or (1=1)이 그 다음에 계산된다.

- 즉, FALSE or TRUE가 되어 결과적으로 TRUE가 되고 결국 4)와 같이 member 테이블에서 모든 레코드 값을 가져오게된다.

 

 

- 가져올 아이디 값이 정해지지 않았기 때문에, 가장 위쪽의 레코드를 읽어온다.

- 따라서, member 테이블에는 아래와 같이 2개의 계정만 존재하고, TEST_ID보다 admin이 위에 있다.

- 따라서, 가장 위에 있는 레코드의 admin 값을 가져오게 되어 admin으로 로그인에 성공한 것이다.

- 많은 경우에 관리자(admin)가 가장 위에 존재하기 때문에 이런 방법으로 관리자로 로그인 할 수도 있다.

 

 

⊙ 주석문을 이용한 admin 로그인

- 1)의 SQL 문을 2)처럼 바꾸면, 주석문(--) 이후의 문자열은 주석 처리되어 무시되므로 결과적으로 3)의 SQL 문이 된다.

 

 

- 이것을 로그인 페이지에서 입력해보자. ( 이 때도 홑따옴표를 잊지 말자.)

 

 

-  admin으로 로그인에 성공했다. 이제 이 게시판의 관리자 권한을 갖게 된 것이다.

 

 

▶ 시스템 명령어 실행

- xp_cmdshell은 MS-SQL DB에 잇는 master DB의 확장 프로시저로서, 이것을 이용하면 시스템 명령어(OS Call)를 실행할 수 있다.

- SQL 쿼리 분석기 창에서 xp_cmdshell을 사용하기 위해 등록할 떄는 다음과 같은 명령어를 실행하면 된다.

 

등록

 sp_addextendedproc 'xp_cmdshell', 'xplog70.dll

제거

 sp_dropextendedproc 'xp_cmdshell' 또는

 C:\Program Files\Microsoft SQL Server\MSSQL\Binn에서 xplog70.dll 삭제

 

⊙ 두가지 이상의 쿼리문 실행

- 두 가지 이상의 명령을 연속해서 사용할 때는, 세미콜론(;) 표시를 이용하여 사용할 수 있다.

- 먼저 member 테이블의 내용을 확인하고, 자기 자신의 시스템에 ping 명령을 수행하는 ping 127.0.0.1을 실핼하였다.

 

 

⊙ 시스템에 폴더 생성하기

- 앞서 테스트한 ping 127.0.0.1이 포함된 SQL injection 명령을 게시판에서 실행하면, 공격이 성공하여 잘 실행이 되어도 결과를 확인할 방법이 없다. 그렇기 때문에 폴더를 만들어 시스템 명령어가 잘 실행되었는지 확인하자.

- 폴더를 생성하는 명령은 다음과 같다.

 

 

- 로그인 페이지의 아이디 입력 폼에 위의 쿼리문을 입력하고 싶어도 할 수 없을 것이다.

- 왜냐하면 아래의 예제에서 그 내용을 확인할 수 있듯이 입력 값의 길이가 15로 제한되어 있기 때문이다.

- 이렇게 길이에 제한이 있어 원하는 SQL Injection 문을 직접 입력할 수 없는 경우도 있다.

 

 

- 이럴 때는 프록시 툴을 이용하여 길이 제약을 피할 수 있다.

- 예로들면 오디세우스 프록시 툴을 이용하여 SQL Injection 문을 서버로 전달할 것이다.

- 먼저 admin/admin 계정으로 로그인할 때 전송되는 내용을 확인해보자.

 

 

- memberid=admin 부분을 아래와 같이 조작하여 전송하면 길이 제한에 상관없이 시스템 명령어를 실행할 수 잇다.

- URL 인코딩을 위해 공백은 %20으로 변경해야 한다.

 

 

 

- admin 계정으로 로그인되었지만 게시판 리스트만 보일 뿐 특별한 내용은 없다.

- 명령어가 제대로 실행되었는지 실제로 폴더를 확인해보면 C:\board 아래에 test 폴더가 생성된 것을 확인할 수 있다.

 

 

▶ 테이블 정보 열람하기

⊙ 집계함수

- 집계는 이미 계산된 것들을 모아서 계산하는 것을 말한다.

- SQL의 집계 함수에는 avg(), sum(), count() 등이 있다.

- 즉, 이미 계산된 결과를 어떤 기준으로 그룹화 하는 함수들이다.

- 그룹화하는 기준을 집계 키라고 하는데, GROUP BY 절의 칼럼이나 연산식을 집계 키로 사용할 수 있다.

- GROUP BY 절에 사용된 집계 키들만 SELECT 목록에 사용할 수 있다는 것이다. 그렇지 않으면 에러가 발생!

- 예를 들어, 쿼리 분석기에서 아래의 명령을 실행. 여기에서 member.bId는 테이블명.필드명으로 특정 필드를 가리키는 표현 방식

 

 

- 아래와 같이 SELECT 절에는 bId, bPass, bName, bMail이 있고 GROUP BY절에는 member.bId만 있을 경우에 에러가 발생한다.

- 왜냐하면 bPass, bName, bMail은 GROUP BY에서 사용하는 집계 키가 아니라서 SELECT 절에 사용할 수 없기 때문이다.

 

 

⊙ 테이블 명 획득

- GROUP BY 절이 어떤 칼럼을 기준으로 그룹을 만들 때 HAVING는 결과를 다시 한번 더 필터링 하는 역할을 한다.

- 이것은 GROUP BY 절에 대한 조건, 즉 일반적인 SELECT 절의 WHERE와 비슷하다.

- HAVING는 단독으로 쓰일 수 없으며 GROUP BY 절과 함께 사용되어야 한다.

- 이 점을 이용하여 다음과 같은 명령을 검색어로 입력하면 에러가 발생하는 것을 확인 할 수 있다.

 

 

- 에러는 'bbs.idx' 열이 집계 함수에 없고, GROUP BY 절이 없으므로 SELECT 목록에서 사용할 수 없다는 내용이다.

- 이 에러 메시지에는 bbs라는 테이블 명과, idx라는 필드명을 언급함으로써 중요한 정보를 노출하고 있다.

 

 

⊙ 필드 명 획득

- 이전에 획득한 테이블 명과 필드 명을 다시 이용하여 검색 쿼리문에서 사용하면 bbs 테이블에 있는 다른 필드 명도 알아낼 수 있다.

 

 

- 입력 값으로 group by 조건에 idx를 추가하였다.

- 이렇게 하면 집계 키에 idx가 있으므로 그 다음에 있는 tId를 볼 수 있다.

- 하지만 이것은 집계 키에 없으므로 bbs.tId를 사용할 수 없다는 에러를 발생시킨다.

- 이런 방식으로 계속해서 아래와 같이 반복하면 bbs 테이블의 전체 필드 명을 알 수 있다.

 

 

 

 

 

 

 

- 이 과정을 통해 bbs라는 테이블에 idx, tId, tName, tMail, tTitile, tContent, tFilename, tfilepath, tRead, tDate라는 10개의 열리 존재한다는 것을 알 수 있다.

- 로그인 페이지에도 위와 동일한 방식으로 테이블의 필드 명을 알아낼 수 있다.

 

 

- SQL 쿼리 분석기에서 로그인 페이지에 대해 위의 과정을 실행하여 결과를 확인해보자.

- 쿼리 분석기에는 에러가 발생해도 끝까지 실행하기 때문에 전체 에러 메시지를 확인할 수 있다.

 

- 결국, member 테이블에 idx, bId, bPass, bName, bPost, bAssr1, bAddr2, bPhone, bMail, bDate 열이 있으며 로그인 페이지에는 이것을 이용하여 쿼리를 하고 있다는 것을 짐작할 수 있다.

 

⊙ 필드 타입 획득

- 이제 UNION과 sum()함수를 이욯아여 필드 타입을 알아보자

- sum() 함수에는 숫자형만 사용할 수 있고 UNION을 사용하기 위해서는 두 테이블의 필드 수가 동일해야 한다.

- admin으로 로그인을 한 후 게시판 리스트 하단에 게시글을 검색하는 입력 폼에 테스트

- 아래의 board_search.asp 파일을 열어 확인해보면 검색어(Keyword)를 받아, Select * From bbs Where tTitle like '%keyword%'을 생성

- 쿼리문이 제대로 실행되면 제목에 keyword가 포함되어 있는 게시글을 찾아서 보여줄 것이다.

 

- 검색어에 union을 사용하여 member 테이블과 bbs 테이블의 필드 타입을 알아낼 수 있다.

 

 

 

- sum() 함수는 varchar 타입을 사용할 수 없기 때문에 에러가 발생하게 되고 bId가 varchar타입인 것을 알 수 있다.

- 동일한 방법으로 member 테이블의 bId, bPass, bName, bpost, bAddr1, bAddr2, bPhone, bMail과 bbs 테이블의 tId, tName, tMail, tTitle, tContent, tfilename, ffilepath가 varchar 타입을 사용한다는 것을 확인할 수 있다.

 

 

 

- 그리고 member.bDate와 bbs.tDate가 datetime 데이터 형식을 사용한다는 것도 확인하였다.

- 이제 member.idx와 bbs.idx, bbs.tRead만 확인하면 된다.

- 아래의 결과는 UNION에서 필드의 개수를 맞추지 않았기 때문에 에러가 발생했다는 것이며, 이는 데이터 형식에 대한 에러가 아니기 때문에 idx가 숫자형이라는 것을 유추할 수 있다.

 

 

 

- 실제 우리가 사용하는 테이블과 그 내용이 동일함을 알 수 있다.

 

member 테이블

bbs 테이블

필드 명

필드 타입

필드 명

필드 타입

idx

숫자

idx

숫자

bId

varchar

tId

varchar

bPass

varchar

tName

varchar

bName

varchar

tMail

varchar

bPost

varchar

tTitile

varchar

bAddr1

varchar

tContent

varchar

bAddr2

varchar

tfilename

varchar

bPhone

varchar

tfilepath

varchar

bMail

varchar

tRead

숫자

bDate

datetime

tDate

datetime

 

 

1. XSS ( Cross Site Scripting)

- 사용자로부터 입력받은 값을 검증하지 않고 바로 실행해서 생기는 취약점

- XSS 공격 자체로는 아무런 영향이 없으나 함께 사용되는 코드에 따라 여러 가지 공격이 발생할 수 있다.

- 가령, 사용자가 접근하는 웹 페이지에 XSS 공격 코드를 삽입하여 사용자가 원하지 않는 페이지로 이동하거나 악성 코드를 감염시키거나 사용자 정보를 수집하는 공격이 만들어질 수 있다.

 

2. XSS 공격 가능 여부 테스트

- 보안상 많은 게시판이 XSS 공격이 가능하지 않도록 관리되고 있다.

- 게시물에 공격 스트립트를 입력 후 게시물을 올려보자.

 

 

- 방금 등록한 게시물을 클릭하면, 게시물을 클릭한 사용자의 쿠키 값이 팝업 창 형태로 나타난다.

- 팝업창이 성공적으로 나타나면 해당 게시판은 XSS 공격에 취약하다는 뜻이다.

 

 

3. XSS 공격

- XSS 공격 스트립트가 입력된 게시물을 관리자가 읽으면 관리자의 쿠키 값이 getcookie.txt 파일에 저장된다.

- 공격자는 이 파일에 저장된 쿠키 값을 이용하여 관리자 계정 권한으로 게시판에 접근한다.

- 그러기위해서는 ASP 파일을 작성해야된다. 이 ASP 파일은 파라미터로 받은 쿠키 값을 getcookie.txt라는 이름의 텍스트 파일로 저장되는 역할

 

 

- 위의 시나리오대로 진행하기 위해서 먼저 getcookie.asp 파일을 업로드 해야 한다.

 

 

- 게시물이 정상적으로 등록되었음을 확인할 수 있다.

- 이제 첨부파일이 업로드된 경로를 확인해야 할 차례이다.

- XSS 공격 시 획득된 쿠키 값은 getcookie.asp 파일로 보내어져 텍스트 파일 형태로 저장되므로 해당 ASP 파일이 업로드된 경로를 알아야한다.

 

 

- 이제 본격적인 XSS 공격을 시작하기 앞서 공격 스트립트를 입력해보자

 

 

- 게시판에서 로그아웃한 후 관리자 계정으로 로그인 한 후 앞서 XSS 공격 스트립트 게시물을 읽어본다.

 

 

- 획득한 쿠키 값을 이용하기 위해 getcookie.asp 파일을 업로드한 경로에 접근해야 한다.

- 업로드 경로와 같은 경로에 getcookie.txt 파일이 생성되는데, 주소창에 http://IP주소/board/pds/getcookie.txt를 입력하면 관리자로부터 획득한 쿠키 값이 보이게된다.

- 관리자로부터 획득한 쿠키 값을 붙여넣기한 후 Cooxie Toolbar에 붙여넣기한 후 Set 버튼을 클릭한다.

 

 

- 현재 쿠키 값을 설정한 인터넷 익스플로러의 주소 창에서 http://IP주소/board/board_list.asp를 입력하면, 원래는 로그인 과정을 거쳐야 게시판 리스트를 볼수 있으나 쿠키 값 설정을 통하여 로그인을 하지 않고 게시판 리스트를 볼 수 있다.

- 또한, 관리자의 쿠키 값을 가지고 했기 때문에 관리자로 접속이 되어 있는 것을 확인 할 수 있다.

 

 

4. 대응방법

- XSS 공격을 하기 위해서는 기본적으로 "<", ">"와 같은 기호가 포함되어야 한다.

- 사용자 입력 폼이나 URL의 입력 값을 검증하여 "<", ">"가 포함되어 있는지를 확인하여 필터링해야 한다.

- 특수 문자나 예외 문자를 필터링하기 위해서 replace() 함수를 사용할 수 있다.

- replace(문자열, 찾을 문자열, 바꿀 문자열)

 

▶ 게시판 리스트를 보여주는 페이지에서 스트립트 필터링

- 게시판 화면 페이지에서 검색 구문에 <script>alert(document.cookie)</script>를 입력하게 되면 게시판에 작성된 쿠키 정보 팝업창이 뜨게 된다.

 

 

- 게시판 검색 구문이 들어간 board_serach.asp 파일에 replace() 함수 구문을 넣어서 "<", ">"을 필터링 시켜준다.

 

 

- 파일을 저장하고 게시판 리스트를 보여주는 페이지에 쿠키 정보를 확인하기 위해 사용했던 <script>alert(document.cookie)</script>를 입력

- 더 이상 쿠키 정보 팝업 창이 뜨지 않음을 확인 가능

 

 

▶ 게시물 최초 등록시 스트립트 필터링

- 게시판에서 게시물 등록시 나오는 화면으로 다른 파일과 그 파일에 넘어가는 인자들을 소스보기(FORM)으로 알 수 있다.

 

 

- 인자들이 넘어가는 board_write_reg.asp 파일에 아래와 같이 replace() 함수를 사용하여 문자를 필터링할 방어소스를 넣어준다.

 

 

- 쿠키 정보를 확인하기 위해 사용했던 <script>alert(document.cookie)</script>을 입력 후 게시판 게시물 등록하여 게시물 확인.

- 더 이상 쿠키 정보 팝업 창이 뜨지 않음을 확인, 그저 소스가 출력된다. ( 문자 필터링 완료 )

 

 

 

▶ 게시물 수정 시 스트립트 필터링

- 게시물에 공격 스트립트를 입력 한 게시물을 수정하여 올려보자.

 

 

- 방금 수정한 게시물을 클릭하면, 게시물을 클릭한 사용자의 쿠키 값이 팝업 창 형태로 나타난다.

- 이와 같이 팝업 창 형태로 뜨는 이유는 수정하는 asp파일이 다르기 때문이다. 

 

 

- 게시판에서 게시물 수정시 나오는 화면으로 다른 파일과 그 파일에 넘어가는 인자들을 소스보기(FORM)으로 알 수 있다.

 

 

- 인자들이 넘어가는 board_update_reg.asp 파일에 아래와 같이 replace() 함수를 사용하여 문자를 필터링할 방어소스를 넣어준다.

 

 

- 쿠키 정보를 확인하기 위해 사용했던 <script>alert(document.cookie)</script>을 입력 후 게시판 게시물 수정하여 게시물 확인.

- 더 이상 쿠키 정보 팝업 창이 뜨지 않음을 확인, 그저 소스가 출력된다. ( 문자 필터링 완료 )

 

 

1, 프록시(Proxy)

- 어떤 일을 대신하거나 위임받을 경우에 쓰인다.

- 인터넷에서는 PC와 인터넷을 중개 역할을 해주는 것이라 할 수 있다.

- IP를 변조하고자 할때 프록시 서버를 사용하는 경우가 많다.

- 클라이언트가 서버로 접속할 때 프록시 서버를 통하면 서버에서는 클라이언트 IP를 모르고 프록시 서버 IP만 알게 되기 때문에 IP 변조가 가능하다.

 

 

2. 웹 프록시

- 앞에 알아본 프록시와 개념은 동일

- 웹에 대해서만 프록시를 사용하기 때문에 웹 프록시라고 불린다.

- 외부 프록시 서버를 거치는 것이 아니라 클라이언트가 웹으로 접근할 때 클라이언트 시스템에 있는 웹 프록시 프로그램을 거쳐 나가도록 한다.

- 클라이언트와 서버 사이에 어떤 내용을 주고 받는지 확인할 수 있고, 그 내용도 수정 가능

 

 

+ Recent posts