Slide 1

Slide 1 text

Finding Vulnerabilities with Bandit Kevin London www.kevinlondon.com @kevin_london

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Two kinds of big companies:

Slide 4

Slide 4 text

Two kinds of big companies: 1. Those that have been hacked

Slide 5

Slide 5 text

Two kinds of big companies: 1. Those that have been hacked 2. Those who don’t know they have been hacked

Slide 6

Slide 6 text

Companies hacked in 2015 (so far)

Slide 7

Slide 7 text

22 million people
 5 million fingerprints

Slide 8

Slide 8 text

30 million men 10 thousand women

Slide 9

Slide 9 text

300K tax accounts

Slide 10

Slide 10 text

300K tax accounts

Slide 11

Slide 11 text

1.4 million Jeeps

Slide 12

Slide 12 text

80 million people

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Security is hard.

Slide 15

Slide 15 text

“That will never happen to me.”

Slide 16

Slide 16 text

Let’s talk about Bandit.

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Bandit is an open-source security linter.

Slide 19

Slide 19 text

Created by

Slide 20

Slide 20 text

How to install:

Slide 21

Slide 21 text

How to run:

Slide 22

Slide 22 text

I did an experiment.

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

Experiment Notes

Slide 25

Slide 25 text

Experiment Notes I scanned 16 open-source Python projects with Bandit.

Slide 26

Slide 26 text

Experiment Notes 11 had potential security issues.

Slide 27

Slide 27 text

Experiment Notes 9 fixes / pull requests 6 issues raised

Slide 28

Slide 28 text

Experiment Notes Identifying details have been removed to protect the innocent.

Slide 29

Slide 29 text

Issues found:

Slide 30

Slide 30 text

Assertions

Slide 31

Slide 31 text

70 @percent.setter 71 def percent(self, value): 72 assert value >= 0 73 assert value <= 100 Assertions

Slide 32

Slide 32 text

>> Issue: Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. 70 @percent.setter 71 def percent(self, value): 72 assert value >= 0 73 assert value <= 100 Assertions

Slide 33

Slide 33 text

Opening URLs

Slide 34

Slide 34 text

165 try: 166 conn = urllib2.urlopen(request) Opening URLs

Slide 35

Slide 35 text

>> Issue: Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. 165 try: 166 conn = urllib2.urlopen(request) Opening URLs

Slide 36

Slide 36 text

Requests

Slide 37

Slide 37 text

206 resp = requests.get(uri, verify=False) Requests

Slide 38

Slide 38 text

>> Issue: Requests call with verify=False disabling SSL certificate checks, security issue. 206 resp = requests.get(uri, verify=False) Requests

Slide 39

Slide 39 text

Shell Commands

Slide 40

Slide 40 text

87 # Create ECC privatekey 88 proc = subprocess.Popen( 89 “openssl -genkey -out %s" % key_path, 90 shell=True, 91 ) Shell Commands

Slide 41

Slide 41 text

>> Issue: subprocess call with shell=True identified, security issue. 87 # Create ECC privatekey 88 proc = subprocess.Popen( 89 “openssl -genkey -out %s" % key_path, 90 shell=True, 91 ) Shell Commands

Slide 42

Slide 42 text

Temporary Files

Slide 43

Slide 43 text

291 listpath = tempfile.mktemp(“.tmp") Temporary Files

Slide 44

Slide 44 text

>> Issue: Use of insecure and deprecated function (mktemp). 291 listpath = tempfile.mktemp(“.tmp") Temporary Files

Slide 45

Slide 45 text

Loading XML

Slide 46

Slide 46 text

47 root = ElementTree.fromstring(content) Loading XML

Slide 47

Slide 47 text

>> Issue: Using ElementTree.fromstring to parse untrusted XML data is known to be vulnerable to XML attacks. Replace with its defusedxml equivalent function. 47 root = ElementTree.fromstring(content) Loading XML

Slide 48

Slide 48 text

&lol4; Loading XML Billion Laughs Attack

Slide 49

Slide 49 text

Deserializing

Slide 50

Slide 50 text

446 yamlFile = open(yamlPath) 447 regexes = yaml.load(yamlFile) Deserializing

Slide 51

Slide 51 text

>> Issue: Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load(). 446 yamlFile = open(yamlPath) 447 regexes = yaml.load(yamlFile) Deserializing

Slide 52

Slide 52 text

Deserializing

Slide 53

Slide 53 text

Deserializing 42 def loads(self, value): 43 return pickle.loads(value)

Slide 54

Slide 54 text

Deserializing >> Issue: Pickle library appears to be in use, possible security issue. 42 def loads(self, value): 43 return pickle.loads(value)

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

Deserializing

Slide 58

Slide 58 text

Deserializing 89 def unpack_db_value(self, val): 92 return marshal.loads(val)

Slide 59

Slide 59 text

Deserializing >> Issue: Deserialization with the marshal module is possibly dangerous. 89 def unpack_db_value(self, val): 92 return marshal.loads(val)

Slide 60

Slide 60 text

Everyone makes mistakes.

Slide 61

Slide 61 text

Security Recommendations

Slide 62

Slide 62 text

Keep it simple.

Slide 63

Slide 63 text

Don’t give up.

Slide 64

Slide 64 text

Look for security flaws during code reviews.

Slide 65

Slide 65 text

Use Bandit to check your third-party libraries.

Slide 66

Slide 66 text

Use Bandit to participate in open-source.

Slide 67

Slide 67 text

Use Bandit in your CI pipeline.

Slide 68

Slide 68 text

Use Bandit to improve your projects.

Slide 69

Slide 69 text

Bandit https://github.com/openstack/bandit Kevin London www.kevinlondon.com @kevin_london Slides http://bit.ly/python-bandit