Skip to content

Commit 674f396

Browse files
authored
Merge pull request #9 from lalithr95/rate-limit
implement api rate limiting check
2 parents e44cd7f + 4329438 commit 674f396

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

lib/API_Fuzzer.rb

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require 'API_Fuzzer/xxe_check'
1010
require 'API_Fuzzer/redirect_check'
1111
require 'API_Fuzzer/idor_check'
12+
require 'API_Fuzzer/rate_limit_check'
1213

1314
module API_Fuzzer
1415
# Scans all the checks
@@ -22,6 +23,7 @@ def self.scan(options = {})
2223
vulnerabilities << API_Fuzzer::SqlBlindCheck.scan(options)
2324
vulnerabilities << API_Fuzzer::RedirectCheck.scan(options)
2425
vulnerabilities << API_Fuzzer::IdorCheck.scan(options)
26+
vulnerabilities << API_Fuzzer::RateLimitCheck(options)
2527
API_Fuzzer::XxeCheck.scan(options)
2628
vulnerabilities.uniq.flatten
2729
end

lib/API_Fuzzer/rate_limit_check.rb

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
require 'API_Fuzzer/vulnerability'
2+
require 'API_Fuzzer/request'
3+
4+
module API_Fuzzer
5+
class RateLimitCheck
6+
def self.scan(options = {})
7+
@url = options[:url]
8+
@params = options[:params] || {}
9+
@cookies = options[:cookies] || {}
10+
@vulnerabilities = []
11+
@limit = options[:limit] || 50
12+
@methods = options[:method] || [:get]
13+
14+
@methods.each { |method| fuzz_api_requests(method) }
15+
@vulnerabilities.uniq { |vuln| vuln.description }
16+
end
17+
18+
def self.fuzz_api_requests(method)
19+
initial_response = fetch_initial_response(method)
20+
21+
responses = []
22+
@limit.times do
23+
responses << API_Fuzzer::Request.send_api_request(
24+
url: @url,
25+
method: method,
26+
cookies: @cookies,
27+
params: @params
28+
)
29+
end
30+
31+
vulnerable = true
32+
responses.each do |response|
33+
if response.code == initial_response.code
34+
content_length = response_content_length(response)
35+
initial_content_length = response_content_length(initial_response)
36+
if content_length != initial_content_length
37+
vulnerable = false
38+
break
39+
end
40+
else
41+
vulnerable = false
42+
break
43+
end
44+
end
45+
@vulnerabilities << API_Fuzzer::Vulnerability.new(
46+
description: "API is not rate limited for #{method} #{@url}",
47+
value: "API doesn't have any ratelimiting protection enabled which can be implemented by either throttling request or using captcha",
48+
type: 'LOW'
49+
) if vulnerable
50+
end
51+
52+
private
53+
def self.fetch_initial_response(method)
54+
API_Fuzzer::Request.send_api_request(
55+
url: @url,
56+
method: method,
57+
cookies: @cookies,
58+
params: @params
59+
)
60+
end
61+
62+
def self.response_content_length(response)
63+
response.headers['Content-Length'] || response.body.to_s.size
64+
end
65+
end
66+
end

0 commit comments

Comments
 (0)