Prevent arbitrary class instantiation from SOAP fault exceptionName

An inbound SOAP <Fault> whose <detail> carries an <exceptionName> element
caused the fault deserializer to load the named class and invoke its
constructor with attacker-controlled data before any type check, running
the resulting ClassCastException into a silent catch. With a suitable
gadget on the classpath (e.g. Spring's ClassPathXmlApplicationContext,
the CVE-2023-46604 gadget) this is an unauthenticated remote
class-instantiation / RCE, reachable pre-authentication because the
engine force-parses the request body during service dispatch.

Harden the fault path:
- SOAPFaultDetailsBuilder.setValue loads the <exceptionName> class without
  initializing it (no static initializer runs) and only accepts it if it
  is an org.apache.axis.AxisFault subtype.
- SOAPFaultBuilder.createFault gates the reflective constructor branch on
  AxisFault assignability, so a non-fault class is never constructed.
- ClassUtils.forName now honors a non-initializing load; the existing
  three-arg overload previously ignored its init flag (all callers passed
  true, so behavior is unchanged for them).

Legitimate custom-fault deserialization (real AxisFault subtypes) still
works. Adds a regression test that fails against the vulnerable code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6 files changed