6
AUTOMATING NEXPOSE

image

Nexpose is a vulnerability scanner similar to Nessus but geared toward enterprise-level vulnerability management. This means not only helping system admins find which boxes need patches, but also helping them mitigate and prioritize the potential vulnerabilities over time. In this chapter, I show you how to use C# to automate Rapid7’s Nexpose vulnerability scanner in order to create a Nexpose site, scan that site, create a PDF report of the site’s vulnerabilities, and then delete the site. Nexpose’s reporting is incredibly flexible and powerful, allowing you to automatically generate reports for a wide variety of audiences, from executives to technical admins.

Like the Nessus scanner discussed in Chapter 5, Nexpose uses the HTTP protocol to expose its API, but it uses XML instead of JSON to format data. As in Chapter 5, we’ll write two separate classes: one to communicate with the Nexpose API (the session class) and another to drive the API (the manager class). Once we’ve written the classes, you’ll learn how to run a scan and view the results.

Installing Nexpose

Nexpose is available in various forms and editions from Rapid7. We’ll use the Nexpose binary installer from Rapid7 on a fresh Ubuntu 14.04 LTS machine using the commands and URL shown in Listing 6-1. This URL is updated with the latest installer whenever new versions are released. If the URL doesn’t work for whatever reason, you can also find a download link after registering for a Community activation key (required to run Nexpose). After downloading the installer, we need to set the executable file permission so we can subsequently run the installer as root.

$ wget http://download2.rapid7.com/download/NeXpose-v4/NeXposeSetup-Linux64.bin
$ chmod +x ./NeXposeSetup-Linux64.bin
$ sudo ./NeXposeSetup-Linux64.bin

Listing 6-1: Downloading and installing Nexpose

When the installer is run in a graphical desktop environment, such as KDE or GNOME, a graphical installer is presented for the user to step through for the initial configuration, as shown in Figure 6-1. If you are installing Nexpose through a text-based environment, such as SSH, the installer should step through configuration with yes/no questions and other prompts for information.

image

Figure 6-1: The graphical Nexpose installer

Once Nexpose is installed, run ifconfig in a terminal to see the IP address open in the web browser. Then enter https://ip:3780/ into the browser, replacing ip with the IP address of the machine running Nexpose. You should see the Nexpose login page, as shown in Figure 6-2.

image

Figure 6-2: The Nexpose login page

Use the credentials asked for during setup. You may see an SSL certificate error before being presented with the login page. Because Nexpose uses a self-signed SSL certificate by default, your browser probably doesn’t trust it and may complain. This is normal and expected.

Activation and Testing

When you first log in, you should be prompted to enter the activation key you were sent in an email from Rapid7 after registering for the Community Edition, as shown in Figure 6-3.

image

Figure 6-3: The activation modal pop-up in Nexpose

Now test your installation to make sure you have activated the software correctly and can authenticate with the Nexpose API by sending an HTTP request. You can use the curl utility to make an authentication request to the API and display the response, as shown in Listing 6-2.

$ curl -d '<LoginRequest user-id="nxadmin" password="nxpassword"/>' -X POST -k
  -H "Content-Type: text/xml" https://192.168.1.197:3780/api/1.1/xml
<LoginResponse success="1" session-id="D45FFD388D8520F5FE18CACAA66BE527C1AF5888"/>
$

Listing 6-2: Successfully authenticating with the Nexpose API using curl

If you see a response containing success="1" and a session ID, Nexpose has been correctly activated, and the API is functioning as expected with your credentials.

Some Nexpose Parlance

Before we discuss managing and reporting on vulnerability scans in Nexpose any further, we need to define a couple of terms. When you start a vulnerability scan in Nexpose, you scan a site, which is a collection of related hosts or assets.

Nexpose has two types of sites: static sites and dynamic sites. We will focus on the former during our automation. A static site holds a list of hosts you can only change by reconfiguring the site. This is why it is called static—the site won’t change over time. Nexpose also supports creating sites based on asset filters, so the assets in a dynamic site may change from one week to another based on their vulnerability count or inability to authenticate. Dynamic sites are more complex, but they are much more powerful than static sites and are a great feature to familiarize yourself with as extra homework.

The assets that make up the sites are simply connected devices on your network that Nexpose can communicate with. These assets can be bare-metal data center rack servers, VMware ESXi hosts, or Amazon AWS instances. If you can ping it with an IP address, it can be an asset in your Nexpose site. Many times, it is beneficial to separate the hosts on your physical network into logical sites in Nexpose so you can more granularly scan and manage vulnerabilities. A sophisticated enterprise network may have a site specifically for ESXi hosts, a site for the C-level executive network segment, and a site for the customer service call center assets.

