오늘은 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