[zz]Opera Arioso!

5 views
Skip to first unread message

大风

unread,
Jul 6, 2008, 9:43:14 PM7/6/08
to ph4...@googlegroups.com

 

So, my dear Firefox and Explorer fanboys :) I have something special today for Opera users only. I'm pretty excited by Opera's Userscripts that allow you to write Javascript files that are far richer than greasemonkey Userscripts -which is also supported by Opera- I've written a security plugin for Opera last night, that attempts to mitigate various Javascript attack vectors. But, one problem for writing a security plugin is that we usually need to process a script before it gets rendered by the browser. Otherwise, it is already to late to block a dangerous request or script instance. This is particularly useful to mitigate CSRF and XSS.

For instance, the Opera event listeners can process inline or remote Javascript and other page events before and after it gets executed. What a marvelous idea, I am really stunned when I read about it. It's exactly what I wanted for Opera! It really gives absolute user control over the page. Bare with me, it is written in a couple of hours with a few ideas I had at the moment. I will be working on it some more when I find the time for it. I gave the script the name Arioso, as an appreciation for Opera.

Arioso's features I created:

-Arioso enumerates all links inside a website looking for dangerous URI schemes
-Arioso blocks remote JS files that are not coming from the same-domain (strict SOP)
-Arioso scans remote and same-origin Javascript before it gets rendered and kills the script if needed.
-When it is done, it creates a bar in the browser alerting the issue at hand.

Arioso source can be loaded into Opera. To enable user JavaScript, use Tools > Preferences > Advanced > Content > JavaScript options, and select the directory where you will put your User JavaScript files. Opera will load all files in the specified directory whose names end with .js and will use them as User JavaScript files.

/*

        ~~~ Opera Arioso!  ~~~

        by rvdh, 0x000000.com



*/



// Ariosos magic (ghost) varibales

window.opera.defineMagicVariable('arioso_links', function() {}, null);

window.opera.defineMagicVariable('arioso_sanitize_xss', function() {}, null);



// Arioso variables

var arioso_links = document.links;

var arioso_sanitize_xss = true;

var bad_arioso_schemes = '';



// Arioso arrays

var arioso_schemes = ["chrome:", "file:", "opera:", "res:", "data:", "telnet:", "about:", "resource:", "view-source:", "acrobat:", "mms:", "localhost", "loopback"];



// Arioso link enumerator detecting bad schemes

for (var i = 0; i < arioso_links.length;++i) {

    for (j = 0; j < arioso_schemes.length;++j) {

        if (arioso_links[i].toString().match(arioso_schemes[j])) {

            bad_arioso_schemes += arioso_schemes[j] + ' | ';

        }

    }

}





// Arioso evil JS blocker

