summaryrefslogtreecommitdiff
path: root/tools/pyboard.py
diff options
context:
space:
mode:
authorMichael Buesch <m@bues.ch>2020-08-12 21:30:33 +0200
committerDamien George <damien@micropython.org>2020-08-21 16:08:03 +1000
commit60cf2c0959ed2668c01df664a2e7c3cd1f5c6d89 (patch)
treeee4797c79692f2171f63e9a04b638c4676994851 /tools/pyboard.py
parent8727c4e2eca9026494c173061c5905d54fa5f73d (diff)
tools/pyboard.py: Replace eval() of received data with alternative.
Prior to this commit, pyboard.py used eval() to "parse" file data received from the board. Using eval() on received data from a device is dangerous, because a malicious device may inject arbitrary code execution on the PC that is doing the operation. Consider the following scenario: Eve may write a malicious script to Bob's board in his absence. On return Bob notices that something is wrong with the board, because it doesn't work as expected anymore. He wants to read out boot.py (or any other file) to see what is wrong. What he gets is a remote code execution on his PC. Proof of concept: Eve: $ cat boot.py _print = print print = lambda *x, **y: _print("os.system('ls /; echo Pwned!')", end="\r\n\x04") $ ./pyboard.py -f cp boot.py : cp boot.py :boot.py Bob: $ ./pyboard.py -f cp :boot.py /tmp/foo cp :boot.py /tmp/foo bin chroot dev home lib32 media opt root sbin sys usr boot config etc lib lib64 mnt proc run srv tmp var Pwned! There's also the possibility that the device is malfunctioning and sends random and possibly dangerous data back to the PC, to be eval'd. Fix this problem by using ast.literal_eval() to parse the received bytes, instead of eval(). Signed-off-by: Michael Buesch <m@bues.ch>
Diffstat (limited to 'tools/pyboard.py')
-rwxr-xr-xtools/pyboard.py8
1 files changed, 7 insertions, 1 deletions
diff --git a/tools/pyboard.py b/tools/pyboard.py
index 6376b13c7..c97ddbe48 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -70,6 +70,7 @@ Or:
import sys
import time
import os
+import ast
try:
stdout = sys.stdout.buffer
@@ -426,7 +427,12 @@ class Pyboard:
data = bytearray()
self.exec_("print(r(%u))" % chunk_size, data_consumer=lambda d: data.extend(d))
assert data.endswith(b"\r\n\x04")
- data = eval(str(data[:-3], "ascii"))
+ try:
+ data = ast.literal_eval(str(data[:-3], "ascii"))
+ if not isinstance(data, bytes):
+ raise ValueError("Not bytes")
+ except (UnicodeError, ValueError) as e:
+ raise PyboardError("fs_get: Could not interpret received data: %s" % str(e))
if not data:
break
f.write(data)