Skip to content

Commit

Permalink
fix bandit warning about use of insecure hash functions by switching …
Browse files Browse the repository at this point in the history
…to an explicitly non-cryptographic hash since we don't need to use an expensive hash function in these places

>> Issue: [B303:blacklist] Use of insecure MD2, MD4, MD5, or SHA1 hash function.
   Severity: Medium   Confidence: High
   Location: guidedmodules/models.py:63
   Location: siteapp/models.py:179
   Location: siteapp/models.py:222
   Location: siteapp/views_landing.py:137
  • Loading branch information
JoshData committed Aug 30, 2018
1 parent 6bab3b4 commit eaa2a7c
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 26 deletions.
10 changes: 5 additions & 5 deletions guidedmodules/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ def get_description(self):
return "github.com/%s" % self.spec.get("repo")

def make_cache_stale_key(self):
import hashlib, json
h = hashlib.sha1()
h.update(json.dumps(self.spec).encode("utf8"))
h.update(self.updated.isoformat().encode("ascii"))
return h.hexdigest()
import pyhash, json
payload = b""
payload += json.dumps(self.spec).encode("utf8")
payload += self.updated.isoformat().encode("ascii")
return str(pyhash.spooky_128()(payload))

def open(self):
# Return an AppSourceConnection instance for this source.
Expand Down
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ PyGithub # LGPL License
GitPython # BSD License
Pygments==2.2.0 # BSD License
termcolor # MIT License
pyhash # Apache License 2.0

# Common Django Packages
Django<2.1 # BSD License
Expand Down
8 changes: 7 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ pygithub==1.40 \
pygments==2.2.0 \
--hash=sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d \
--hash=sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc
pyhash==0.9.1 \
--hash=sha256:1112816478addf69fbaf9cfcb70d8b12fa0165b588b8c38cad5561a3f7d8c6f9 \
--hash=sha256:1d895b630e59c1e48363d6d494e30ddc08466156f9f7cee8c0195e7db4bea412 \
--hash=sha256:2b07d60fad06603cfcc65afbb07624905f2c57abeb93857b2a7276c8a34e81e9 \
--hash=sha256:9dbdb65a151c56c83705beeeaff8b6443281bd4a688679b698a53b8b919ccc04 \
--hash=sha256:9f7b5992e5a3f5e86c38d7864b7576c504fc213e912a3bfda5eb23acd418fac8
pyjwt==1.6.4 \
--hash=sha256:30b1380ff43b55441283cc2b2676b755cca45693ae3097325dea01f3d110628c \
--hash=sha256:4ee413b357d53fd3fb44704577afac88e72e878716116270d722723d65b42176 \
Expand Down Expand Up @@ -313,7 +319,7 @@ termcolor==1.1.0 \
typing==3.6.6 \
--hash=sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d \
--hash=sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4 \
--hash=sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a
--hash=sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a \
# via fs
tzlocal==1.5.1 \
--hash=sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e \
Expand Down
31 changes: 17 additions & 14 deletions siteapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ def get_profile_picture_absolute_url(self):
# Because of invitations, profile photos are not protected by
# authorization. But to prevent user enumeration and to bust
# caches when photos change, we include in the URL some
# information about the internal data of the profile photo
# information about the internal data of the profile photo,
# which is checked in views_landing.py's user_profile_photo().
# Also since profile photos are per-Organization we have to
# include which org this User instance is localized to.

Expand All @@ -174,16 +175,19 @@ def get_profile_picture_absolute_url(self):
except:
return None

# We've got the content.
import hashlib
sha1 = hashlib.sha1()
sha1.update(pic['content_dataurl'].encode("ascii"))
fnhash = sha1.hexdigest()

# We've got the content. Make a fingerprint.
import pyhash, base64
payload = pic['content_dataurl']
fingerprint = base64.urlsafe_b64encode(
pyhash.spooky_128()(
payload
)
.to_bytes(128//8, byteorder='little')
).decode('ascii').rstrip("=")
return settings.SITE_ROOT_URL + "/media/users/%d/photo/%s/%s" % (
self.id,
self.user_settings_task.project.organization.subdomain,
fnhash
fingerprint
)

def render_context_dict(self, req_organization):
Expand Down Expand Up @@ -216,12 +220,11 @@ def render_context_dict(self, req_organization):

random_colors = ('#5cb85c', '#337ab7', '#AFB', '#ABF', '#FAB', '#FBA', '#BAF', '#BFA')
def get_avatar_fallback_css(self):
# Compute a hash over the user ID and username to generate
# a stable random number.
import hashlib
digest = hashlib.sha1()
digest.update(("%d|%s|" % (self.id, self.username)).encode("utf8"))
digest = digest.digest()
# Compute a non-cryptographic hash over the user ID and username to generate
# a stable set of random bytes to use to select CSS styles.
import pyhash
payload = "%d|%s|" % (self.id, self.username)
digest = pyhash.spooky_128()(payload).to_bytes(128//8, byteorder='big')

# Choose two colors at random using the bytes of the digest.
color1 = User.random_colors[digest[0] % len(User.random_colors)]
Expand Down
11 changes: 5 additions & 6 deletions siteapp/views_landing.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,11 @@ def user_profile_photo(request, user_id, org_subdomain, hash):
if not photo: raise Http404()
if not photo.answered_by_file.name: raise Http404()

# Check that the hash in the URL matches. See User.get_profile_picture_absolute_url.
import hashlib
sha1 = hashlib.sha1()
sha1.update(photo.get_value().get("content_dataurl").encode("ascii"))
fnhash = sha1.hexdigest()
if hash != fnhash: raise Http404()
# Check that the fingerprint in the URL matches. See User.get_profile_picture_absolute_url.
user.localize_to_org(org)
path_with_fingerprint = user.get_profile_picture_absolute_url()
if not path_with_fingerprint.endswith(request.path):
raise Http404()

# Get the dbstorage.models.StoredFile instance which holds
# an auto-detected mime type.
Expand Down

0 comments on commit eaa2a7c

Please sign in to comment.