Skip to content

Commit

Permalink
We added a new attribute uris which allows a list of URI. (#49)
Browse files Browse the repository at this point in the history
`uri` and `uris` can't be specified at the same time.

One example configuration file is as follow:

```yaml
  - uris: ["/db.sql", "/db.sql.gz", "/db.sqlite", "/db.sqlite.gz", "/db.sqlite3", "/db.sqlite3.gz", "/data.sql", "/data.sql.gz", "/users.sql", "/users.sql.gz", "/dump.sql", "/dump.sql.gz", "/mysqldump.sql", "/mysqldump.sql.gz", "/backup.sql", "/backup.sql.gz", "/db.backup", "/db.backup.gz", "/database.sql", "/database.sql.gz", "/db-data.sql", "/db-data.sql.gz", "/db_test.sql", "/db_test.sql.gz", "/db-test.sql", "/db-test.sql.gz"]
    checks:
      - name: Database file
        status_code: 200
        remediation: Delete this file
        description: Verifies a database dump is accessible.
        severity: "High"
```

And we tried it using:

```bash
./gochopchop scan -u http://127.0.0.1:3000 --timeout 1 --csv --csv-file boo.csv -c policy.yml
```

Closes #2
  • Loading branch information
PaulSec authored Oct 23, 2020
1 parent 0def9d5 commit fc05c68
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 45 deletions.
96 changes: 55 additions & 41 deletions app/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,60 +103,74 @@ func Scan(cmd *cobra.Command, args []string) {
go func(domain string) {
defer wg.Done()
Verbose("Testing domain : "+prefix+domain+suffix, verbose)
for index, plugin := range y.Plugins {
_ = index
for _, plugin := range y.Plugins {

canExecutePluginByName := isPluginAuthorized(plugin, tags)
if !canExecutePluginByName {
Verbose("Skipping signature rule with URI: "+plugin.URI, verbose)
var uris []string
// check the present of `uri` and `uris` which has to be forbidden
if len(plugin.ListOfURI) > 0 && plugin.URI != "" {
log.Fatal("You can't both have `uri` and `uris` specified for URI: " + plugin.URI)
}

canExecutePluginBySeverity := isPluginAuthorizedBySeverity(plugin, severity)
if !canExecutePluginBySeverity {
Verbose("Skipping signature rule with URI: "+plugin.URI, verbose)
if plugin.URI != "" {
uris = make([]string, 1)
uris[0] = plugin.URI
} else {
uris = plugin.ListOfURI
}

if canExecutePluginByName && canExecutePluginBySeverity {
tmpURL = prefix + domain + suffix + fmt.Sprint(plugin.URI)
if plugin.QueryString != "" {
tmpURL += "?" + plugin.QueryString
for j := 0; j < len(uris); j++ {
canExecutePluginByName := isPluginAuthorized(plugin, tags)
if !canExecutePluginByName {
Verbose("Skipping signature rule with URI: "+uris[j], verbose)
}

// By default we follow HTTP redirects
followRedirects := true
// But for each plugin we can override and don't follow HTTP redirects
if plugin.FollowRedirects != nil && *plugin.FollowRedirects == false {
followRedirects = false
canExecutePluginBySeverity := isPluginAuthorizedBySeverity(plugin, severity)
if !canExecutePluginBySeverity {
Verbose("Skipping signature rule with URI: "+uris[j], verbose)
}

Verbose("Testing URL: "+tmpURL, verbose)
httpResponse, err := pkg.HTTPGet(insecure, tmpURL, followRedirects, httpRequestTimeout)
if err != nil {
fmt.Println(err)
}
if canExecutePluginByName && canExecutePluginBySeverity {
tmpURL = prefix + domain + suffix + fmt.Sprint(uris[j])
if plugin.QueryString != "" {
tmpURL += "?" + plugin.QueryString
}

if httpResponse != nil {
for _, check := range plugin.Checks {
if severity != "" && check.Severity.String() != severity {
continue // break if the severity is defined and different from the one we specified
}
answer := pkg.ResponseAnalysis(httpResponse, check)
if answer {
Verbose("[!] Hit found!\n\tURL: "+tmpURL+"\n\tPlugin: "+check.PluginName+"\n\tSeverity: "+string(*check.Severity), verbose)
hit = true
if BlockCI(blockedFlag, *check.Severity) {
block = true
// By default we follow HTTP redirects
followRedirects := true
// But for each plugin we can override and don't follow HTTP redirects
if plugin.FollowRedirects != nil && *plugin.FollowRedirects == false {
followRedirects = false
}

Verbose("Testing URL: "+tmpURL, verbose)
httpResponse, err := pkg.HTTPGet(insecure, tmpURL, followRedirects, httpRequestTimeout)
if err != nil {
fmt.Println(err)
}

if httpResponse != nil {
for _, check := range plugin.Checks {
if severity != "" && check.Severity.String() != severity {
continue // break if the severity is defined and different from the one we specified
}
answer := pkg.ResponseAnalysis(httpResponse, check)
if answer {
Verbose("[!] Hit found!\n\tURL: "+tmpURL+"\n\tPlugin: "+check.PluginName+"\n\tSeverity: "+string(*check.Severity), verbose)
hit = true
if BlockCI(blockedFlag, *check.Severity) {
block = true
}
out = append(out, data.Output{
Domain: domain,
PluginName: check.PluginName,
TestedURL: uris[j],
Severity: string(*check.Severity),
Remediation: *check.Remediation,
})
}
out = append(out, data.Output{
Domain: domain,
PluginName: check.PluginName,
TestedURL: plugin.URI,
Severity: string(*check.Severity),
Remediation: *check.Remediation,
})
}
_ = httpResponse.Body.Close()
}
_ = httpResponse.Body.Close()
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions data/format_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ type Config struct {

// Signature struct to load it afterwards
type Signature struct {
URI string `yaml:"uri"`
QueryString string `yaml:"query_string"`
Checks []Check `yaml:"checks"`
FollowRedirects *bool `yaml:"follow_redirects"`
URI string `yaml:"uri"`
ListOfURI []string `yaml:"uris"`
QueryString string `yaml:"query_string"`
Checks []Check `yaml:"checks"`
FollowRedirects *bool `yaml:"follow_redirects"`
}

// IsValid will verify that the severityType is part of the enum previously declared
Expand Down

0 comments on commit fc05c68

Please sign in to comment.