Java SignedObject-beheerde Deserialisering en Pre-auth bereikbaarheid via foutpaaie
Reading time: 7 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Hierdie bladsy dokumenteer 'n algemene "beheerde" Java deserialisering-patroon opgebou rondom java.security.SignedObject en hoe skynbaar onbereikbare sinks pre-auth bereikbaar kan word via fout-handhavingsvloei. Die tegniek is waargeneem in Fortra GoAnywhere MFT (CVE-2025-10035) maar is van toepassing op soortgelyke ontwerpe.
Bedreigingsmodel
- Aanvaller kan 'n HTTP-endpoint bereik wat uiteindelik 'n aanvaller-voorsiene byte[] verwerk wat bedoel is om 'n geserialiseerde SignedObject te wees.
- Die kode gebruik 'n validating wrapper (bv., Apache Commons IO ValidatingObjectInputStream of 'n pasgemaakte adapter) om die buitenste tipe te beperk tot SignedObject (of byte[]).
- Die binneste objek wat deur SignedObject.getObject() teruggegee word is waar gadget-kettinge kan ontbrand (bv., CommonsBeanutils1), maar slegs ná 'n handtekening-verifikasiehek.
Tipiese kwesbare patroon
'n Vereenvoudigde voorbeeld gebaseer op com.linoma.license.gen2.BundleWorker.verify:
private static byte[] verify(byte[] payload, KeyConfig keyCfg) throws Exception {
String sigAlg = "SHA1withDSA";
if ("2".equals(keyCfg.getVersion())) {
sigAlg = "SHA512withRSA"; // key version controls algorithm
}
PublicKey pub = getPublicKey(keyCfg);
Signature sig = Signature.getInstance(sigAlg);
// 1) Outer, "guarded" deserialization restricted to SignedObject
SignedObject so = (SignedObject) JavaSerializationUtilities.deserialize(
payload, SignedObject.class, new Class[]{ byte[].class });
if (keyCfg.isServer()) {
// Hardened server path
return ((SignedContainer) JavaSerializationUtilities.deserializeUntrustedSignedObject(
so, SignedContainer.class, new Class[]{ byte[].class }
)).getData();
} else {
// 2) Signature check using a baked-in public key
if (!so.verify(pub, sig)) {
throw new IOException("Unable to verify signature!");
}
// 3) Inner object deserialization (potential gadget execution)
SignedContainer inner = (SignedContainer) so.getObject();
return inner.getData();
}
}
Sleutelwaarnemings:
- Die validating deserializer by (1) blokkeer arbitrêre topvlak gadget-klasse; slegs SignedObject (of raw byte[]) word aanvaar.
- Die RCE-primitive sal in die innerlike objek wees wat deur SignedObject.getObject() by (3) gematerialiseer word.
- 'n Signature gate by (2) dwing af dat die SignedObject teen 'n product-baked public key moet verify(). Tensy die aanvaller 'n geldige signature kan produseer, deserialiseer die innerlike gadget nooit.
Oorwegings vir uitbuiting
Om code execution te bereik, moet 'n aanvaller 'n korrek getekende SignedObject lewer wat 'n kwaadwillige gadget chain as sy innerlike objek omsluit. Dit vereis gewoonlik een van die volgende:
- Private key compromise: bekom die ooreenstemmende private sleutel wat deur die produk gebruik word om license objects te sign/verify.
- Signing oracle: dwing die vendor of 'n vertroude signing service om attacker-controlled serialized content te sign (bv. as 'n license server 'n ingeslote arbitrary object uit client input teken).
- Alternate reachable path: vind 'n server-side pad wat die innerlike objek deserialiseer sonder om verify() af te dwing, of wat signature checks onder 'n spesifieke modus oorslaan.
As een van hierdie afwesig is, sal signature verification uitbuiting voorkom ondanks die teenwoordigheid van 'n deserialization sink.
Pre-auth bereikbaarheid via foutafhandelingsvloei
Selfs wanneer 'n deserialization endpoint blyklik authentisering of 'n session-bound token te vereis, kan foutafhandelingskode per ongeluk die token skep en aan 'n unauthenticated session heg.
Voorbeeld bereikbaarheidsketting (GoAnywhere MFT):
- Target servlet: /goanywhere/lic/accept/
vereis 'n session-bound license request token. - Error path: die tref van /goanywhere/license/Unlicensed.xhtml met trailing junk en invalid JSF state veroorsaak AdminErrorHandlerServlet, wat die volgende doen:
- SessionUtilities.generateLicenseRequestToken(session)
- Redirects to vendor license server met 'n signed license request in bundle=<...>
- Die bundle kan offline ontsleutel word (hard-coded keys) om die GUID te herstel. Behou dieselfde session cookie en POST na /goanywhere/lic/accept/
met attacker-controlled bundle bytes, en bereik so die SignedObject sink pre-auth.
Bewys-van-bereikbaarheid (impact-loos) probe:
GET /goanywhere/license/Unlicensed.xhtml/x?javax.faces.ViewState=x&GARequestAction=activate HTTP/1.1
Host: <target>
- Unpatched: 302 Location header to https://my.goanywhere.com/lic/request?bundle=... en Set-Cookie: ASESSIONID=...
- Patched: redirect sonder bundle (geen token-generering).
Blue-team deteksie
Wysers in stack traces/logs dui sterk daarop dat daar pogings is om 'n SignedObject-gated sink te bereik:
java.io.ObjectInputStream.readObject
java.security.SignedObject.getObject
com.linoma.license.gen2.BundleWorker.verify
com.linoma.license.gen2.BundleWorker.unbundle
com.linoma.license.gen2.LicenseController.getResponse
com.linoma.license.gen2.LicenseAPI.getResponse
com.linoma.ga.ui.admin.servlet.LicenseResponseServlet.doPost
Verhardingsriglyne
- Handhaaf handtekeningverifikasie voor enige getObject() oproep en verseker dat die verifikasie die beoogde publieke sleutel/algoritme gebruik.
- Vervang direkte SignedObject.getObject() oproepe met 'n versterkte wrapper wat filterering weer op die binneste stroom toepas (bv. deserializeUntrustedSignedObject gebruik ValidatingObjectInputStream/ObjectInputFilter allow-lists).
- Verwyder foutbehandelingsvloei wat session-bound tokens aan nie-geauthentiseerde gebruikers uitreik. Beskou foutpaaie as attack surface.
- Verkies Java serialization filters (JEP 290) met streng allow-lists vir beide buitenste en binneste deserialisasies. Voorbeeld:
ObjectInputFilter filter = info -> {
Class<?> c = info.serialClass();
if (c == null) return ObjectInputFilter.Status.UNDECIDED;
if (c == java.security.SignedObject.class || c == byte[].class) return ObjectInputFilter.Status.ALLOWED;
return ObjectInputFilter.Status.REJECTED; // outer layer
};
ObjectInputFilter.Config.setSerialFilter(filter);
// For the inner object, apply a separate strict DTO allow-list
Voorbeeld aanvalsketting samevatting (CVE-2025-10035)
- Pre-auth token minting via foutbehandelaar:
GET /goanywhere/license/Unlicensed.xhtml/watchTowr?javax.faces.ViewState=watchTowr&GARequestAction=activate
Ontvang 302 met bundle=... en ASESSIONID=...; decrypt bundle offline om GUID te herstel.
- Bereik die sink pre-auth met dieselfde cookie:
POST /goanywhere/lic/accept/<GUID> HTTP/1.1
Cookie: ASESSIONID=<value>
Content-Type: application/x-www-form-urlencoded
bundle=<attacker-controlled-bytes>
- RCE vereis 'n korrek ondertekende SignedObject wat 'n gadget chain omsluit. Navorsers kon nie signature verification omseil nie; uitbuiting hang af van toegang tot 'n ooreenstemmende private key of 'n signing oracle.
Gefikseerde weergawes en gedragsveranderinge
- GoAnywhere MFT 7.8.4 en Sustain Release 7.6.3:
- Versterk inner deserialization deur SignedObject.getObject() te vervang met 'n wrapper (deserializeUntrustedSignedObject).
- Verwyder error-handler token generation, en sluit pre-auth reachability.
Aantekeninge oor JSF/ViewState
Die reachability-truuk benut 'n JSF-blad (.xhtml) en 'n ongeldig javax.faces.ViewState om na 'n bevoorregte error handler te roeteer. Alhoewel dit nie 'n JSF deserialization-kwessie is nie, is dit 'n herhalende pre-auth patroon: breek in error handlers wat bevoorregte aksies uitvoer en security-relevant session attributes stel.
References
- watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035
- Fortra advisory FI-2025-012 – Deserialization Vulnerability in GoAnywhere MFT's License Servlet
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.