간단하게 ZAP Scripting 배워보기

오늘은 ZAP Scripting을 처음 접할 때 익숙해지기 좋은 예제 두가지를 소개해볼까 합니다. 이 글을 읽어주시면, 간단한 코드 작성으로 ZAP에서 데이터를 조회하거나, 3rd party 스캔을 요청하는 방법을 얻어가실 수 있을거에요 😊

ZAP Scripting

ZAP에서 Scripting은 좌측 Tree Window에서 Scripts를 누르면 각 타입 별 스크립트를 보실 수 있습니다. 그리고 중간의 Workspace window의 Script console을 눌러보시면, 스크립트를 작성하고 테스트해볼 수 있는 공간이 나타납니다.

오늘은 여기서도 Targeted script에 대한 이야기를 하려고 합니다.

Targeted Script

ZAP에서 Targeted Script는 각 Request/Response에서 실행할 수 있는 Script 입니다. 기본적으로 msg object를 통해 Request와 Response 정보를 가져올 수 있고, 이를 기반으로 스크립트를 작성할 수 있습니다.

보통은 스캔성 작업이나 Payload 생성 등 조금 귀찮은 작업들을 스크립트화 하여 사용하곤 하죠.

Structure

구조는 간단합니다. invokeWith 메소드를 정의하면 History에서 우클릭 > Invoke withScripts > 실행할 스크립트 선택 시 해당 스크립트가 실행되고, 이 때 Req/Res 정보를 msg Object로 받게 됩니다.

function invokeWith(msg) {
	// logic!
}

Msg object

자주 사용되는 코드 스니펫입니다.

var url = msg.getRequestHeader().getURI().toString();
// https://www.hahwul.com

var host = msg.getRequestHeader().getURI().getHost(); 
// www.hahwul.com

var req = msg.getRequestHeader().toString()+msg.getRequestBody().toString()
// POST /blahblah
// 
// a=1

var responseBody = msg.getResponseBody().toString()
// <html>
// blahblah..

var responseHeader = msg.getResponseHeader().getHeader("Server")
// Apache

웹에서 검색하기

openUrlInBrowser

org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser() 함수는 ZAP에서 제공하는 인자 값으로 받은 URL을 브라우저를 통해 여는 기능입니다. Proxy걸린 Embeded browser가 아닌, System에서 기본 값으로 명시된 브라우저라는 특징이 있습니다.

org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser("https://google.com")

Case Study

SSLLab 검색

function invokeWith(msg) {
	var host = msg.getRequestHeader().getURI().getHost(); 
	org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser(
		"https://www.ssllabs.com/ssltest/analyze.html?d=" + host + "&latest");
}

Google Dork

function invokeWith(msg) {
	var host = msg.getRequestHeader().getURI().getHost(); 
	org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser(
		"https://www.google.com/search?client=safari&rls=en&q=site%3A"+ host + "+inurl%3Atest&ie=UTF-8&oe=UTF-8");
}

API를 통해 스캔하기

HttpSender

HttpSender는 Java에서 제공하는 HTTP Client입니다. 위에서 테스트해본 openUrlInBrowser와는 다르게 별도의 브라우저를 열지 않고 웹 요청을 발생시킬 수 있습니다.

var URI = Java.type("org.apache.commons.httpclient.URI");
var HttpSender = Java.type("org.parosproxy.paros.network.HttpSender");
var Model = Java.type("org.parosproxy.paros.model.Model");
var connectionParams = Model.getSingleton().getOptionsParam().getConnectionParam();

var requestUri = new URI("https://blahblah", false);
msg.getRequestHeader().setURI(requestUri);

var sender = new HttpSender(connectionParams, true, 6);
sender.sendAndReceive(msg);

Scan via API Server

var URI = Java.type("org.apache.commons.httpclient.URI");
var HttpSender = Java.type("org.parosproxy.paros.network.HttpSender");
var Model = Java.type("org.parosproxy.paros.model.Model");
var connectionParams = Model.getSingleton().getOptionsParam().getConnectionParam();

function invokeWith(msg) {
	var url = msg.getRequestHeader().getURI().toString();
	var apiUri = "https://{YOUR_API}/scan?target=" + url;
	var requestUri = new URI(apiUri, false);
	msg.getRequestHeader().setURI(requestUri);
	
	var sender = new HttpSender(connectionParams, true, 6);
	sender.sendAndReceive(msg);
}
GET /scan?target=https://www.hahwul.com HTTP/1.1