window.opera.addEventListener('BeforeScript', function(e) {

    // prevent heap spraying, denial of service

    if (e.element.text.match(/for\s*\(\s*[a-z]\s*\=\s*[0-9]\s*;\s*[a-z]\s*(<|>|<=|>=|<==|>==)\s*[0-9]{3,}\s*;\s*/gim)) {

        arioso_alert = 'Possible heapspraying or denial of service vector found and blocked';

        e.preventDefault();

        // prevent heap spraying, stack/heap overflows

        }

    if (e.element.text.match(/(while|for|space|block|memory).*unescape\(("|')%([0-9]|\\x|\\u)([a-z]|[0-9])("|')\)/gim)) {

        arioso_alert = 'Possible heapspraying or denial of service vector found and blocked';

        e.preventDefault();

        // VBinjection

        }

    if (e.element.text.match(/String\(\s*[0-9]{6,},\s*"[a-z]"\)/gim)) {

        arioso_alert = 'VBInjection vector found and blocked';

        e.preventDefault();

        // prevent JS cookie stealing

        }

    if (e.element.text.match(/http:\/\/.*\?.*=.*(\+|concat|join).*document\.cookie/gim)) {



        arioso_alert = 'Cookie stealing attempt blocked';

        e.preventDefault();

        // prevent  non-same origin bad URI sourcing

        }

    if (e.element.text.match(/(src|href|location)\s*=.*(localhost|loopback|telnet:|file:|res:|resource:|about:|javascript:|data:)/gim)) {

        arioso_alert = 'Prevented non-same origin URI sourcing';

        e.preventDefault();

        // prevent keycode logging



        }

    if (e.element.text.match(/(\.charCode|\.keyCode))/gim)) {

        arioso_alert = 'Prevented keylogging';

        e.preventDefault();

        // Arioso self protection, not really needed because of the 'ghost' variables.

        }

    if (e.element.text.match(/(bad_arioso_schemes|arioso_links|arioso_schemes|arioso_sanitize_xss))/gim)) {

        e.preventDefault();

    }

}, false);



// Arioso strict non-same origin JS blocker (think: ads, and cookie stealers)

window.opera.addEventListener('BeforeExternalScript', function(e) {

    // If JS is not on the same domain, block it

    if (!e.element.getAttribute('src').match(document.location)) {

        e.preventDefault();

    }

}, false);





document.addEventListener('load', function(e) {



    if (bad_arioso_schemes) {

        arioso_message = 'found and blocked unsafe URI hyperlink schemes.\r\nSchemes found and blocked: | ' + bad_arioso_schemes;

    } else if (arioso_alert) {

        arioso_message = arioso_alert;

    }



    if (arioso_message) {

        var ary = document.createElement('div');

        ary.style.position = 'fixed';

        ary.style.top = '0px';

        ary.style.left = '0px';

        ary.style.width = '100%';

        ary.style.border = '1px solid #999';

        ary.style.padding = '3px';

        ary.style.font = 'small-caps bold 10pt sans-serif';

        ary.style.backgroundColor = '#fffff0';

        ary.style.color = '#000';

        ary.appendChild(document.createTextNode('ARIOSO: ' + arioso_message))

            document.body.appendChild(ary);

    } else {

        return true;

    }

}, false);



List of useful userscript events:

BeforeExternalScript
Fired when a SCRIPT element with a SRC attribute is encountered. The script element is available as the element attribute of the UserJSEvent. If cancelled, the external source is not loaded and the script element is not executed. In addition, if it is cancelled, the BeforeScript event will not fire.

BeforeScript
Fired before a SCRIPT element is executed. The script element is available as the element attribute of the UserJSEvent. The content of the script is available as the text property of the script element, and is also writable:
UserJSEvent.element.text = UserJSEvent.element.text.replace(/!=s*null/,'');
The BeforeScript event is fired for inline scripts as well as external scripts, including scripts with a type that Opera normally does not execute (such as VBScript). If cancelled, the script element is not executed.

AfterScript
Fired after a SCRIPT element has finished executing. The script element is available as the element attribute of the UserJSEvent.

BeforeEvent
Fired before a regular event is fired, regardless of whether such an event would be handled by any event handlers. The regular event is available as the event attribute of the UserJSEvent. If cancelled, the regular event is not fired, its default action is performed, and any associated BeforeEventListener events are not fired.

BeforeEvent.type
Like BeforeEvent, but fired only for events of the specified type (for example, BeforeEvent.click). In Opera 8, if any listeners are registered for a matching BeforeEvent.type event, no BeforeEvent event is fired. In Opera 9, both will fire.

AfterEvent
Fired after a regular event has been fired and handled but before its default action has been performed. The regular event is available as the event attribute of the UserJSEvent. If cancelled, any attempts by a regular event handler to cancel the regular event will be ignored. The UserJSEvent object will also have the eventCancelled property, that will be set to true if any regular event handlers have cancelled the event.

AfterEvent.type
Like AfterEvent, but fired only for events of the specified type (for example, AfterEvent.click). In Opera 8, if any listeners are registered for a matching AfterEvent.type event, no AfterEvent event is fired. In Opera 9, both will fire.

BeforeEventListener
Fired before a listener for a regular event is called. The regular event is available as the event attribute of the UserJSEvent, and the listener to be called is available as the listener attribute of the UserJSEvent. If cancelled, the regular event listener will not be called.

BeforeEventListener.type
Like BeforeEventListener, but fired only for events of the specified type (for example, BeforeEventListener.click). In Opera 8, if any listeners are registered for a matching BeforeEventListener.type event, no BeforeEventListener event is fired. In Opera 9, both will fire.

AfterEventListener
Fired after a listener for regular events is called. The regular event is available as the event attribute of the UserJSEvent, and the listener to be called is available as the listener attribute of the UserJSEvent. If cancelled, any attempts by a regular event handler to cancel the regular event propagation will be ignored. The UserJSEvent object will also have the propagationStopped property, that will be set to true if any regular event handlers have cancelled the event propagation.

AfterEventListener.type
Like AfterEventListener, but fired only for events of the specified type (for example, AfterEventListener.click). In Opera 8, if any listeners are registered for a matching AfterEventListener.type event, no AfterEventListener event is fired. In Opera 9, both will fire.

BeforeJavascriptURL
Fired before a javascript: URL is executed. The JavaScript code to be executed (everything after the 'javascript:' in the URL) is available as the source attribute of the UserJSEvent, and is also writable. If cancelled, the javascript: URL is not executed.

AfterJavascriptURL
Fired after a javascript: URL is executed. The JavaScript code that was executed (everything after the 'javascript:' in the URL) is available as the source attribute of the UserJSEvent, and any value returned by that code is available as the returnValue attribute of the UserJSEvent. The returnValue is also writable. If cancelled, any returned value will not be used as the source of a new page.

 

[Ph4nt0m]

[Ph4nt0m Security Team]

                  @ph4nt0m

          Email:  ax...@ph4nt0m.org

          PingMe:

          === V3ry G00d, V3ry Str0ng ===

          === Ultim4te H4cking ===

          === XPLOITZ ! ===

          === #_# ===

#If you brave,there is nothing you cannot achieve.#

 

 

Reply all
Reply to author
Forward
0 new messages