Code Generator?
이름 그래도 코드를 생성해주는 기능입니다. 자주 애용하던 기능이라 불편함이 바로 찾아왔는데요, 바로 Code generator 입니다.Burp suite에선 reissue request scripter 확장 기능으로 Request를 Python, Ruby, HTML 등 여러가지 언어 형태로 바로 변환할 수 있습니다.
(https://portswigger.net/bappstore/6e0b53d8c801471c9dc614a016d8a20d)
Burp suite에서도 확장 기능을 통해 해결된 부분이라 ZAProxy에서 찾아봤지만 확장 기능으로 따로 제공되진 않네요. 그래서 만들까 생각을 하던 중 ZAProxy에서 제공하는 Scripts 엔 없을까 하고 뒤져봤는데.... 이럴수가 유사한 기능을 찾았습니다.
CSRF Poc Genertor 인데요, 이 이야기인 즉슨 Request 데이터를 읽어와서 원하는 대로 파싱하고 문자열을 붙여서 기능을 만들 수 있다는 이야기가 되겠지요.
그래서 Scripts 작성을 통해 해결해봅니다.
(Request => HTML의 경우는 CSRF Poc 사용하면 될 듯 합니다. 전 Reuqest => Ruby로 작성해봅니다)
Write Code for generator
우선 Script 종류는 여러가지를 사용할 수 있습니다. 우선 ECMAScript(Javascript), Mozila Zest Script가 기본으로 탑재되어 있고 확장 기능 설치를 통해 Ruby, Python, Groovy 등 여러가지 언어에 대해 스크립팅을 할 수 있도록 추가가 가능합니다.(관련해서 지난 포스팅에 유용한 확장 기능에 있었죠!)
Ruby로 짤까 고민했지만 JRuby는 그닥 땡기지 않기 떄문에 많이 사용하는 JS로 작성합니다. (사실 보안분석 때문에 JS가 더 익숙할지도...)
Request/Response, Requester 등 요청 정보가 있는 곳에서 우클릭 > 특정 메뉴 선택으로 코드를 생성하는 것을 생각했기 떄문에 Tageted type API인 invokeWith를 사용하면 조금 편합니다.
작성전에 몇가지만 체크합시다.
1. invokeWith를 통해 우클릭 시 해당 위치에 타겟팅(포커싱)된 요청 값을 msg 인자값으로 넘겨줍니다.
2. 우리는 msg 값을 이용해서 Method, URL 등을 가져올 수 있습니다.
3. 이 과정은...
- Method : msg.getRequestHeader().getMethod()
- Url : msg.getRequestHeader().getURI()
- clipboard 제어 : java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
=> jruby 처럼 java 코드에 접근해서 가져오면 됩니다.
Add script 해서 하나 만들면 되요. 결과는 Clipboard 복사 및 Log에 찍힙니다. |
Request to Ruby Generator Code
작성하는 과정을 하나하나 작성할 순 없으니.. 기본 동작만 하는 풀 코드로 올립니다.GET/POST 구별 정도만 하고있고 JSON, Multipart는 코드 추가해야할 것 같네요.
손봐야할 부분이 많긴한데, 조만간 정리해서 git에 올려두도록 하겠습니다.
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//Author : @hahwul
function invokeWith(msg) {
var method = msg.getRequestHeader().getMethod();
var url = msg.getRequestHeader().getURI().toString();
code = 'require "net/http"\n';
code = code + 'require "uri"\n';
code = code + 'uri = URI.parse("'+url+'")\n';
code = code + 'http = Net::HTTP.new(uri.host, uri.port)\n';
if(method == "GET"){
code = code + 'request = Net::HTTP::Get.new(uri.request_uri)\n';
}
else if(method == "POST"){
code = code + 'request = Net::HTTP::Post.new(uri.request_uri)\n';
body = msg.getRequestBody().toString();
body = body.trim();
if(isJson(body)){
a=1;// JSON Proc
}
else{
if(ismultipart(msg.getRequestHeader())){
a=1;// Multipart Proc
}
else{
body=body.split('&');
code = code + 'request.set_form_data({';
for(i=0;i<body.length;i++)
{
keyval = body[i].split('=');
code = code + '"'+ decodeURIComponent(keyval[0]) + '" => ' + '"' + decodeURIComponetn(keyval[1]) + '",';
}
code = code + '"endendend"=>"endendend"}';
}
}
}
code = code + 'request["Accept"] = "*/*"\n';
code = code + 'request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0"\n';
code = code + 'request["Connection"] = "close"\n';
code = code + 'request["Accept-Language"] = "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3"\n';
code = code + 'request["Accept-Encoding"] = "gzip, deflate"\n';
code = code + 'response = http.request(request)\n';
code = code + 'puts "[$] Code: "+response.code\n';
code = code + '#puts "[$] Response Body: "+response.body\n';
code = code + '\n';
print(code);
selected = new java.awt.datatransfer.StringSelection(code);
clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selected,null);
}
function isJson(str)
{
try{
JSON.parse(str);
}
catch(e){
return false;
}
return true;
}
function ismultipart(header){
type = header.getHeader(org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE);
if(type == null )
return false;
if(type.contains("multipart/form-data"))
return true;
return false;
}
Run!
Context menu > Request_to_ruby(이름 좀 잘 지을껄 그랬나..) |
복사된 코드로 테스트해보면 잘 요청됩니다 :) |
HAHWULSecurity engineer, Gopher and H4cker! |
0 개의 댓글:
Post a Comment