Back to scan results
Check 31 of 45

Insecure Deserialization

We inspect public page attributes for serialized-looking values, then send only truncated, non-executable format markers through a small set of common GET parameters. New deserializer-specific errors are reported as potential sinks that need manual validation.

What this check probes

The passive stage examines HTML value and href attributes for signatures associated with Java object streams, .NET BinaryFormatter, PHP object serialization, Python pickle, Ruby Marshal, and serialized Node functions.

The active stage tests the common parameter names data, object, state, and payload. Each receives a deliberately incomplete Java, .NET, PHP, Python, or Ruby format marker. A warning requires a new format-specific parsing error or a new server error that was not present with the harmless baseline value. An ordinary HTTP 200 response is not a finding.

ASP.NET ViewState is recorded separately. ViewState is normal framework state and its presence alone is not a vulnerability, so this check does not modify __VIEWSTATE or attempt to bypass its message authentication.

No complete serialized object, gadget chain, executable function, command, callback, local-file reference, or denial-of-service payload is used. POST bodies, cookies, authenticated or unlinked endpoints, uploads, and message queues remain outside this public scan.

Why this matters for PCI DSS

Deserializing attacker-controlled object graphs can lead to remote code execution, authentication bypass, privilege changes, data tampering, or denial of service. Those outcomes can directly affect systems that store, process, or transmit cardholder data.

PCI DSS secure-development practices require applications to treat external data as untrusted, use safe data formats, constrain inputs, and remove known-vulnerable implementation patterns. A pass here covers only the public, unauthenticated GET surface tested by this scanner.

How to fix it

Do not use BinaryFormatter or another native object-graph deserializer on untrusted input. Replace it with a simple, typed data contract. This .NET Framework-compatible example accepts JSON into a DTO with no runtime type metadata:

[DataContract]
public sealed class CartUpdate
{
    [DataMember]
    public string CartId { get; set; }
}

var serializer = new DataContractJsonSerializer(typeof(CartUpdate));
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
    var update = (CartUpdate)serializer.ReadObject(stream);
}

Allowlist fields and values after parsing, enforce small request and object limits, reject unexpected content types, and keep serialization libraries patched. If Newtonsoft.Json is used, keep TypeNameHandling.None and do not allow clients to select .NET types.

For ASP.NET Web Forms, never disable the ViewState MAC. Use stable protected machine keys across a server farm and set ViewStateUserKey where per-user binding is appropriate. Do not treat encryption as a replacement for integrity.

Apply the same rule across platforms: use typed message schemas instead of Java native serialization, PHP unserialize, Python pickle, Ruby Marshal.load, or function-capable Node serializers for untrusted data. Log and reject format errors without returning stack traces or class names.

Fixed it? Re-run the scan to confirm.

Run scan again