The NexposeSession Class

We’ll begin by writing the NexposeSession class to communicate with the Nexpose API, as shown in Listing 6-3.

public class NexposeSession : IDisposable
{
  public NexposeSession(string username, string password, string host,
    int port = 3780, NexposeAPIVersion version = NexposeAPIVersion.v11)
  {
    this.Host = host;
    this.Port = port;
    this.APIVersion = version;

    ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;

    this.Authenticate(username, password);
  }

  public string Host { get; set; }
  public int Port { get; set; }
  public bool IsAuthenticated { get; set; }
  public string SessionID { get; set; }
  public NexposeAPIVersion APIVersion { get; set; }

Listing 6-3: The beginning of the NexposeSession class with constructor and properties

The NexposeSession class constructor takes up to five arguments: three are required (username, password, and the host to connect to), and two are optional (the port and API version, with defaults of 3780 and NexposeAPIVersion.v11 , respectively). Beginning at , we assign the properties Host, Port, and APIVersion to the three required arguments. Next, we disable SSL certificate verification at by setting ServerCertificateValidationCallback to always return true. Doing so violates good security principles, but we disable verification because Nexpose runs on HTTPS with a self-signed certificate by default. (Otherwise, SSL certificate verification would fail during the HTTP request.)

At , we attempt to authenticate by calling the Authenticate() method, shown expanded in Listing 6-4.

public XDocument Authenticate(string username, string password)
{
  XDocument cmd = new XDocument(
    new XElement("LoginRequest",
      new XAttribute("user-id", username),
      new XAttribute("password", password)));

  XDocument doc = (XDocument)this.ExecuteCommand(cmd);

 if (doc.Root.Attribute("success").Value == "1")
  {
  this.SessionID = doc.Root.Attribute("session-id").Value;
   this.IsAuthenticated = true;
  }
  else
    throw new Exception("Authentication failed");

 return doc;
}

Listing 6-4: The NexposeSession class’s Authenticate() method

The Authenticate() method takes as arguments a username and a password. To send the username and password to the API for authentication, we create an XDocument at with root node LoginRequest and user-id and password attributes. We pass the XDocument to the ExecuteCommand() method and then store the result returned by the Nexpose server.

At , we determine whether Nexpose’s XML response has a success attribute value of 1. If so, at we assign the SessionID property to the session-id in the response and set IsAuthenticated to true. Finally, we return the XML response .

The ExecuteCommand() Method

The ExecuteCommand() method shown in Listing 6-5 is the real meat of the NexposeSession class.

public object ExecuteCommand(XDocument commandXml)
{
  string uri = string.Empty;
  switch (this.APIVersion)
  {
  case NexposeAPIVersion.v11:
    uri = "/api/1.1/xml";
    break;
  case NexposeAPIVersion.v12:
    uri = "/api/1.2/xml";
    break;
  default:
    throw new Exception("Unknown API version.");
  }

Listing 6-5: The beginning of the NexposeSession class’s ExecuteCommand() method

Before we can send data to Nexpose, we need to know which version of the API to use, so at we use a switch/case block (similar to a series of if statements) to test the value of the APIVersion. A value of NexposeAPIVersion.v11 or NexposeAPIVersion.v12, for example, would tell us that we need to use the API URI for version 1.1 or 1.2.

Making the HTTP Request to the Nexpose API

Having determined the URI to make the API request to, we can now send the XML request data to Nexpose, as shown in Listing 6-6.

  byte[] byteArray = Encoding.ASCII.GetBytes(commandXml.ToString());
HttpWebRequest request = WebRequest.Create("https://" + this.Host
          + ":" + this.Port.ToString() + uri) as HttpWebRequest;
  request.Method = "POST";
  request.ContentType = "text/xml";
  request.ContentLength = byteArray.Length;
using (Stream dataStream = request.GetRequestStream())
  dataStream.Write(byteArray, 0, byteArray.Length);

Listing 6-6: Sending the XML command over HTTP for Nexpose inside ExecuteCommand()

Talking to the HTTP API for Nexpose happens in two parts. First, Nexpose makes the API request with the XML that will tell Nexpose what command we are running; then it reads the response with the results of the API request. To make the actual HTTP request to the Nexpose API, we create an HttpWebRequest and assign its Method property to POST , its ContentType property to text/xml , and the ContentLength property to the length of our XML. Next, we write the API XML command bytes to the HTTP request stream and send the stream to Nexpose with Write() . Nexpose will parse the XML, determine what to do, and then return the results in the response.

Reading the HTTP Response from the Nexpose API

Next, we need to read the HTTP response from the API request we just made. Listing 6-8 shows how we finish the ExecuteCommand() method by reading the HTTP response from Nexpose and then returning either an XDocument or an array of raw bytes, depending on the HTTP response content type. With Listing 6-8 finishing the ExecuteCommand() method, we will be able to make an API request and then return the correct response data, depending on the response content type.

