awvs是一個漏洞掃描工具,具體的介紹不再贅述,大家可以參考官網。這款軟體安裝需要付費,API也需要付費才可以查看。不過所幸awvs提供了docker版本,可以看下面的安裝教程。然後根據經驗提供了java和python api常見的操作。
我們這裡使用docker鏡像。
docker pull secfa/docker-awvs
docker run -it -d -p 13443:3443 secfa/docker-awvs
在瀏覽器中訪問 連結
默認的用戶名和密碼如下所示,登陸之後,就可以進行操作了。
Username:admin@admin.com
password:Admin123
我們操作是需要進行認證的,所以第一步是獲取相應的API密鑰。
說明,awvs默認是需要證書的,我這裡為了簡單,就把https給忽略了,下同。
@RequestMapping(value = "/addTarget", method = RequestMethod.GET) public String addTargetForWVS(String target) { log.debug("target:{}", target); RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.add("X-Auth", apiKey); headers.add("Content-Type", "application/json;charset=UTF-8"); JSONObject jsonObject = new JSONObject(); jsonObject.put("address", target); jsonObject.put("description", "url"); jsonObject.put("criticality", "10"); HttpEntity<String> entity = new HttpEntity<String>(jsonObject.toString(), headers); String url = awvsUrl + "api/v1/targets"; try { SslUtils.ignoreSsl(); } catch (Exception e) { e.printStackTrace(); } ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class); log.debug("response:{}", response.getBody()); if (response.getStatusCodeValue() == 201) { JSONObject resJson = new JSONObject(response.getBody()); return resJson.getString("target_id"); } return "error " + response.getStatusCodeValue(); }
postman測試:
下面是python版本。
def addTarget(self, target_url): info = { "address": target_url, "description": '', 'criticality': "10" } info = json.dumps(info) ret = self.awvs.post(self.awvs_url + 'api/v1/targets', data=info, verify=False, headers=self.headers).text ret = json.loads(ret) return ret['target_id']
@RequestMapping(value = "/scanTarget", method = RequestMethod.GET) public String scanTargetForWVS(String targetID) { log.debug("target:{}", targetID); RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.add("X-Auth", apiKey); headers.add("Content-Type", "application/json;charset=UTF-8"); JSONObject jsonObject = new JSONObject(); jsonObject.put("target_id", targetID); jsonObject.put("profile_id", "11111111-1111-1111-1111-111111111111"); JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("disable", false); jsonObject1.put("start_date", JSONObject.NULL); jsonObject1.put("time_sensitive", false); jsonObject.put("schedule", jsonObject1); jsonObject.put("ui_session_id", "81ae275a0a97d1a09880801a533a0ff1"); HttpEntity<String> entity = new HttpEntity<String>(jsonObject.toString(), headers); String url = awvsUrl + "api/v1/scans"; try { SslUtils.ignoreSsl(); } catch (Exception e) { e.printStackTrace(); } ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class); log.debug("response:{}", response.getBody()); if (response.getStatusCodeValue() == 201) { return response.getBody(); } return "error " + response.getStatusCodeValue(); }
def scanTarget(self, target_id): info = '{"target_id":"xxxxxxxxxxxx","profile_id":"11111111-1111-1111-1111-111111111111","schedule":{"disable":false,"start_date":null,"time_sensitive":false},"ui_session_id":"81ae275a0a97d1a09880801a533a0ff1"}' info = info.replace('xxxxxxxxxxxx', target_id) self.awvs.post(self.awvs_url + '/api/v1/scans', data=info, verify=False, headers=self.headers).text
這一步不同於前兩步,較為繁瑣。我們首先需要根據targetID獲取scanID,然後獲取當前scanID的狀態,注意這一步需要不斷重試,如果已完成,則獲取下載地址,包含html格式和pdf格式,調用接口下載html和pdf格式的掃描結果。
@RequestMapping(value = "/reports", method = RequestMethod.GET) public String reportsForWVS(String targetID) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.add("X-Auth", apiKey); headers.add("Content-Type", "application/json;charset=UTF-8"); // 1. 獲取scanID String getScanIDURL = awvsUrl + "api/v1/scans"; //String url = awvsUrl + "api/v1/reports"; try { SslUtils.ignoreSsl(); } catch (Exception e) { e.printStackTrace(); } HttpEntity<String> entity = new HttpEntity<String>(headers); ResponseEntity<String> response = restTemplate.exchange(getScanIDURL, HttpMethod.GET, entity, String.class); String scanID = ""; String status = ""; if (response.getStatusCodeValue() == 200) { JSONObject scanIDJsonObject = new JSONObject(response.getBody()); JSONArray jsonArray = scanIDJsonObject.getJSONArray("scans"); for (int i = 0; i < jsonArray.length(); ++i) { JSONObject scanRes = jsonArray.getJSONObject(i); if (scanRes.getString("target_id").equals(targetID)) { scanID = scanRes.getString("scan_id"); break; } } // 2. 獲取當前的狀態 while (!status.equals("completed")) { String getScanStatusURL = awvsUrl + "api/v1/scans/" + scanID; response = restTemplate.exchange(getScanStatusURL, HttpMethod.GET, entity, String.class); if (response.getStatusCodeValue() == 200) { JSONObject jsonObject = new JSONObject(response.getBody()); status = jsonObject.getJSONObject("current_session").getString("status"); } else { return "error " + response.getStatusCodeValue(); } try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } // 3. 獲取下載地址 JSONObject dataReportJson = new JSONObject(); dataReportJson.put("template_id", "11111111-1111-1111-1111-111111111111"); JSONObject sourceJson = new JSONObject(); sourceJson.put("list_type", "scans"); sourceJson.put("id_list", new JSONArray().put(scanID)); dataReportJson.put("source", sourceJson); HttpEntity<String> postEntity = new HttpEntity<String>(dataReportJson.toString(), headers); String reportsURL = awvsUrl + "api/v1/reports"; response = restTemplate.exchange(reportsURL, HttpMethod.GET, postEntity, String.class); if (response.getStatusCodeValue() == 200) { // 4. 下載所需報告 JSONObject jsonObject = new JSONObject(response.getBody()); String download = jsonObject.getJSONArray("reports").getJSONObject(0).getJSONArray("download").getString(0); String reportsDownloadURL = awvsUrl + download; log.info("reportsDownloadURL: ", reportsDownloadURL); response = restTemplate.exchange(reportsDownloadURL, HttpMethod.GET, entity, String.class); if (response.getStatusCodeValue() == 200) { return response.getBody(); } else { return "error " + response.getStatusCodeValue(); } } else { return "error " + response.getStatusCodeValue(); } } return "error " + response.getStatusCodeValue(); }
其他的,大家可以參考下面的,不再贅述。