JavaMail is vulnerable to a directory-traversal attack where files can be written to an arbitrary location within the filesystem, by specifying a Content-Disposition header which contains a relative path.
0d8d9c543b406aa12fb6d97ffbe7d720e1c2adf4a994ee527ee49219e237ba7f
1. INTRODUCTION
The JavaMail API provides a platform-independent and
protocol-independent framework to build mail and messaging applications.
The JavaMail API is implemented as a Java platform optional package and
is also available as part of the Java 2 platform, Enterprise Edition.
2. SYNOPSIS
MimeBodyPart.getFileName () method in the JavaMail API doesn't properly
validate filename attribute in Content-Disposition header, what makes it
vulnerable to directory traversal attacks. Successful exploitation of
this vulnerability allows writing arbitrary content in any directory
accessible to the servlet running JavaMail.
3. AFFECTED VERSIONS
This vulnerability has been checked in current release, JavaMail 1.3.2.
It may be present in all previous versions.
4. EXPLOITATION PROCEDURE
Send an email with the following filename attribute in
Content-Disposition header:
../../../file.ext
This will write attachment three directories backward from expected
location, as long as the servlet processing the email has writeable
access to that directory.
5. EXAMPLE SCENARIO
This method uses getFileName () method to save the first attachment into
a file:
protected void saveMailAttachment (javax.mail.internet.MimeMultipart mp) {
try {
int n = mp.getCount();
javax.mail.Part p = mp.getBodyPart (0);
String disposition = p.getDisposition ();
if (disposition != null &&
(disposition.equalsIgnoreCase (javax.mail.Part.ATTACHMENT)
|| disposition.equalsIgnoreCase (javax.mail.Part.INLINE) ) ) {
String filename = p.getFileName ();
File f = new File (filename);
OutputStream os = new BufferedOutputStream (new FileOutputStream (f) );
InputStream is = p.getInputStream ();
int c;
while ( (c = is.read () ) != -1)
os.write (c);
os.close ();
}
} catch (Exception e) { }
}
6. API DOCUMENTATION
getFileName
public java.lang.String getFileName() throws MessagingException
Get the filename associated with this part, if possible. Useful if this
part represents an "attachment" that was loaded from a file. The
filename will usually be a simple name, not including directory components.
Returns: Filename to associate with this part
7. VULNERABLE SOURCE CODE
The following code has been obtained by decompiling JavaMail
MimeBodyPart class file. Although JavaMail source code is available from
Suns site, checking this vulnerability over binaries is somewhat more
reliable.
MimeBodyPart.java:
public String getFileName () throws MessagingException {
return getFileName ( ( (MimePart) (this) ) );
}
static String getFileName (MimePart mimepart) throws MessagingException {
String s = null;
String s1 = mimepart.getHeader ("Content-Disposition", null);
if (s1 != null) {
ContentDisposition contentdisposition = new ContentDisposition (s1);
s = contentdisposition.getParameter("filename");
}
if (s == null) {
String s2 = mimepart.getHeader ("Content-Type", null);
if (s2 != null)
try {
ContentType contenttype = new ContentType (s2);
s = contenttype.getParameter ("name");
} catch (ParseException _ex) { }
}
if (decodeFileName && s != null) {
try {
s = MimeUtility.decodeText(s);
} catch(UnsupportedEncodingException unsupportedencodingexception) {
throw new MessagingException
("Can't decode filename", unsupportedencodingexception);
}
}
return s;
}
Not that no check for directory traversal patterns is performed.
8. CURRENT WORKAROUND
Input validation mechanism should be enforced in the servlet being
developed. No patches are available for this issue.
9. MORE INFORMATION
https://java.sun.com/products/javamail/
-------------------------------
Rafael San Miguel Carrasco
Security Consultant
rafael.sanmiguel@dvc.es
+ 34 660 856 647
+ 34 902 464 546
Davinci Consulting - www.dvc.es
Oficina Madrid - Parque empresarial Alvento
Via de los Poblados 1 Edificio A 6ยช planta
28033 Madrid
-------------------------------