  string response = string.Empty;
  using (HttpWebResponse r = request.GetResponse() as HttpWebResponse)
  {
    using (StreamReader reader = new StreamReader(r.GetResponseStream()))
      response = reader.ReadToEnd();

    if (r.ContentType.Contains("multipart/mixed"))
    {
      string[] splitResponse = response
          .Split(new string[] {"--AxB9sl3299asdjvbA"}, StringSplitOptions.None);

      splitResponse = splitResponse[2]
          .Split(new string[] { " " }, StringSplitOptions.None);

      string base64Data = splitResponse[1];

      return Convert.FromBase64String(base64Data);
    }
  }
  return XDocument.Parse(response);
}

Listing 6-8: The last part of the NexposeSession class’s ExecuteCommand() method

Usually, when you send an XML command to Nexpose, you get XML in return. But when you request a vulnerability scan report, such as the PDF report we will request after performing a vulnerability scan, you get the HTTP response multipart/mixed rather than application/xml. Exactly why Nexpose changes the HTTP response based on PDF reports is not clear, but because our request may return a response with either a Base64-encoded report or an XDocument (the XML document class we first used in Chapter 3), we need to be able to handle both types of responses.

In order to begin reading the HTTP response from Nexpose, we call GetResponse() so that we can read the HTTP response stream; then we create a StreamReader to read the response data into a string and check its content type. If the response type is multipart/mixed , we break the response into an array of strings so that we can parse the report data by leveraging the fact that Nexpose multipart/mixed responses always use the string --AxB9sl3299asdjvbA to separate the HTTP parameters in the HTTP response.

After the HTTP response is split, the third element in the resulting string array will always contain the Base64-encoded report data from the scan. At , we use two newline sequences ( ) to separate out this report data. Now we can reference only the Base64-encoded data, but first we must remove some invalid data from the end of the Base64-encoded report. Finally, we pass the Base64-encoded data to Convert.FromBase64String() , which returns a byte array of the Base64-decoded data that can then be written to the filesystem as our final PDF report to read later.

Logging Out and Disposing of Our Session

Listing 6-9 shows the Logout() and Dispose() methods, which will make it easy for us to log out of our session and clean up any session data.

public XDocument Logout()
{
  XDocument cmd = new XDocument(
    new XElement("LogoutRequest",
      new XAttribute("session-id", this.SessionID)));

  XDocument doc = (XDocument)this.ExecuteCommand(cmd);
  this.IsAuthenticated = false;
  this.SessionID = string.Empty;

  return doc;
}

public void Dispose()
{
  if (this.IsAuthenticated)
    this.Logout();
}

Listing 6-9: The NexposeSession class’s Dispose() and Logout() methods

In Logout() , we build an XDocument with the root node LogoutRequest and the attribute session-id . When we send this information to Nexpose as XML, it will attempt to invalidate the session ID token, effectively logging us out. At the same time, we set IsAuthenticated to false and SessionID to string.Empty to clean up the old authentication information; then we return the logout response XML.

We’ll use the Dispose() method (required by the IDisposable interface) to clean up our Nexpose session. As you can see at , we check whether we are authenticated and, if so, call Logout() to invalidate our session.

Finding the API Version

Listing 6-10 shows how we’ll use NexposeAPIVersion to determine which Nexpose API version to use.

public enum NexposeAPIVersion
{
  v11,
  v12
}

Listing 6-10: The NexposeAPIVersion enum used in the NexposeSession class

The code enum NexposeAPIVersion gives us an easy way to determine which API URI to make HTTP requests to. We used NexposeAPIVersion in Listing 6-5 to do exactly this when building the API URI in ExecuteCommand().

Driving the Nexpose API

Listing 6-11 shows how we can now use NexposeSession to communicate with the Nexpose API and authenticate and print the SessionID. This is a good test to ensure the code we have written so far is working as expected.

class MainClass
{
  public static void Main(string[] args)
  {
    using (NexposeSession session = new NexposeSession("admin", "adm1n!", "192.168.2.171"))
    {
      Console.WriteLine(session.SessionID);
    }
  }
}

Listing 6-11: Using NexposeSession to authenticate with the Nexpose API and print SessionID

At , we attempt to authenticate by passing the username, password, and IP address of the Nexpose server to a new NexposeSession. If authentication succeeds, we display the SessionID assigned to the session onscreen. If authentication fails, we throw an exception with the message “Authentication failed.”

The NexposeManager Class

The NexposeManager class shown in Listing 6-12 allows us to create, monitor, and report on the result of our scans. We begin with a simple API call.

public class NexposeManager : IDisposable
{
  private readonly NexposeSession _session;
  public NexposeManager(NexposeSession session)
  {
    if (!session.IsAuthenticated)
      throw new ArgumentException("Trying to create manager from "
      + "unauthenticated session. Please authenticate.", "session");

    _session = session;
  }

