Error Querying API Information Using the Rapid7Nexpose PowerShell Module

I’ve managed to connect to our InsightVM instance, however, I am unable to query anything due to the following error. I am using the PowerShell module that is posted here: https://github.com/My-Random-Thoughts/Rapid7Nexpose. Any ideas as to why I’m getting the error below? My PowerShell version is 5.1.18362.1171 and I’m on Win10 1909 Enterprise. Thank you!

Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list…
You cannot call a method on a null-valued expression.
At line:183 char:13

  •         Throw "`n$errMsg1`n$errMsg2`n$errMsg3"
    
  •         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : OperationStopped: (
      Error formatti…ued expression.:String) [], RuntimeException
    • FullyQualifiedErrorId :
      Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
      .
      You cannot call a method on a null-valued expression.

Not sure what method you are calling, but my knowledge of just directly hitting the InsightVM API from PowerShell there are arrays of filters used. This error tells me that the author is trying to split a string into one of these arrays. Can you provide your PowerShell sting that calls this (desensitized if necessary) knowing your arguments and what cmdlet is being called will aid in troubleshooting

Here is an example of a Asset Search:

$Search = [pscustomobject]@{
match = 'all'
  filters = @(
     [pscustomobject]@{
        field = 'risk-score'
        operator = 'is-greater-than'
        value = 5000
     },
     [pscustomobject]@{
        field = 'operating-system'
        operator = 'contains'
        value = 'windows'
     },
     [pscustomobject]@{
        field = 'service-name'
        operator = 'contains'
        value = 'ssh'
     }
  )
}
$Results = Invoke-RestMethod -Uri "$Rapid7BaseUrl/assets/search?size=500" -Body $($Search | ConvertTo-Json) -Method Post -ContentType 'Application/JSON' -Headers $Rapid7Headers
2 Likes

Sure! I’m using the Get-NexposeAsset function. Also, according to the directions on Github page, one example was calling Get-NexposeSite. I ran this in Verbose mode. That is supposed to return all sites, however, it returns the same error:

       **VERBOSE: Executing API method "GET" against "/api/3/sites?size=100"**
    Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list..
    You cannot call a method on a null-valued expression.
    At line:183 char:13
    +             Throw "`n$errMsg1`n$errMsg2`n$errMsg3"
    +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : OperationStopped: (
    Error formatti...ued expression.:String) [], RuntimeException
        + FullyQualifiedErrorId : 
        Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list. 
       .
    You cannot call a method on a null-valued expression.
1 Like

The author has a bug in the error handling section of the code.
I’d post a message on the Github page addressing this.
This error is masking what you actual error is.
Starting on line 172 of master/private/Invoke-NexposeQuery.ps1

Catch {
    $errMsg1 = $_.Exception.Message
    Try {
        $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
        $reader.BaseStream.Position = 0
        $reader.DiscardBufferedData()
        $errMsg2 = $reader.ReadToEnd()
    }
    Catch {
        $errMsg3 = $_.Exception.Message
    }
    Throw "`n$errMsg1`n$errMsg2`n$errMsg3"
}

Also, a simple version of this to check if your credentials, server, and port are correct:

$Rapid7_User = ''
$Rapid7_Password = ''
$Rapid7_Server = ''
$Rapid7_Port = '3780'
$Rapid7_BaseUrl = "https://$($Rapid7_Server):$($Rapid7_Port)/api/3"
$Rapid7_Headers = @{Authorization = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($Rapid7_User):$($Rapid7_Password)")))"}

(Invoke-RestMethod -Uri "$Rapid7_BaseUrl/sites?size=100" -Headers $Rapid7_Headers).resources
1 Like

Thank you, @brandon_mcclure. I’ll let the author know. I’m really just trying to look into automating a way to import {Last Logged On Users} as an {Owner} tag in InsightVM if there is a way to do that. Possibly even {Location} based on IP scope-lookup in DHCP. That one might be trickier though.

According to that cred checker script, my creds work just fine. I have to omit the port in my code because everything goes through our load balancer. The LB proxies everything and masks the port, so if you attempt to connect using the DNS name and port, it throws an error. I fixed this is some of the code within the Library, and got it to work. Below is an example of what returns after using the cred check you provided (making sure I desensitized the output and using Verbose):

VERBOSE: GET https://DNSNAME/api/3/sites?size=100 with 0-byte payload
VERBOSE: received -1-byte response of content type application/json;charset=UTF-8


assets          : 0
description     : Monthly Discovery Scan for the BYOD networks
id              : 84
importance      : normal
links           : {@{href=https://DNSNAME/api/3/sites/84; rel=self}, @{href=https://DNSNAME/api/3/sites/84/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/84/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/84/scan_schedules; rel=Schedules}...}
name            : BYOD Wireless Discovery Scan
riskScore       : 0.0
scanEngine      : 12
scanTemplate    : discovery
type            : static
vulnerabilities : @{critical=0; moderate=0; severe=0; total=0}

assets          : 10913
id              : 66
importance      : normal
lastScanTime    : 2021-02-19T06:44:51.949Z
links           : {@{href=https://DNSNAME/api/3/sites/66; rel=self}, @{href=https://DNSNAME/api/3/sites/66/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/66/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/66/scan_schedules; rel=Schedules}...}
name            : Discovery Site
riskScore       : 182934384
scanEngine      : 12
scanTemplate    : discovery
type            : static
vulnerabilities : @{critical=125644; moderate=31318; severe=435232; total=592194}

assets          : 4
description     : This will scan R7-Scan1-R7-Scan4 for any vulns using the local scanner built into InsightVM.
id              : 75
importance      : normal
lastScanTime    : 2021-02-17T21:09:23.333Z
links           : {@{href=https://DNSNAME/api/3/sites/75; rel=self}, @{href=https://DNSNAME/api/3/sites/75/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/75/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/75/scan_schedules; rel=Schedules}...}
name            : Rapid 7 Scanners Site
riskScore       : 4710.0
scanEngine      : 3
scanTemplate    : full-audit-without-web-spider
type            : static
vulnerabilities : @{critical=1; moderate=4; severe=3; total=8}

assets          : 3170
id              : 3
importance      : normal
lastScanTime    : 2021-02-19T21:44:56.653Z
links           : {@{href=https://DNSNAME/api/3/sites/3; rel=self}, @{href=https://DNSNAME/api/3/sites/3/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/3/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/3/scan_schedules; rel=Schedules}...}
name            : Rapid7 Insight Agents
riskScore       : 282816000
scanEngine      : 3
scanTemplate    : full-audit-without-web-spider
type            : agent
vulnerabilities : @{critical=196503; moderate=53786; severe=693745; total=944034}

assets          : 1
id              : 83
importance      : normal
lastScanTime    : 2020-12-02T22:20:37.559Z
links           : {@{href=https://DNSNAME/api/3/sites/83; rel=self}, @{href=https://DNSNAME/api/3/sites/83/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/83/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/83/scan_schedules; rel=Schedules}...}
name            : Synology Devices
riskScore       : 28601.0
scanEngine      : 12
scanTemplate    : hipaa-audit
type            : static
vulnerabilities : @{critical=16; moderate=9; severe=25; total=50}

assets          : 0
description     : These are IT owned UPS devices.
id              : 79
importance      : normal
links           : {@{href=https://DNSNAME/api/3/sites/79; rel=self}, @{href=https://DNSNAME/api/3/sites/79/alerts; rel=Alerts}, 
                  @{href=https://DNSNAME/api/3/sites/79/scan_engine; rel=Scan Engine}, @{href=https://DNSNAME/api/3/sites/79/scan_schedules; rel=Schedules}...}
name            : UPS
riskScore       : 0.0
scanEngine      : 12
scanTemplate    : discovery
type            : static
vulnerabilities : @{critical=0; moderate=0; severe=0; total=0}
1 Like

This will apply the Owner Tag of “Me” to the first 500 Windows OS Assets you have:

$Rapid7_Owner = 'Me'
$Rapid7_Body = [pscustomobject]@{
    name = $Rapid7_Owner
    type = 'owner'
}
$Rapid7_NewTag = Invoke-RestMethod -Uri "$Rapid7_BaseUrl/tags" -Body ($Rapid7_Body | ConvertTo-Json) -Headers $Rapid7_Headers -Method Post -ContentType 'application/json'

$Rapid7_AssetSearch = [pscustomobject]@{
  match = 'all'
  filters = @(
     [pscustomobject]@{
        field = 'operating-system'
        operator = 'contains'
        value = 'windows'
     }
  )
}
$Rapid7_AssetResults = (Invoke-RestMethod -Uri "$Rapid7_BaseUrl/assets/search?size=500" -Body $($Rapid7_AssetSearch | ConvertTo-Json) -Method Post -ContentType 'Application/JSON' -Headers $Rapid7_Headers).resources
$Rapid7_AssetResults | ForEach-Object {
    Invoke-RestMethod -Uri "$Rapid7_BaseUrl/tags/$($Rapid7_NewTag.id)/assets/$($_.id)" -Headers $Rapid7_Headers -Method Put
}

hypothetically, I didn’t actually run it but I did pull it out of other code where I did dynamically populate the owner tag from a REST call pulling the data from another system

1 Like