Cross Site Scripting(XSS) concept
XSS Test
시나리오 #1
시나리오 #2
XSS 대응방안
Reference
Cross Site Scripting(XSS) concept
Cross Site Scripting은 사용자에게 공격 목적의 악의적인 웹 컨텐츠를 보내는 공격 방법이다. 공격자가 사용자에게 보내는 악의적인 웹 컨텐츠는 URL에 포함된 스크립트 코드이거나 보안에 취약한 웹 사이트의 폼 필드에 입력된 스크립트 코드가 될 수 있다.
일반적으로 HTML 코드에 의해 미리 정의된 위치에 평범한 텍스트 형태로 브라우저 상에 표현되지만 HTML은 그런 평범한 텍스트뿐만 아니라 다른 다양한 컨텐츠를 표현하고 Client Side Script Code 를 포함할 수 있다.
Client측 Script는 Sendbox 로 알려진 제한된 환경에서 동작하기 때문에 대부분의 경우 local에는 악영향을 미치지 않는다. Cross Site Scripting 공격이 의미하는 바는 정확히 어느 한 사용자가 입력한 스크립트 코드를 다른 사용자의 컴퓨터에서 실행시키는 것 이다. 즉 XSS의 가장 큰 특징인 Server가 아닌 Client를 공격하는 것 이다. Sendbox 덕분에 사용자는 심각한 침해로부터 보호 받을 수 있지만 Client Script Code는 코드에 명시된 파일이나 로컬 리소스에 접근해서 자신의 정해진 동작을 수행할 수 있어야 한다. 바로 이 점이 위험을 내포하고 있는 것이다 실행되는 스크립트 코드는 현재의 웹 페이지에 포함된 모든 정보에 접근할 수 있으며 악의적인 의도를 가진 공격자가 XSS를 이용해서 사용자의 쿠키를 훔쳐 낼 수 있고 마치 그 사용자인 것처럼 행세할 수도 있으며 다른 악의적인 사이트로 사용자를 이동시키거나 교묘히 웹 페이지 내용을 조작해서 사용자가 개인 정보를 입력하게 할 수도 있음을 의미한다.
XSS공격은 주로 사용자의 SessionID 나 Cookie값을 훔쳐내어 권한을 훔쳐내는 기법이 사용되며.
본 문서에서는 Session 과 Cookie를 따로 설명 하지는 않고 Cookie Stealing 에서 자세히 다루겠다.
XSS 공격은 저장(Stored)XSS 와 반사(Reflected)XSS 이렇게 크게 두 가지가 있다.
우선 첫 번째로는 저장(Stored)XSS 에 대해 살펴보겠다. 저장XSS는 공격자가 XSS 보안 취약점 공격을 위해 가장 많이 살펴보는 곳이 같은 사이트를 방문하는 다른 사용자들에게 보이는 데이터를 입력하는 부분이다. 즉 메시지입력 부분, 방명록, 댓글, 등을 남기기 위해 사용자가 입력하는 부분이다. 공격자는 이러한 FORM필드 부분에 악의적인 스크립트를 저장하고 후에 어떤 사용자가 해당 사이트의 같은 곳을 방문하면 해당 스크립트가 웹 페이지에서 로드면서 코드가 실행되는 것이다.
두 번째로는 반사(Reflected)XSS 공격이며 반사()XSS 공격은 URL의 CGI 인자에 스크립트 코드를 삽입하는 것이다. 공격자가 이 메일을 이용해 어떤 웹 페이지 링크를 보내고 그 링크를 전달받은 사용자가 링크를 클릭하면 그 링크에 대한 웹 페이지가 로드 된다. 그 때 웹 페이지에 대한 링크 URL에 삽입된 스크립트 코드가 실행되면서 웹 페이지의 내용이 변경된다. 이 공격은 스크립트를 저장하기 위한 웹 사이트는 필요하지 않으며 사용자가 조작된 링크 주소를 클릭하면 링크에 대한 웹 페이지가 로드 되면서 그 스크립트 코드가 실행되기 때문이다.
공격 대상
사용자가 웹 사이트에 입력한 데이터를 해당 웹 사이트를 방문한 다른 사용자가 볼 수 있는 경우에 이 공격을 적용할 수 있다. XSS 공격에 취약한 부분이 발견 되었더라도 다른 사용자가 그 부분을 접하지 않으면 아무런 소용이 없다. 당연한 이야기 이지만 이유는 간단하다 XSS공격의 특징은 ServerSideScript 가 아니라 Client SideScript 이기 때문이다.
공격 수행 방법 HTML은 웹 페이지에 스크립트 코드를 삽입할 수 있는 여러 가지 메커니즘을 제공하며 그 중에서도 가장 명확한 것이 <script>…</script> 태그를 이용하는 것이다. 우선 공격할 FORM 필드에 <script>alert(“XSS Attack”)</script>를 이용하여 다음과 같이 메시지박스가 뜬다면 XSS 공격에 취약한 것으로 본다.
HTML 태그는 스크립트 삽입에 취약하다. 예를 들면 IMG 태그가 그런 경우라고 할 수 있다. <img src=”path/image.gif>
위의 img 태그를 다음과 같이 수정할 수 있다.
<img src=javascript:alert(“XSS alert!”)> HTML 태그 전반적인 문제들이 있으며 STYLE, SRC, HREF, TYPE 속성을 지원하는 태그들이 대부분 마찬가지이기 때문에 HTML 태그 자체를 필터링하는 것은 어려운 일이다. 하지만 공격자는 단지 메시지 창을 띄우는 것이 아니라 공격자는 세션 ID를 포함하는 중요 정보를 얻고자 하며 <script>alert(document.cookie)</script>를 이용하여 쿠키의 값을 보여줄 수 있는 메시지 박스를 띄우도록 한다.
하지만 이런 쿠키정보는 공격자 입장에서는 아무런 도움이 되지 못한다. 공격자에게 도움이 되려면 원격으로 이 쿠키정보를 획득 할 수 있어야 하며 획득 할 수 있는 방법도 여러 가지가 존재한다. 실제적인 공격방법은 시나리오를 통해서 알아 보도록 하겠다.
XSS 입력 과정/공격절차
1. 공격자가 XSS 취약점이 존재하는 서버에 악성 스크립트를 게시
2. 관리자 또는 사용자가 로그인을 실시하고 토큰(Cookie 또는 SessionID)생성
3. 공격자가 게시한 악성 스크립트를 보거나 클릭
4. 관리자 또는 사용자의 토큰이 공격자에게 전송
5. 공격자가 해당 토큰을 이용/다른 사용자의 권한을 가장 또는 소유
희생자가 메일을 읽으면 다음과 같은 화면이 나타날 것이고 이 화면을 본 순간 희생자의 쿠키 값은 공격자의 웹 서버에 남게 된다.
공격자의 C:\xss\xss.txt 파일에는 쿠키 값이 남게 된다.
공격자는 훔친 쿠키로 로그인 해서 희생자의 개인정보를 알아낼 수 있다.
XSS 대응방안
기술적인 XSS 방어방법을 설명하기 이전에 어떤 것을 어떻게 해야 하는지부터 설명을 하겠다.
스크립트 코드를 실행하기 위한 대표적인 코드는 <script>…</script> 태그가 있다. 하지만 이 태그 이외에도 HTML, 자바스크립트, VB스크립트, 액티브X, FLASH 등과 같이 다양한 스크립트 언어나 삽입기술이 XSS 공격에 이용될 수 있다.
이렇게 때문에 허용되어서는 안 되는 데이터를 필터링 하는 방법보다는 허용 가능한 데이터만 필터링 하는 편이 낫다.
가장 확실하고 쉬운 방법은 데이터가 코드로 해석되는 것을 방지하는 것인데 즉 HTML에서 모든 코드는 < >안에 존재한다. 생각해보면 모든 각 괄호를 해당 인코딩 값으로 교체하면 데이터가 코드로 잘못 인식되는 경우는 발생하지 않는다라는 이야기가 된다.
필자가 생각해본 방어방법 중 하나는 HTML 삽입 부분을 없애는 것이다. 그렇다면 서비스 측면에측 볼 때 상당히 성능이 떨어진다고 생각하지만 HTML 툴을 쓰는 것이 가장 효율적이지 않나 하는 생각을 한다. 물론 이미지삽입 공격이나 첨부파일형식의 공격은 못 막겠지만 말이다. 평소 생각하고 있었던 것을 이 문서를 통해 말하는 바이다.
우선 XSS 공격이 되는 게시판에 테스트를 해보고 HTML 인코딩 을 적용시키는 예를 살펴보자
다음과 같이 스크립트가 적용되는 것을 볼 수 있다.
contents = Server.HTMLEncode(Request("contents"))
CONTENTS 부분을 HTML Encode 시킨다면 다음과 같이 <script> 태그가 적용이 안 될 것이다. 이 방법의 문제점은 CONTETS 부분에 HTML 태그 전부를 인코딩 하는 결과가 발생된다.
content = ConvertTohtml(content)
content = Replace(content,"'","''")
content = replace(content ,"&","&")
content = replace(content ,">",">")
content = replace(content ,"<","<")
Replace 구문을 쓰게 되면 해당 태그를 필터링 시킬 수 있다.
Reference
- 황순일,김광진.(2005) “웹 해킹 패턴과 대응” 사이텍미디어
- 마이크엔드류스/제임스A.휘태커.(2006) “How to Break Web Software : Funtional and Security Testing of Web Applications and Web Services” Pearson
2009년 7월 7일 발생한 DDOS 공격이 청와대, 네이버, 각 은행, 국내 주요 사이트 운영에 장애를 유발
악성코드는 기존 C&C 서버로부터 공격 목표를 전달받는 것이 아니라 감염시 생성되는 공격목표(하드코딩 됨) 설정 파일을 기반으로 공격
perfvwr.dll 이 Service 로 등록되어 uregvs.nls(하드코딩된 파일) 로 GET Flooding 공격을 수행
perfvwr.dll → " Performance Analyzer" 라는 이름으로 Service 에 등록이 되어 있음 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services → perfvwr 항목있는지 검사
uregvs.nls → 공격대상 , Domain , 공격 방법 등이 명시된 내용을 포함
HTTP GET 요청으로 발생하는 Traffic 비율이 전체 공격 Traffic의 92.4%로 대부분을 차지함
User-Agent의 입력 값은 다섯 가지 형태가 있습니다.
- User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6;.NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
- User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1;Trident/4.0; GTB6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NETCLR 3.5.30729)
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;rv:1.8.1.20) Gecko/20081217 Firefox/2.0.0.20 (.NET CLR 3.5.30729)
- User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;InfoPath.2; MAXTHON 2.0)
- User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;Trident/4.0; GTB6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NETCLR 3.5.30729)
하지만 위 요청들은 모두 정상적인 요청으로 Signature 로 차단하기 매우 힘듬
POST 형식 중 Content-Length:0 HTTP 규악에는 위배되지 않지만 비정상적이라 생각할 수 있음
브라우저 형식 별로 국내환경을 고려해 차단 가능 하지만 어디까지나 환경적 요소가 강함 Accept-Language: zh-cn 를 패턴화시킴 (환경적으로 중국 OS 를 사용하는 사용자는 거의 없음)
CC 공격 : Cache-Control: no-store, must-revalidate Signature 만듬
Request Packet 에는 CC 사용하는 경우는 거의 없지만 Response 에서는 가끔 있음
매번 꾸준히 발견되며 국내 웹 사이트의 대다수가 SQL injection에 노출되어 있다.
보안성 강화 차원에서 L7 까지 패턴화 시켜 공격을 막는 솔루션 즉 웹 방화벽이라는 것이 있지만
이 역시 솔루션의 한계를 들어낼 수 밖에 없다.
웹 방화벽의 기본적인 특징은 SQL injection 의 패턴들을 위에서는 ' or 1=1-- 라는 것을 시그니처화 시켜 패턴이 발견되면 Request Packet 을 Drop 하는 형태이다.
하지만 SQL injection 의 수 많은 패턴을 전부 등록하고 미리 예측하여 등록하기란 사실상 불 가능에 가깝다.
패턴을 정교하게 만들지 않으면 서비스 가용성에 문제가 생길 수 밖에 없는 현실 때문이다.
본론으로 SQL injection은 사용자로 부터 입력 받은 데이터를 이용하여 동적으로 Query 구문을 오나성 할 수 있는 페이지에서 적절한 검증 없이 DB Query문의 일부로 포함되는 경우 발생하며 DBMS가 의도되지 않은 결과를 반환하며 입력 값에 대해 그 적정성을 검사하지 않았기 때문에 발생 한다.
SQL injection은 입력 값 검증 부재 의 일종이이다.
정의를 내리자면 웹 페이지를 통해 입력된 Parameter 값을 이용하여 Query 를 재 구성 하는 방법 이라고 할 수 있다.
우선 SQL injection 을 하기 위해서는 공격대상의 DB를 파악한 후 해당 DB 의 Table Name 과 Column Name 을 알아낸 후 공격자가 원하는 필드 값을 획들 하는 형식의 공격이 이루어 진다.
처음 DB Schema 파악 하는데 ( 'and db_name() > 1-- ) db_name()을 이용하여 DB Name 을 알아낸다. db_name()은 MS-SQL에서 DB 이름을 문자열로 반환하는 함수 이며 결과 값은 당연히 에러 메시지가 뜨게 되어 있다. 문자열을 정수랑 비교했는데 에러가 안나겠는가 ??
에러 형식:
Microsoft OLE DB Provider for SQL Server (0x80040E07)
nvarchar 값 ‘oyesmall'을(를) int 데이터 형식의 열로 변환하는 중 구문 에러가 발생했습니다.
/demoshop/login/findNewaddr.asp, line 192
oyesmall 이라는 DB를 토해내는 것을 볼 수 있다.
여기서 우리는 첫 번째 정보를 획득한 것이다. DB NAME = oyesmall 이다.
두 번째 DB안에 있는 table 을 알아야 한다. DB table 은 table 명을 포함한 system table 을 이용하는 것이다. 사실 table 을 직접 참조하는 것이 아니라 system view 에 의해 반환되는 형식이다.
information_schema.tables 라는 시스템 뷰를 이용해 table 명을 알아 낼 때는 UNION 구문의 형식은 선행 table 의 column 개수가 동일 해야 한다.
table을 알아내는 방법에는 여러 가지가 존재한다. tables 이름을 하나씩 제거 하던가 .. 비교연산을 통한 TOP 구문을 이용하여 검색결과를 하나씩 늘려가던가 필자는 통상적으로 Guessing 으로 알아내는 경우가 더 많다.
오류 형식:
Microsoft OLE DB Provider for SQL Server (0x80040E14)
UNION 연산자를 포함하는 SQL 문의 모든 쿼리는 대상 목록에 동일한 개수의 식이 있어야 합니다.
/demoshop/login/findNewaddr.asp, line 192
마지막으로 table 안의 column을 알아야 하며 table을 알아내는 방법과 동일 하지만 system view 를 달리 써야한다. table name 은 information_schema.tables 를 사용했지만 column은 column은 명을 포함하고 잇는 system view 를 사용하여야 한다.
information_schema.column을 이용할 경우에는 table_name 과 column명을 포함하고 있다.
SQL injection의 효과 : Application에서 사용하고 있는 DB 정보 조회/변조/삭제
아주 간단한 SQL injection
로그인 우회를 하기 위해 'or '1'=1 구문을 사용해 우회해보자 처음 등록된 사용자로 로그인이 된다.
다음은 우편번호의 SQL Query 가 어떻게 날라가는지를 생각해본다.
[133-824] 서울 성동구 성수1가2동 670 사용자가 다음과 같은 우편번호 조회를 했다고 가정해 보면 SQL Query 는 다음과 같이 날라 갈것이다.
Select ‘우편번호’, 시, 구, 동 from zipcode where 동=’성수1가2동’;
SQL Query 를 만들어 냈다면 다음 공격은 간단하게 진행이 된다. 우선 Union 구문의 특성을 생각해보자. Union 구문의 특성의 가장 큰 특징은 바로 COLUMN 개수가 동일 해야 한다는 것이다.
UNION SELECT '1','2','3'TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--
이와 같은 형식이 될 것이며 information_schema.tables--과 table_name 은 위에서 설명했으므로 생략하겠다.
실제 공격을 진행해 보도록 하겠다.
$'UNION SELECT '1','2','3','4',TABLE_NAME FROM INFORMATION_SCHEMA.TABLES –
입력하여 해당 데이터베이스의 TABLE을 볼 수 있다.
다음 공격은 해당 TABLE 에 대한 COLUMN 을 알아내는 것이다.
$'UNION SELECT '1','2','3','4', COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= 'admin_tb' --
이 구문은 ‘admin_tb’ 테이블의 COLUMN 을 나타내는 구문이다.
'union select '1','2','3',adminid, adminpwd from admin_tb--
아주 간단한 구문이다 admin_tb 테이블에서 adminin, adminpwd COULMN 값을 볼 수 있으며 이 구문 이외도 아주 다양한 구문이 존재한다.
가령 $' or 1=(select top 1 adminid from admin_tb)-- 이 구문은 말도 안되는 구문이다 정수랑 문자열이랑 같다고 했으니 말이다. 하지만 알아야 할 것은 에러페이지 안에 adminid가 존재할 것이다
Microsoft OLE DB Provider for SQL Server (0x80040E07)
varchar 값 'goodbyestar'을(를) int 데이터 형식의 열로 변환하는 중 구문 오류가 발생했습니다.
/demoshop/login/findNewaddr.asp, line 192
자 그럼 마지막 단계인 password 를 한번 획득해 보자.
$'union select '1','2','3','4' adminid,adminpwd from admin_tb where adminid='goodbyestar' --
admin_tb 테이블안의 adminid,adminpwd COLUMN 값 중 adminid 가 goodbyestar 인 것을 출력하라는 뜻이다.
SQL Injection 대응방안
SQL Injection의 방어 방법에는 여러 가지가 존재한다.
방어 방법에는 사용자 입력 값에 대한 검증이 이루어져 하고 적절한 데이터 길이 제한 같은 1차적인 룰이 있어야 한다. 하지만 데이터 길이 제한 같은 경우 쉽게 우회가 가능하므로 확실한 대비책이라고는 볼 수 없다. 적절한 오류 처리 및 IDS/웹 방화벽 구축 이 있으며 로그분석 또한 공격자의 추적에 도움이 된다.
첫 번째로는 사용자 입력 값에 대한 SQL Injection을 유발 시킬 수 있는 대표적인 싱글쿼테이션(‘) 을 필터링 시키는 방법을 알아 보도록 하겠다.
UserID = Request.Form("User_ID")
PassWD = Request.Form("PassWD")
위 코드는 Request객체에 Form메소드를 사용하여 User_ID 와 PassWD 값을 파라미터 값으로 받아왔지만 어디에도 User_ID 와 PassWD 를 검증 하는 코드는 존재하지 않는다.
UserID = Request.Form("User_ID")
PassWD = Request.Form("PassWD")
UserID=Replace(UserID,"'","''")
PassWD=Replace(PassWD,"'","''")
Replace함수로 (‘) , (“) 을 필터링 한 코드이다. 이렇게 되면 다음과 같이 SQL Injection 유발 문자열을 필터링 할 수 있다
..................................................... 아무말도 하고 싶지 않아 !! ..................................................... 소주는 한잔 먹고 싶긴 해 !! ..................................................... 울고 싶기도 하고 ..................................................... 많이 가슴이 아프기도 해 ..................................................... 난 괜찮으니까 너만 행복하면 될꺼라 생각해 ..................................................... 행복하지 ?? ..................................................... 그럼 된거야 !! ..................................................... 나 신경쓰지 않아도 되니까 ..................................................... 걱정하지말고 !!
..................................................... 원래 내가 소심해 ..................................................... 그게 아니라면 ...... ..................................................... 다음에 갈때는 손잡고 같이 가자 !!
댓글