Nessus RESTful API-实现POST的Java问题 [英] Nessus RESTful API - Java Problems implementing POST

查看:309
本文介绍了Nessus RESTful API-实现POST的Java问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前的任务是为Nessus进行自动化.

Im currently tasked to do automation for Nessus.

尽管几乎所有功能都正常,但与此调用有关的工作还是很困难(来自API-DOCU ):

While almost everything works fine, im biting on rock working with this call (from 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测试了呼叫,效果很好:

i've tested the call(s) with CURL, which works fine:

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"

...这将返回预期的结果:

...which gives back the intended result:

{"scan_uuid":"06c4aed8-ee64-c44e-9800-f6aeed1ba94fab8b2ed9c1033626"}

问题的核心所在:在Java中做同样的事情!

Now to the heart of the Problem: Doing the Same in 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方法看起来像这样(,并且可以与其他调用一起使用!):

my postRequest Method looks like this (and it works with other calls!):

/**
 * 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调用的方法都可以使用(创建会话和检索令牌,该方法可以使用相同的方法),但该方法却没有问题.

...now what i suspect is that the output postData: alt_targets=%27127.0.0.1%27&scan_id=21 isn't valid. Though i have no idea (and the internet gives astonishingly few informations) about what an "array" is in context of a POST request - and how it is encoded into a POST. In CURL it works perfectly - in Java it does not, despite the method being OK for other API-Calls (creating a sessions and retrieving the token works with the same method).

这是代码的调用部分:

/* 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也无济于事.

The API-Docu doesn't help much either, as you can see above.

问题:

  • 如何在POST请求中正确提交数组"值?
  • 我如何查看/调试/检查实际发送的内容/POST的外观?
  • 如何修复我的脚本?

谢谢!

推荐答案

我终于解决了它!

问题出在我作为有效载荷发送的数据字符串的格式上.它没有记录,但是API仅适用于JSON-Requests.巧合的是,我的第一个POST-Request(/session)是有效的JSON,而第二个(/scans/{id}/launch)不是.

The problem was with the format of the data-String that i sent as payload. It was not documented, but the API works with JSON-Requests only. Coincidentally my first POST-Request ( /session ) was valid JSON, while the second ( /scans/{id}/launch) wasn't.

因此,将有效的JSON作为POST数据有效载荷就可以了:

so doing valid JSON as POST data-payload did the trick:

    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"]}

...which results in a valid JSON POST data-payload: {"scan_id":"21", "alt_targets":["127.0.0.1"]}

...而不是旧版本:scan_id=21&alt_targets=[10.208.65.226]

...instead of the old one: scan_id=21&alt_targets=[10.208.65.226]

这篇关于Nessus RESTful API-实现POST的Java问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