  public XDocument GetSystemInformation()
  {
    XDocument xml = new XDocument(
      new XElement("SystemInformationRequest",
        new XAttribute("session-id", _session.SessionID)));

  return (XDocument)_session.ExecuteCommand(xml);
  }
  public void Dispose()
  {
    _session.Logout();
  }
}

Listing 6-12: The NexposeManager class with a GetSystemInformation() method

Because NexposeManager implements IDisposable , we write a Dispose() method by declaring the _session to hold the NexposeSession class that NexposeManager will consume, and we pass in NexposeSession as the only argument. If the Nexpose session authenticates , we assign _session to the session. If not, we throw an exception .

To test the manager class initially, we’ll implement a short and simple API method for retrieving some general system information about the Nexpose console. The GetSystemInformation() method makes a simple SystemInformationRequest API request and then returns the response .

In order to print the Nexpose system information (including versioning information, such as the PostgreSQL and Java versions in use, and hardware information, such as the CPU count and RAM available), we add NexposeManager to our Main() method from Listing 6-11, as shown in Listing 6-13.

public static void Main(string[] args)
{
  using (NexposeSession session = new NexposeSession("admin", "Passw0rd!", "192.168.2.171"))
  {
    using (NexposeManager manager = new NexposeManager(session))
    {
      Console.WriteLine(manager.GetSystemInformation().ToString());
    }
  }
}

Listing 6-13: Using the NexposeManager class in the Main() method

We pass our NexposeSession class into the NexposeManager constructor and then call GetSystemInformation() to print the system information, as shown in Figure 6-4.

image

Figure 6-4: Getting the Nexpose system information via the API

Automating a Vulnerability Scan

In this section, we finally look at how to automate a vulnerability scan with Nexpose. We create a Nexpose site, scan the site, and then download a report of the findings. We’ll only scratch the surface of Nexpose’s powerful scanning features.

Creating a Site with Assets

Before launching a scan with Nexpose, we need to create a site to be scanned. Listing 6-14 shows how we can build the XML API request for creating a site in the CreateOrUpdateSite() method.

public XDocument CreateOrUpdateSite(string name, string[] hostnames = null,
      string[][] ips = null, int siteID = -1)
{
  XElement hosts = new XElement("Hosts");
  if (hostnames != null)
  {
    foreach (string host in hostnames)
      hosts.Add(new XElement("host", host));
  }

  if (ips != null)
  {
    foreach (string[] range in ips)
    {
      hosts.Add(new XElement ("range",
        new XAttribute("from", range[0]),
        new XAttribute("to", range[1])));
    }
  }

  XDocument xml = new XDocument(
    new XElement("SiteSaveRequest",
      new XAttribute("session-id", _session.SessionID),
      new XElement("Site",
        new XAttribute("id", siteID),
        new XAttribute("name", name),
      hosts,
        new XElement("ScanConfig",
          new XAttribute("name", "Full audit"),
          new XAttribute("templateID", "full-audit")))));

  return (XDocument)_session.ExecuteCommand(xml);
}

Listing 6-14: The CreateOrUpdateSite() method in the NexposeManager class

The CreateOrUpdateSite() method takes up to four arguments: the human-readable site name, any hostnames and IP ranges, and the site ID. Passing -1 as the site ID, as shown here, creates a new site. At , we create an XML element called Hosts, and if there is a hostnames argument that is not null , we add it to Hosts. We do the same for any IP ranges passed as arguments.

Next, we create an XDocument with the root XML node SiteSaveRequest and a session-id attribute to tell the Nexpose server that we’re authenticated and can make this API call. Inside the root node, we create an XElement called Site to hold specific information for the new site and scan configuration details, such as the hosts to scan and the scan template ID . At , we pass SiteSaveRequest to ExecuteCommand() and cast the object that ExecuteCommand() returns to an XDocument.

Starting a Scan

Listing 6-15 shows how to begin the site scan and get its status with the ScanSite() and GetScanStatus() methods. Hopefully you’re beginning to see how easy it can be to implement new API functionality in the Manager class when the NexposeSession class does all the communication and all you have to do is set up the API request XML.

public XDocument ScanSite(int siteID)
{
  XDocument xml = new XDocument(
    new XElement("SiteScanRequest",
      new XAttribute("session-id", _session.SessionID),
      new XAttribute("site-id", siteID)));
  return (XDocument)_session.ExecuteCommand(xml);
}

public XDocument GetScanStatus(int scanID)
{
  XDocument xml = new XDocument(
    new XElement("ScanStatusRequest",
      new XAttribute("session-id", _session.SessionID),
      new XAttribute("scan-id", scanID)));

  return (XDocument)_session.ExecuteCommand (xml);
}

Listing 6-15: The ScanSite() and GetScanStatus() methods in the NexposeManager class

The ScanSite() method takes the siteID as an argument to scan. We create an XDocument with root node SiteScanRequest and then add to it the session-id and site-id attributes. Next, we send the SiteScanRequest XML to the Nexpose server and return the response.

The GetScanStatus() method accepts one argument, the scan ID to check, which is returned by the ScanSite() method. After creating a new XDocument with root node ScanStatusRequest and adding the session-id and scan-id attributes, we send the resulting XDocument to the Nexpose server and return the response to the caller.

Creating a PDF Site Report and Deleting the Site

Listing 6-16 shows how we create the scan report and delete the site using the API in the GetPdfSiteReport() and DeleteSite() methods.

public byte[] GetPdfSiteReport(int siteID)
{
  XDocument doc = new XDocument(
    new XElement("ReportAdhocGenerateRequest",
      new XAttribute("session-id", _session.SessionID),
      new XElement("AdhocReportConfig",
        new XAttribute("template-id", "audit-report"),
        new XAttribute("format", "pdf"),
        new XElement("Filters",
          new XElement("filter",
            new XAttribute("type", "site"),
            new XAttribute("id", siteID))))));

  return (byte[])_session.ExecuteCommand(doc);
}

public XDocument DeleteSite(int siteID)
{
  XDocument xml = new XDocument(
    new XElement("SiteDeleteRequest",
      new XAttribute("session-id", _session.SessionID),
      new XAttribute("site-id", siteID)));
  return (XDocument)_session.ExecuteCommand(xml);
}

Listing 6-16: The GetPdfSiteReport() and DeleteSite() methods in the NexposeManager class

Both methods take only one argument, the site ID. To generate a PDF report, we use ReportAdHocGenerateRequest and specify pdf and the siteID . We cast the object returned by ExecuteCommand() to a byte array instead of an XDocument because Nexpose will return a multipart/mixed HTTP response for a ReportAdHocGenerateRequest. We return the raw bytes of the PDF report to be written to the calling method.

We use DeleteSite() to delete the site and create a SiteDeleteRequest XDocument and then make the API call and return the results .

Putting It All Together

Now that you know how to drive Nexpose programmatically, let’s create a new Nexpose site, scan it, create a PDF report of its vulnerabilities, and delete the site. Listing 6-17 begins this process by creating a new site and retrieving its ID with our two new classes.

public static void Main(string[] args)
{
  using (NexposeSession session = new NexposeSession("admin", "adm1n!", "192.168.2.171"))
{
  using (NexposeManager manager = new NexposeManager(session))
  {
    string[][] ips =
    {
      new string[] { "192.168.2.169", string.Empty }
    };

    XDocument site = manager.CreateOrUpdateSite(Guid.NewGuid().ToString(), null, ips);

    int siteID = int.Parse(site.Root.Attribute("site-id").Value);

Listing 6-17: Creating the temporary site and retrieving the site ID

After creating the NexposeSession and NexposeManager objects, we pass in the list of IP addresses to scan as a string , with a starting and ending address. To scan a single IP, use an empty string as the second element, as shown at . We pass the list of target IPs to CreateOrUpdateSite() along with a Guid as the name of the temporary site. (We simply need a unique string for the site name.) When we receive the HTTP response from Nexpose for creating the temporary site, we grab the site ID from the XML and store it.

Starting the Scan

Listing 6-18 shows how we run and monitor the vulnerability scan by basically sitting in a while loop and sleeping until the scan is finished.

   XDocument scan = manager.ScanSite(siteID);
   XElement ele = scan.XPathSelectElement("//SiteScanResponse/Scan");

   int scanID = int.Parse(ele.Attribute("scan-id").Value);
   XDocument status = manager.GetScanStatus(scanID);

   while (status.Root.Attribute("status").Value != "finished")
   {
     Thread.Sleep(1000);
     status = manager.GetScanStatus(scanID);
     Console.WriteLine(DateTime.Now.ToLongTimeString()+": "+status.ToString());
   }

Listing 6-18: Starting and monitoring the Nexpose scan

We begin the scan by passing the site ID to ScanSite() and then grab the scan ID from the response and pass it to GetScanStatus() . Next, in a while loop, we sleep for a few seconds, as long as the scan status is not finished . Then we check the scan status again and display a status message to the user with WriteLine() .

Generating a Report and Deleting the Site

Once the scan finishes, we can generate a report and delete the site, as shown in listing 6-19.

      byte[] report = manager.GetPdfSiteReport(siteID);
      string outdir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
      string outpath = Path.Combine(outdir, siteID + ".pdf");
      File.WriteAllBytes(outpath, report);

      manager.DeleteSite(siteID);
    }
  }
}

Listing 6-19: Retrieving the Nexpose site report, writing it to the filesystem, and then deleting the site

To generate a report, we pass the site ID to GetPdfSiteReport() , which returns an array of bytes. Then we use WriteAllBytes() to save the PDF report to the user’s Desktop directory with the site’s ID as the filename and a .pdf extension. Then we delete the site with DeleteSite() .

Running the Automation

Listing 6-20 shows how to run a scan and view its report.

C:UsersexampleDocumentsch6inDebug>.6_automating_nexpose.exe
11:42:24 PM: <ScanStatusResponse success="1" scan-id="4" engine-id="3" status="running" />
–-snip--
11:47:01 PM: <ScanStatusResponse success="1" scan-id="4" engine-id="3" status="running" />
11:47:08 PM: <ScanStatusResponse success="1" scan-id="4" engine-id="3" status="integrating" />
11:47:15 PM: <ScanStatusResponse success="1" scan-id="4" engine-id="3" status="finished" />

C:UsersexampleDocumentsch6inDebug>dir UsersexampleDesktop*.pdf
 Volume in drive C is Acer
 Volume Serial Number is 5619-09A2

