Showing posts with label JAR. Show all posts
Showing posts with label JAR. Show all posts

Saturday, 2 August 2008

On GIFARs

The Black Hat Briefings 2008 are fast approaching. As I mentioned in my previous post on stealing password hashes I am speaking with Nate McFeters and Rob Carter; you can find the abstract for our talk here.


One of the areas that we'll be talking about is some quality research carried out by Billy Rios (Billy was originally speaking due to speak with us but is no longer; he is giving his Bad Sushi talk though, so check it out). Billy realised that you can make a JAR archive look like a GIF image (dubbed a "GIFAR"), or in more general terms, that you can make a JAR look like many other file types. He is not alone in this observation; PDP has also been working on similar ideas. Now many websites allow you to upload specific types of content - images for example. Most web applications will check the extension of the uploaded files and many will also do some content inspection to make sure the file is what the extension says it is.


This means we can upload a JAR on to a publicly accessible page (e.g. a profile page). This has interesting implications. Suppose you end up running malicious content in your browser. Ordinarily it would not be able to fully interact with other websites you might be logged into (CSRF does not constitute full interaction); this is a tenet of the same origin policy implemented by all browsers. However what if the malicious content contains an APPLET tag that references the JAR file uploaded to the target site? The Java browser plugin sees a codebase URL of the target site and consequently adds a SocketPermission allowing the applet to connect back to it and make full requests.


But that is only part of the story. It turns out that when an applet makes an HTTP request to a website the Java browser plugin will slap on the relevant cookies from the browser cookie store (even if the applet is unsigned). This initially surprised me - as far as I can remember older versions of the JRE never supported this. A little digging into how this is accomplished in IE revealed there is a class, com.sun.deploy.net.cookie.IExplorerCookieHandler that contains the following native methods:



JNIEXPORT jstring JNICALL Java_com_sun_deploy_net_cookie_IExplorerCookieHandler_getCookieInfo
(JNIEnv *env, jobject sender, jstring url)

JNIEXPORT void JNICALL Java_com_sun_deploy_net_cookie_IExplorerCookieHandler_setCookieInfo
(JNIEnv *env, jobject, jstring url, jstring value)


These methods call the Wininet functions InternetGetCookie and InternetSetCookie respectively. Now if only there was a way of calling these functions with arbitrary URLs... (seriously I don't have one! At least I don't yet.)


So to summarise, once the malicious content references an applet on the target site, it can send arbitrary requests and parse the responses; if you are logged are, these requests will be made with your cookies, giving the applet full control of your account.


Billy's research is getting a fair amount of press (with some creative headlines) prompting Nate to make some further clarifications on his blog. In some of the articles that are appearing credit is wrongly being attributed to me/my employer/Nate/Black Hat hackers/those pesky kids/our new GIFAR overlords and so on, so I'm setting the record straight: this is Billy's baby.


Anyway, that's a brief summary of the issue. Hopefully I'll have time to put out another post before Black Hat. If not, hope to see you there.




Cheers

John

Saturday, 21 June 2008

A Different Form of JAR Hell

In my last post I used a Java applet to steal password hashes. Part two, covering NTLMv2, is on its way. Today however, I'm going to discuss SunSolve #233323 - a vulnerability that was fixed in the March updates to the JRE. Anyone who caught my ToorCon talk will have already heard me discuss this issue.


Java Web Start has provision for resources, signed JAR files that contain either Java classes or native libraries that can be cached for use by one or more applications. JARs containing Java classes are extracted as per the usual Java caching mechanism (i.e. written to disk using randomly generated names) whereas native libraries are extracted with their original filenames. Interestingly filenames can include parent path sequences (e.g. ..\..\..\..\test.txt). This means that "nativelibs" can be written outside the cache folder. But that's ok because nativelib resources need to be signed and therefore explicitly trusted by the user, right?


Not exactly. Take a look at the following code snippet, which resembles the vulnerable Java Web Start code, and see if you can spot the bypass (it's not exactly obvious):


try
{
// Open the JAR file specifying true to indicate
// we want to verify the JarFile is signed.
JarFile jf = new JarFile(UserSuppliedFile, true);

Enumeration e = jf.entries();
while (e.hasMoreElements())
{
ZipEntry ze = (ZipEntry) e.nextElement();
InputStream i = jf.getInputStream(ze);
byte b[] = new byte[i.available()];
i.read(b);

// Call our method to write the bytes
// to disk

WriteFileToDisk(ze.getName(), b);
}
}
catch (SecurityException se)
{
// Some sort of signature verification error
System.out.println("Security Error: " + se.toString());
}
catch (IOException ioe)
{
System.out.println("File Error: " + ioe.toString());
}


If you spotted the problem, well done! If not, here's a hint courtesy of an IBM article on signed JARs:


Each signer of a JAR is represented by a signature file with the extension .SF within the META-INF directory of the JAR file. The format of the file is similar to the manifest file -- a set of RFC-822 headers. As shown below, it consists of a main section, which includes information supplied by the signer but not specific to any particular JAR file entry, followed by a list of individual entries which also must be present in the manifest file. To validate a file from a signed JAR, a digest value in the signature file is compared against a digest calculated against the corresponding entry in the JAR file.


What if a file doesn't have a corresponding manifest entry? It turns out the above code will happily call WriteFileToDisk anyway and there'll be no exception thrown. We can use this bypass to append a file to a signed resource and have it drop a java.policy file in the user's home directory allowing applets and Web Start applications to do bad things.

Let's take a look at how the Jarsigner tool that ships with the JDK validates signed JARs. Jarsigner correctly detects JARs containing both signed and unsigned content:



The code snippet below shows the enumeration of ZipEntrys; it's taken from sun.security.tools.JarSigner:


Enumeration e = entriesVec.elements();

long now = System.currentTimeMillis();

while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
CodeSigner[] signers = je.getCodeSigners();
boolean isSigned = (signers != null);
anySigned |= isSigned;
hasUnsignedEntry |= !je.isDirectory() && !isSigned
&& !signatureRelated(name);


The code retrieves the entry's CodeSigners; if there are none the entry is deemed unsigned.


As an aside, it's actually possible to fool Jarsigner. Take a look at the signatureRelated method, which is called above:


    /**
* signature-related files include:
* . META-INF/MANIFEST.MF
* . META-INF/SIG-*
* . META-INF/*.SF
* . META-INF/*.DSA
* . META-INF/*.RSA
*/
private boolean signatureRelated(String name) {
String ucName = name.toUpperCase();

if (ucName.equals(JarFile.MANIFEST_NAME) ||
ucName.equals(META_INF) ||
(ucName.startsWith(SIG_PREFIX) &&
ucName.indexOf("/") == ucName.lastIndexOf("/"))) {
return true;
}


Jarsigner ignores unsigned files that start with the prefix "META-INF/SIG-":



Anyway, back to the Web Start issue. Soon after discovering this bug I realised it was effectively moot for I hadn't seen any security dialogs even when working with fully signed JARs. It turned out there were none. Ever. You could simply even use a self-signed JAR! Still, it's a great example of a managed language providing a simple interface (JarFile) that masks a complex implementation; if the contract between the caller and the callee is not clearly defined (however simple the interface), developers can write insecure code without knowing it.


So that's it for now. There's also some interesting behaviour when loading applets containing signed and unsigned content but I'll save that for another day.



Cheers

John

p.s. In case you were wondering, JAR hell is Java's form of DLL hell.