Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 256db46

Browse files
authoredJan 1, 2025··
Merge pull request #241 from cerberauth/discoverable-healthcheck-endpoints
Add Healthcheck endpoints discovery scan
2 parents a648748 + a6c61b8 commit 256db46

File tree

7 files changed

+106
-4
lines changed

7 files changed

+106
-4
lines changed
 

‎internal/cmd/printtable/wellknown_paths_table.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
discoverablegraphql "github.com/cerberauth/vulnapi/scan/discover/discoverable_graphql"
99
discoverableopenapi "github.com/cerberauth/vulnapi/scan/discover/discoverable_openapi"
1010
exposedfiles "github.com/cerberauth/vulnapi/scan/discover/exposed_files"
11+
"github.com/cerberauth/vulnapi/scan/discover/healthcheck"
1112
wellknown "github.com/cerberauth/vulnapi/scan/discover/well-known"
1213
"github.com/olekukonko/tablewriter"
1314
)
@@ -41,6 +42,9 @@ func WellKnownPathsScanReport(reporter *report.Reporter) {
4142
exposedFiles := reporter.GetScanReportByID(exposedfiles.DiscoverableFilesScanID)
4243
rows = append(rows, wellKnownPathsFromReport(exposedFiles, "Exposed Files")...)
4344

45+
healthcheckEndpoints := reporter.GetScanReportByID(healthcheck.DiscoverableHealthCheckScanID)
46+
rows = append(rows, wellKnownPathsFromReport(healthcheckEndpoints, "Health Check")...)
47+
4448
if len(rows) == 0 {
4549
return
4650
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package healthcheck
2+
3+
import (
4+
"github.com/cerberauth/vulnapi/internal/auth"
5+
"github.com/cerberauth/vulnapi/internal/operation"
6+
"github.com/cerberauth/vulnapi/report"
7+
"github.com/cerberauth/vulnapi/scan/discover"
8+
)
9+
10+
const (
11+
DiscoverableHealthCheckScanID = "discover.healthcheck"
12+
DiscoverableHealthCheckScanName = "Discoverable healthcheck endpoint"
13+
)
14+
15+
var issue = report.Issue{
16+
ID: "discover.discoverable_healthcheck",
17+
Name: "Discoverable healthcheck endpoint",
18+
19+
Classifications: &report.Classifications{
20+
OWASP: report.OWASP_2023_SSRF,
21+
},
22+
23+
CVSS: report.CVSS{
24+
Version: 4.0,
25+
Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N",
26+
Score: 0,
27+
},
28+
}
29+
30+
var healthcheckSeclistUrl = "https://raw.githubusercontent.com/cerberauth/vulnapi/main/seclist/lists/healthcheck.txt"
31+
32+
func ScanHandler(op *operation.Operation, securityScheme *auth.SecurityScheme) (*report.ScanReport, error) {
33+
vulnReport := report.NewIssueReport(issue).WithOperation(op).WithSecurityScheme(securityScheme)
34+
r := report.NewScanReport(DiscoverableHealthCheckScanID, DiscoverableHealthCheckScanName, op)
35+
return discover.DownloadAndScanURLs("HealthCheck", healthcheckSeclistUrl, r, vulnReport, op, securityScheme)
36+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package healthcheck_test
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/cerberauth/vulnapi/internal/auth"
8+
"github.com/cerberauth/vulnapi/internal/operation"
9+
"github.com/cerberauth/vulnapi/internal/request"
10+
"github.com/cerberauth/vulnapi/scan/discover/healthcheck"
11+
"github.com/jarcoal/httpmock"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestDiscoverableScanner_Passed_WhenNoDiscoverableHealthCheckEndpointFound(t *testing.T) {
17+
client := request.NewClient(request.NewClientOptions{
18+
RateLimit: 500,
19+
})
20+
httpmock.ActivateNonDefault(client.Client)
21+
defer httpmock.DeactivateAndReset()
22+
23+
op := operation.MustNewOperation(http.MethodGet, "http://localhost:8080/", nil, client)
24+
httpmock.RegisterResponder(op.Method, op.URL.String(), httpmock.NewBytesResponder(http.StatusNoContent, nil))
25+
httpmock.RegisterNoResponder(httpmock.NewBytesResponder(http.StatusNotFound, nil))
26+
27+
report, err := healthcheck.ScanHandler(op, auth.MustNewNoAuthSecurityScheme())
28+
29+
require.NoError(t, err)
30+
assert.Greater(t, httpmock.GetTotalCallCount(), 5)
31+
assert.True(t, report.Issues[0].HasPassed())
32+
}
33+
34+
func TestDiscoverableScanner_Failed_WhenOneHealthCheckEndpointFound(t *testing.T) {
35+
client := request.NewClient(request.NewClientOptions{
36+
RateLimit: 500,
37+
})
38+
httpmock.ActivateNonDefault(client.Client)
39+
defer httpmock.DeactivateAndReset()
40+
41+
operation := operation.MustNewOperation(http.MethodGet, "http://localhost:8080/healthz", nil, client)
42+
httpmock.RegisterResponder(operation.Method, operation.URL.String(), httpmock.NewBytesResponder(http.StatusOK, nil))
43+
httpmock.RegisterNoResponder(httpmock.NewBytesResponder(http.StatusNotFound, nil))
44+
45+
report, err := healthcheck.ScanHandler(operation, auth.MustNewNoAuthSecurityScheme())
46+
47+
require.NoError(t, err)
48+
assert.Greater(t, httpmock.GetTotalCallCount(), 0)
49+
assert.True(t, report.Issues[0].HasFailed())
50+
}

‎scan/discover/well-known/well_known.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ const (
1212
DiscoverableWellKnownScanName = "Discoverable well-known path"
1313
)
1414

15-
type DiscoverableGraphQLPathData = discover.DiscoverData
16-
1715
var issue = report.Issue{
1816
ID: "discover.discoverable_well_known",
1917
Name: "Discoverable well-known path",

‎scenario/discover_api.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import (
77
discoverablegraphql "github.com/cerberauth/vulnapi/scan/discover/discoverable_graphql"
88
discoverableopenapi "github.com/cerberauth/vulnapi/scan/discover/discoverable_openapi"
99
exposedfiles "github.com/cerberauth/vulnapi/scan/discover/exposed_files"
10-
fingerprint "github.com/cerberauth/vulnapi/scan/discover/fingerprint"
10+
"github.com/cerberauth/vulnapi/scan/discover/fingerprint"
11+
"github.com/cerberauth/vulnapi/scan/discover/healthcheck"
1112
wellknown "github.com/cerberauth/vulnapi/scan/discover/well-known"
1213
)
1314

@@ -37,6 +38,7 @@ func NewDiscoverAPIScan(method string, url string, client *request.Client, opts
3738
urlScan.AddScanHandler(scan.NewOperationScanHandler(discoverablegraphql.DiscoverableGraphQLPathScanID, discoverablegraphql.ScanHandler))
3839
urlScan.AddScanHandler(scan.NewOperationScanHandler(exposedfiles.DiscoverableFilesScanID, exposedfiles.ScanHandler))
3940
urlScan.AddScanHandler(scan.NewOperationScanHandler(wellknown.DiscoverableWellKnownScanID, wellknown.ScanHandler))
41+
urlScan.AddScanHandler(scan.NewOperationScanHandler(healthcheck.DiscoverableHealthCheckScanID, healthcheck.ScanHandler))
4042

4143
return urlScan, nil
4244
}

‎seclist/lists/healthcheck.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
alive
2+
health
3+
health/live
4+
health/ready
5+
health/started
6+
healthz
7+
healthz/live
8+
healthz/ready
9+
ready
10+
status
11+
status/live
12+
status/ready

‎seclist/lists/well-known.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
.well-known/jwks.json
44
.well-known/oauth-authorization-server
55
.well-known/openid-configuration
6-
.well-known/openid-federation
6+
.well-known/openid-federation

0 commit comments

Comments
 (0)
Please sign in to comment.