 Directory of C:UsersexampleDesktop

07/30/2017  11:47 PM           103,174 4.pdf
09/09/2015  09:52 PM        17,152,368 Automate the Boring Stuff with Python.pdf
               2 File(s)     17,255,542 bytes
               0 Dir(s)  362,552,098,816 bytes free

C:UsersexampleDocumentsch6inDebug>

Listing 6-20: Running the scan and writing the report to the user’s Desktop

Notice in the output of Listing 6-20 that Nexpose is returning at least three scan statuses, which are separate phases of the scan: running , integrating , and finished . Once the scan finishes, our PDF report is written to the user’s Desktop , as expected. You can open this new report with your favorite PDF reader and see what kind of vulnerabilities Nexpose may have found.

Conclusion

In this chapter, you learned how to drive the vulnerability scanner Nexpose to report on vulnerabilities for a given host on a network. You also learned how Nexpose stores information about computers on the network, such as sites and assets. You built a few classes to drive Nexpose programmatically using the base C# libraries, and you learned how to use NexposeSession to authenticate with Nexpose and send and receive XML to the Nexpose API. You also saw how the NexposeManager class wraps functionality in the API, including the ability to create and delete sites. Finally, you were able to drive Nexpose to scan a network asset and then create a nice-looking PDF report displaying the results.

Nexpose has capabilities far beyond simple vulnerability management. Expanding your library to cover this advanced functionality should be relatively straightforward and is an excellent way to familiarize yourself with the other powerful features Nexpose provides, such as custom scan policies, authenticated vulnerability scans, and more customizable reporting. An advanced, modern, mature enterprise network requires granular system controls that allow an organization to integrate security into business workflows. Nexpose brings all of this to the table and is a powerful tool to have in your arsenal as an IT manager or system admin.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset