我目前的任务是为Nessus进行自动化。
虽然几乎所有事情都很好,但我在使用此调用(来自 API-DOCU)时咬在岩石上:
Request
HTTP Request
POST /scans/{scan_id}/launch
Parameters
scan_id integer The id of the scan to launch.
alt_targets array If specified, these targets will be scanned instead of the default. Value can be an array where each index is a target, or an array with a single index of comma separated targets.
Response
Status Code Description
200 Returned if the scan was successfully launched.
403 Returned if the scan is disabled.
404 Returned if the scan does not exist.
我已经用 CURL 测试了调用,它工作正常:
curl -X POST -H 'X-Cookie: token=db565871198eec7fd9569dd1e3ffb8b2a60f757329749bc5' -H 'Content-Type:application/json' --data '{"scan_id":"21", "alt_targets":[127.0.0.1]}' -k "https://nessusServer:8834/scans/21/launch"
。这给出了预期的结果:
{"scan_uuid":"06c4aed8-ee64-c44e-9800-f6aeed1ba94fab8b2ed9c1033626"}
现在进入问题的核心:在Java中做同样的事情!
我得到的是这样的:
java.io.IOException: Server returned HTTP response code: 400 for URL: https://nessusServer:8834/scans/21/launch
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1890)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1885)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1884)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1457)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at at.bachmann.se.security.NessusAPI.postRequest(NessusAPI.java:466)
我的 postRequest 方法看起来像这样(它适用于其他调用!
/**
* Sends a post Request
*
* @param urlPathAdditional
* .. the added part of the path (e.g. /scans/{scanID} )
* @param headers
* .. Map<String, String> the Request Properties
*
* @return Response ... Response-Clazz containing String and Code
* @throws UnsupportedEncodingException
*/
public Response postRequest(String urlPathAdditional, Map<String, String> headers) throws Exception {
System.out.println("postRequest()......");
StringJoiner sj = new StringJoiner("&");
for (Map.Entry<String, String> entry : headers.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
String postData = sj.toString();
System.out.println("postData: " + sj.toString());
URL obj;
HttpsURLConnection con = null;
try {
obj = new URL(apiUrl + urlPathAdditional);
con = (HttpsURLConnection) obj.openConnection();
TrustModifier.relaxHostChecking(con); // here's where the magic happens: SSL is overrated! :)
con.setRequestMethod("POST");
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException |IOException e1) {
e1.printStackTrace();
}
//con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Charset", "UTF-8");
//con.setRequestProperty("Content-Length", Integer.toString(postData.length()));
con.setRequestProperty("X-Cookie", "token=" + token);
con.setDoOutput(true);
int respCode = 0;
/* Send post request */
try {
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(postData);
wr.flush();
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
respCode = con.getResponseCode();
/* read response */
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return new Response(response.toString(), respCode);
}
。现在我怀疑的是输出postData: alt_targets=%27127.0.0.1%27&scan_id=21
无效。 虽然我不知道(互联网提供的信息少得惊人)关于 POST 请求上下文中的"数组"是什么 - 以及它是如何编码到 POST 中的。在 CURL 中它运行良好 - 在 Java 中它不能,尽管该方法可以用于其他 API 调用(创建会话和检索令牌使用相同的方法)。
这里是代码的调用部分:
/* at this point the server is ready */
/* so we need to get the ID of the scan-name we want to launch */
int scanId = getScanIdForName(terminalOrM1 + scanType);
/* Scanner is Ready for a new Scan! */
// 200 Returned if the scan was successfully launched.
// 403 Returned if the scan is disabled.
// 404 Returned if the scan does not exist.
String query = "scans/" + scanId + "/launch";
String targets = "'" + ip + "'"; // <= DOESN'T WORK
//String target = ip; // DOESN'T WORK EITHER -- so what does?
//String target = "[" + ip + "]"; // NO WORK
Map<String, String> headers = new HashMap<>();
headers.put("alt_targets", targets);
headers.put("scan_id", String.valueOf(scanId));
/* launch it! */
Response respLaunch = null;
try {
respLaunch = postRequest(query, headers);
} catch (Exception e) {
e.printStackTrace();
}
API-Docu也没有多大帮助,正如你在上面看到的。
问题:
- 如何在 POST 请求中正确提交"数组"值?
- 如何查看/调试/检查实际发送的内容/开机自检的外观?
- 如何修复我的脚本?
谢谢!
我终于修复了它!
问题在于我作为有效负载发送的数据字符串的格式。它没有记录,但 API 仅适用于 JSON 请求。巧合的是,我的第一个 POST-Request (/session ) 是有效的 JSON,而第二个 (/scans/{id}/launch) 不是。
因此,将有效的JSON作为POST数据有效负载可以解决问题:
String query = "scans/" + scanId + "/launch";
String launchJson = "{"scan_id":"" +String.valueOf(scanId) + "", "alt_targets":["" + ip +""]}";
/* launch it! */
Response respLaunch = null;
try {
respLaunch = postRequest(query, launchJson);
} catch (Exception e) {
e.printStackTrace();
}
。这将产生有效的 JSON POST 数据有效负载:{"scan_id":"21", "alt_targets":["127.0.0.1"]}
。而不是旧的:scan_id=21&alt_targets=[10.208.65.226]