From aaddccfdb158351705596a6c90622e6d84819ad4 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 11 Aug 2014 17:50:56 -0700 Subject: [PATCH 1/2] webconfig: Use a constant-time token comparison This prevents a linear-time attack to recover the auth token. --- share/tools/web_config/webconfig.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/share/tools/web_config/webconfig.py b/share/tools/web_config/webconfig.py index 55ab372ef..8ba99bab6 100755 --- a/share/tools/web_config/webconfig.py +++ b/share/tools/web_config/webconfig.py @@ -680,6 +680,14 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): result.extend([r for r in sample_results if r]) return result + def secure_startswith(self, haystack, needle): + if len(haystack) < len(needle): + return False + bits = 0 + for x,y in zip(haystack, needle): + bits |= ord(x) ^ ord(y) + return bits == 0 + def font_size_for_ansi_prompt(self, prompt_demo_ansi): width = ansi_prompt_line_width(prompt_demo_ansi) # Pick a font size @@ -697,7 +705,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): p = self.path authpath = '/' + authkey - if p.startswith(authpath): + if self.secure_startswith(p, authpath): p = p[len(authpath):] else: return self.send_error(403) @@ -736,7 +744,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): p = self.path authpath = '/' + authkey - if p.startswith(authpath): + if self.secure_startswith(p, authpath): p = p[len(authpath):] else: return self.send_error(403) From 9079ec459cfecea2b1c31e806e2893d7801eed3a Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 11 Aug 2014 17:51:27 -0700 Subject: [PATCH 2/2] webconfig: fixes for token security * Use 16-byte tokens * Use os.urandom (random.getrandbits shouldn't be used for security) * Convert to hex correctly --- share/tools/web_config/webconfig.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/tools/web_config/webconfig.py b/share/tools/web_config/webconfig.py index 8ba99bab6..9e0b9ac00 100755 --- a/share/tools/web_config/webconfig.py +++ b/share/tools/web_config/webconfig.py @@ -26,7 +26,7 @@ if term: os.environ['TERM'] = term import subprocess -import re, socket, cgi, select, time, glob, random, string +import re, socket, cgi, select, time, glob, random, string, binascii try: import json except ImportError: @@ -859,7 +859,7 @@ where = os.path.dirname(sys.argv[0]) os.chdir(where) # Generate a 16-byte random key as a hexadecimal string -authkey = hex(random.getrandbits(16*4))[2:] +authkey = binascii.b2a_hex(os.urandom(16)) # Try to find a suitable port PORT = 8000