Slide 1

Slide 1 text

Writing secure code in Python @yyyyyyyan_ Yan Orestes Software engineer PyCon APAC

Slide 2

Slide 2 text

“Programming in Python is easy”

Slide 3

Slide 3 text

Is programming in Python easy?

Slide 4

Slide 4 text

01. eval() is really dangerous

Slide 5

Slide 5 text

eval(expression[, globals[, locals]]) Evaluates a Python expression and return the result. Optional parameters: globals: dict locals: Any mapping object

Slide 6

Slide 6 text

The danger begins when… ⚠

Slide 7

Slide 7 text

What if we clean the global variables?

Slide 8

Slide 8 text

Python automatically inserts builtins… ⚠

Slide 9

Slide 9 text

What if we specifically clean the builtins?

Slide 10

Slide 10 text

Creating a payload

Slide 11

Slide 11 text

Creating a payload ⚠

Slide 12

Slide 12 text

eval() is really dangerous ❤ @SamuelAntilla / netsec.expert ⚠

Slide 13

Slide 13 text

Alternatives - ast.literal_eval(node_or_string) - String parsing

Slide 14

Slide 14 text

So when should we use eval()? When there is no other viable way to accomplish a task

Slide 15

Slide 15 text

So when should we use eval()? When there is no other viable way to accomplish a task (never)

Slide 16

Slide 16 text

02. arbitrary code execution with pickle

Slide 17

Slide 17 text

Serializes a Python object to a sequence of bytes. Optional parameters: protocol: int denoting the protocol used for the serialization. Currently goes from 0 (oldest) to 5 (Python 3.8) pickle.dump(obj, file, protocol=None, *) pickle.dumps(obj, protocol=None, *)

Slide 18

Slide 18 text

The magic method __reduce__() Used to customize how class instances are serialized. Should return a str or a tuple containing a callable and its parameters.

Slide 19

Slide 19 text

The magic method __reduce__() Used to customize how class instances are serialized. Should return a str or a tuple containing a callable and its parameters. ⚠

Slide 20

Slide 20 text

Opening the pickle jar with pickletools

Slide 21

Slide 21 text

But what about arbitrary code execution?

Slide 22

Slide 22 text

Serializing arbitrary code with marshal

Slide 23

Slide 23 text

And to run it? ⚠

Slide 24

Slide 24 text

Assembling the malicious pickle

Slide 25

Slide 25 text

Demo

Slide 26

Slide 26 text

Prevention pickle signing with HMAC Alternative Using a safer serialization format (JSON)

Slide 27

Slide 27 text

03. the power of pip install

Slide 28

Slide 28 text

What happens when we run pip install? 1. Identification of base requirements and given parameters 2. Resolution of dependencies and determination of what will be installed 3. Determination of installation method 4. Installation of packages

Slide 29

Slide 29 text

Determination of installation method If wheel is available: Download wheel and install from it; Else: Download package source code; If it's possible to build wheel from source code: Build wheel and install from it; Else: Install from setup.py;

Slide 30

Slide 30 text

setup.py - dynamic metadata

Slide 31

Slide 31 text

Arbitrary code execution in package installation

Slide 32

Slide 32 text

Demo

Slide 33

Slide 33 text

Real life risk Typosquatting

Slide 34

Slide 34 text

Real life risk --extra-index-url https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610

Slide 35

Slide 35 text

Prevention - --only-binary - --require-hashes - NEVER download a package as sudo/admin

Slide 36

Slide 36 text

Prevention - --only-binary - --require-hashes - NEVER download a package as sudo/admin

Slide 37

Slide 37 text

04. outdated dependencies

Slide 38

Slide 38 text

Vulnerabilities are found all the time!

Slide 39

Slide 39 text

Prevention - Keep up with the releases of packages we use - Keep up with the CVE vulnerabilities list (cve.mitre.org)

Slide 40

Slide 40 text

05. outdated python

Slide 41

Slide 41 text

Vulnerabilities are found all the time!

Slide 42

Slide 42 text

Understanding Python's versions status

Slide 43

Slide 43 text

Be cautious with deprecated functions!

Slide 44

Slide 44 text

06. the problem with pseudorandomness

Slide 45

Slide 45 text

How not to generate secure passwords

Slide 46

Slide 46 text

The random module and the infamous seed

Slide 47

Slide 47 text

Alternatives - The secrets module - os.urandom() - random.SystemRandom

Slide 48

Slide 48 text

07. watch out for bomb files

Slide 49

Slide 49 text

Billion laughs attack

Slide 50

Slide 50 text

Prevention

Slide 51

Slide 51 text

Tarbombs and path traversal

Slide 52

Slide 52 text

Prevention Don't use extractall() without prior inspection of the files!

Slide 53

Slide 53 text

08. assert is for debug!

Slide 54

Slide 54 text

What is the purpose of assert?

Slide 55

Slide 55 text

Saving a line with assert?

Slide 56

Slide 56 text

Are not equivalent Are equivalent

Slide 57

Slide 57 text

The __debug__ constant and the -O flag

Slide 58

Slide 58 text

Auditing our code

Slide 59

Slide 59 text

Lots of options! ● Codacy (free for open source projects) ● Horusec (open source) ● Pyre/Pysa (open source) ● Coverity Scan (exclusive for open source projects) ● Bandit (open source)

Slide 60

Slide 60 text

Using bandit

Slide 61

Slide 61 text

key points to never forget

Slide 62

Slide 62 text

01. never trust user input

Slide 63

Slide 63 text

02. avoid running Python code as sudo/admin

Slide 64

Slide 64 text

03. keep your system up-to-date

Slide 65

Slide 65 text

04. read the docs

Slide 66

Slide 66 text

04. read the docs

Slide 67

Slide 67 text

05. use static code analysis tools

Slide 68

Slide 68 text

Thank you! Twitter: @yyyyyyyan_ GitHub: @yyyyyyyan LinkedIn: /in/yyyyyyyan [email protected] | [email protected] PyCon APAC