Nessus RESTful API - 实现POST的Java问题

时间:2017-06-21 12:18:09

标签: java rest curl post nessus

我目前的任务是为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请求中正确提交“数组”值?
  • 我如何看/调试/检查实际发送的内容/ POST的外观?
  • 如何修复我的脚本?

谢谢!

1 个答案:

答案 0 :(得分:0)

我终于修好了!

问题在于我作为有效负载发送的data-String的格式。它没有记录,但API仅适用于JSON-Requests。巧合的是,我的第一个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]