curl Nessus RESTful API -实现POST的Java问题

eyh26e7m  于 2023-11-19  发布在  Java
关注(0)|答案(1)|浏览(127)

我目前的任务是为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调用是OK的(创建会话和检索令牌使用相同的方法工作)。
下面是代码的调用部分:

/* 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的外观?
  • 如何修改我的脚本?

谢谢你,谢谢

okxuctiv

okxuctiv1#

我终于修好了!
问题出在我作为payload发送的data-String的格式上。它没有文档记录,但API只适用于JSON请求。巧合的是,我的第一个POST请求(/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]

相关问题