You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-j request.json --function system -p "bash -c 'id'"
76
76
```
77
77
78
78
The tool parses the captured snapshot, injects the gadget tuples, recomputes the checksum, and prints a ready-to-send `/livewire/update` payload.
79
79
80
80
## CVE-2025-54068 – RCE without `APP_KEY`
81
81
82
+
According to the vendor advisory, the issue affects Livewire v3 (>= 3.0.0-beta.1 and < 3.6.3) and is unique to v3.
83
+
82
84
`updates` are merged into component state **after** the snapshot checksum is validated. If a property inside the snapshot is (or becomes) a synthetic tuple, Livewire reuses its meta while hydrating the attacker-controlled update value:
83
85
84
86
```php
@@ -95,6 +97,21 @@ Exploit recipe:
95
97
96
98
1. Find a Livewire component with an untyped public property (e.g., `public $count;`).
97
99
2. Send an update that sets that property to `[]`. The next snapshot now stores it as `[[], {"s": "arr"}]`.
100
+
101
+
A minimal type-juggling flow looks like this:
102
+
103
+
```http
104
+
POST /livewire/update
105
+
...
106
+
"updates": {"count": []}
107
+
```
108
+
109
+
Then the next snapshot stores a tuple that keeps the `arr` synthesizer metadata:
110
+
111
+
```json
112
+
"count": [[], {"s": "arr"}]
113
+
```
114
+
98
115
3. Craft another `updates` payload where that property contains a deeply nested array embedding tuples such as `[ <payload>, {"s":"clctn","class":"GuzzleHttp\\Psr7\\FnStream"} ]`.
99
116
4. During recursion, `hydrate()` evaluates each nested child independently, so attacker-chosen synth keys/classes are honoured even though the outer tuple and checksum never changed.
100
117
5. Reuse the same `CollectionSynth`/`FormObjectSynth` primitives to instantiate a Queueable gadget whose `$chained[0]` contains the phpggc payload. Livewire processes the forged updates, invokes `dispatchNextJobInChain()`, and reaches `system(<cmd>)` without knowing `APP_KEY`.
@@ -112,6 +129,7 @@ Key reasons this works:
112
129
- Fingerprints the deployed Livewire version by parsing `<script src="/livewire/livewire.js?id=HASH">` and mapping the hash to vulnerable releases.
113
130
- Collects baseline snapshots by replaying benign actions and extracting `components[].snapshot`.
114
131
- Generates either an `updates`-only payload (CVE-2025-54068) or a forged snapshot (known APP_KEY) embedding the phpggc chain.
132
+
- If no object-typed parameter is found in a snapshot, Livepyre falls back to brute-forcing candidate params to reach a coercible property.
0 commit comments