package com.acunetix; import com.google.common.base.Charsets; import net.sf.json.JSONArray; import net.sf.json.JSONNull; import net.sf.json.JSONObject; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.nio.file.Paths; import java.util.*; public class Engine { private String apiUrl; private String apiKey; private static final Map<String, String[]> threatCategory = new HashMap<>(); static { threatCategory.put("High", new String[]{"3"}); threatCategory.put("Medium", new String[]{"3", "2"}); threatCategory.put("Low", new String[]{"3", "2", "1"}); } public Engine(String apiUrl, String apiKey) { // System.setProperty("proxySet", "true"); // System.getProperty("proxySet"); this.apiUrl = apiUrl; this.apiKey = apiKey; } public static String getThreatName(String threat) { switch (threat) { case "3": return "High"; case "2": return "Medium"; case "1": return "Low"; } return null; } private static class Resp { int respCode; String respStr = null; JSONObject jso = null; } private HttpsURLConnection openConnection(String endpoint, String method) throws IOException { return openConnection(endpoint, method, "application/json; charset=UTF-8"); } private HttpsURLConnection openConnection(String endpoint) throws IOException { return openConnection(endpoint, "GET", "application/json; charset=UTF-8"); } private HttpsURLConnection openConnection(String endpoint, String method, String contentType) throws IOException { URL url = new URL(endpoint); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setRequestMethod(method); connection.setRequestProperty("Content-Type", contentType); connection.setRequestProperty("User-Agent", "Mozilla/5.0"); connection.addRequestProperty("X-AUTH", apiKey); return connection; } private Resp doGet(String urlStr) throws IOException { HttpsURLConnection connection = openConnection(urlStr); try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) { String inputLine; StringBuilder resbuf = new StringBuilder(); while ((inputLine = in.readLine()) != null) { resbuf.append(inputLine); } Resp resp = new Resp(); resp.respCode = connection.getResponseCode(); resp.jso = JSONObject.fromObject(resbuf.toString()); return resp; } } public String getUrl(String apiUrl, String downloadLink) throws MalformedURLException { URL url = new URL(apiUrl); if (downloadLink.matches("^(http|https)://.*$")) { return downloadLink; } else { return url.getProtocol() + "://" + url.getAuthority() + downloadLink; } } public int doTestConnection(String urlStr) throws IOException { HttpsURLConnection connection = openConnection(urlStr); return connection.getResponseCode(); } private Resp doPost(String urlStr) throws IOException { HttpsURLConnection connection = openConnection(urlStr,"POST"); connection.setUseCaches(false); connection.setDoInput(true); connection.setDoOutput(true); Resp resp = new Resp(); resp.respCode = connection.getResponseCode(); return resp; } private Resp doDelete(String urlStr) throws IOException { HttpsURLConnection connection = openConnection(urlStr,"DELETE"); connection.setUseCaches(false); connection.setDoInput(true); connection.setDoOutput(true); Resp resp = new Resp(); resp.respCode = connection.getResponseCode(); return resp; } private Resp doPostLoc(String urlStr, String urlParams) throws IOException, NullPointerException { HttpsURLConnection connection = openConnection(urlStr, "POST"); connection.setUseCaches(false); connection.setDoInput(true); connection.setDoOutput(true); try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { outputStream.writeBytes(urlParams); } String location = connection.getHeaderField("Location"); Resp resp = new Resp(); resp.respCode = connection.getResponseCode(); try { resp.respStr = location.substring(location.lastIndexOf("/") + 1); } catch (NullPointerException e){ e.printStackTrace(); throw new ConnectionException(); } return resp; } private JSONArray getObjects(String objectName) throws IOException, NullPointerException { JSONArray objects = null; JSONArray cursors; Resp resp = doGet(apiUrl + "/" + objectName); if (resp.respCode != 200) { throw new IOException(SR.getString("bad.response.0", resp.respCode)); } objects = resp.jso.getJSONArray(objectName); JSONObject pagination = resp.jso.getJSONObject("pagination"); if (pagination.containsKey("next_cursor")) { Integer cursor = 0; while ((cursor >= 100) || (cursor%100>0)) { resp = doGet(apiUrl + "/" + objectName + "?c=" + cursor); objects.addAll(resp.jso.getJSONArray(objectName)); pagination = resp.jso.getJSONObject("pagination"); if (pagination.getString("next_cursor").equals("null")) { break; } cursor = pagination.getInt("next_cursor"); } } else{ if (pagination.size() > 0) { cursors = pagination.getJSONArray("cursors"); String cursor; while (cursors.size() > 1) { cursor = cursors.getString(1); resp = doGet(apiUrl + "/" + objectName + "?c=" + cursor); objects.addAll(resp.jso.getJSONArray(objectName)); pagination = resp.jso.getJSONObject("pagination"); cursors = pagination.getJSONArray("cursors"); } } } // } return objects; } public JSONArray getTargets() throws IOException { return getObjects("targets"); } public String getTargetName(String targetId) throws IOException { JSONArray targets = getTargets(); for (int i = 0; i < targets.size(); i++) { JSONObject item = targets.getJSONObject(i); String target_id = item.getString("target_id"); if (target_id.equals(targetId)) { String address = item.getString("address"); String description = item.getString("description"); String target_name = address; if (description.length() > 0) { if (description.length() > 100) { description = description.substring(0, 100); } target_name += " (" + description + ")"; } return target_name; } } return null; } public JSONArray getScanningProfiles() throws IOException { return getObjects("scanning_profiles"); } public Boolean checkScanProfileExists(String profileId) throws IOException { JSONArray profiles = getScanningProfiles(); for (int i = 0; i < profiles.size(); i++) { JSONObject item = profiles.getJSONObject(i); String profile_id = item.getString("profile_id"); if (profile_id.equals(profileId)) { return true; } } return false; } public Boolean checkScanExist(String scanId) { try { JSONArray scans = getScans(); for (int i = 0; i < scans.size(); i++) { JSONObject item = scans.getJSONObject(i); String id = item.getString("scan_id"); if (id.equals(scanId)) { return true; } } } catch (IOException e){ e.printStackTrace(); } return false; } public String startScan(String scanningProfileId, String targetId, Boolean waitFinish) throws IOException { JSONObject jso = new JSONObject(); jso.put("target_id", targetId); jso.put("profile_id", scanningProfileId); jso.put("user_authorized_to_scan", "yes"); JSONObject jsoChild = new JSONObject(); jsoChild.put("disable", false); jsoChild.put("start_date", JSONNull.getInstance()); jsoChild.put("time_sensitive", false); jso.put("schedule", jsoChild); String scanId = doPostLoc(apiUrl + "/scans", jso.toString()).respStr; if (waitFinish) { while (!getScanStatus(scanId).equals("completed")) { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } return scanId; } public String createIncScan(String scanningProfileId, String targetId) throws IOException { JSONObject jso = new JSONObject(); jso.put("target_id", targetId); jso.put("profile_id", scanningProfileId); jso.put("user_authorized_to_scan", "yes"); jso.put("incremental", true); JSONObject jsoChild = new JSONObject(); jsoChild.put("disable", false); jsoChild.put("start_date", JSONNull.getInstance()); jsoChild.put("time_sensitive", false); jsoChild.put("triggerable", true); jso.put("schedule", jsoChild); String scanId = doPostLoc(apiUrl + "/scans", jso.toString()).respStr; return scanId; } public String triggerIncScan(String scanId, Boolean waitFinish) throws IOException { String resScanId = doPost(apiUrl + "/scans/" + scanId + "/trigger").respStr; if (waitFinish) { while (!getScanStatus(scanId).equals("completed")) { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } return resScanId; } public JSONArray getScans() throws IOException { return getObjects("scans"); } public String getScanThreat(String scanId) throws IOException { JSONObject jso = doGet(apiUrl + "/scans/" + scanId).jso; return jso.getJSONObject("current_session").getString("threat"); } public String getScanStatus(String scanId) throws IOException { JSONObject jso = doGet(apiUrl + "/scans/" + scanId).jso; return jso.getJSONObject("current_session").getString("status"); } public String getScanProfile(String scanId) throws IOException { JSONObject jso = doGet(apiUrl + "/scans/" + scanId).jso; return jso.getString("profile_id"); } public String getScanTarget(String scanId) throws IOException { JSONObject jso = doGet(apiUrl + "/scans/" + scanId).jso; return jso.getString("target_id"); } public void stopScan(String scanId) { try { Resp resp = doPost(apiUrl + "/scans/" + scanId + "/abort"); if (resp.respCode != 204) { throw new IOException(SR.getString("bad.response.0", resp.respCode)); } } catch (IOException e) { e.printStackTrace(); } } public void deleteScan(String scanId) { try { doDelete(apiUrl + "/scans/" + scanId); } catch (IOException e) { e.printStackTrace(); } } public JSONArray getReportTemplates() throws IOException { Resp resp = doGet(apiUrl + "/report_templates"); if (resp.respCode == 200) { return resp.jso.getJSONArray("templates"); } throw new IOException(SR.getString("bad.response.0", resp.respCode)); } public String getReportTemplateName(String reportTemplateId) throws IOException { JSONArray jsa = getReportTemplates(); for (int i = 0; i < jsa.size(); i++) { JSONObject item = jsa.getJSONObject(i); if (item.getString("template_id").equals(reportTemplateId)) { return item.getString("name"); } } return null; } private String getReportStatus(String reportId) throws IOException { JSONObject jso = doGet(apiUrl + "/reports/" + reportId).jso; return jso.getString("status"); } public void waitReportStatus(String reportId) throws IOException, InterruptedException { while (!getReportStatus(reportId).equals("completed")) { Thread.sleep(10000); } } public String generateReport(String sourceId, String reportTemplateId, String listType) throws IOException, InterruptedException { //returns download link of html report JSONObject jso = new JSONObject(); jso.put("template_id", reportTemplateId); JSONObject jsoChild = new JSONObject(); jsoChild.put("list_type", listType); List<String> id_list = new ArrayList<>(); id_list.add(sourceId); jsoChild.put("id_list", id_list); jso.put("source", jsoChild); String reportId = doPostLoc(apiUrl + "/reports", jso.toString()).respStr; waitReportStatus(reportId); String[] downloadLinkList = doGet(apiUrl + "/reports/" + reportId).jso.getString("download").split(","); String downloadLink = null; for (String item : downloadLinkList) { if (item.contains(".html")) { downloadLink = item.replaceAll("\"", "").replaceAll("\\[", "".replaceAll("]", "")); break; } } // download report return downloadLink; } public Boolean checkThreat(String checkThreat, String scanThreat) { //return true if the threat detected is equal or greater than threat set //checkthreat is the level set in plugin config and scanThreat from the scan result if (checkThreat.equals("DoNotFail")) { return false; } return Arrays.asList(threatCategory.get(checkThreat)).contains(scanThreat); } public Integer getVersion() throws IOException { if (apiUrl.matches(":\\d+")) { JSONObject jso = doGet(apiUrl + "/info").jso; return jso.getInt("major_version"); } else { return 13; } } public String doDownload(String urlSource, String savePath) throws IOException { URLConnection connection = new URL(urlSource).openConnection(); connection.addRequestProperty("User-Agent", "Mozilla"); try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) { // get the file name String cd = connection.getHeaderField("Content-Disposition"); String fileName = null; if (cd != null && cd.contains("=")) { fileName = "Acunetix_" + cd.split("=")[1].trim().replaceAll("\"", ""); } String filePath = Paths.get(savePath, fileName).toString(); String inputLine; try { try (FileOutputStream dfile = new FileOutputStream(filePath)) { while ((inputLine = in.readLine()) != null) { dfile.write(inputLine.getBytes(Charsets.UTF_8)); } } } catch (FileNotFoundException e) { e.printStackTrace(); } return fileName; } } } class ConnectionException extends RuntimeException { public ConnectionException() { super(SR.getString("cannot.connect.to.application")); } public ConnectionException(String message) { super(message); } }