23
Let’s Check Let’s Encrypt Fraser Scott Christopher A. Wood* *Caveat: I don't work in InfoSec

Let’s Check Let’s Encrypt: A Tool for Code-Driven Threat Modeling

Embed Size (px)

Citation preview

Let’s Check Let’s Encrypt

Fraser ScottChristopher A. Wood*

*Caveat: I don't work in InfoSec

Agenda● Threat modeling overview

○ Objectives○ Difficulties and pain points in practice

● Inside-out vs outside-in● ThreatSpec overview● Examples● Let’s Encrypt threat model● Lessons learned● Going Forward

Getting Started

Threat Modeling● Systematic identification of threats, actions, and mitigation strategies

○ What are you building?○ What can go wrong?○ What should you do about things that can go wrong?○ Are you doing a good job?

● STRIDE● DREAD

Threat Modeling● Systematic identification of threats, actions, and mitigation strategies

○ What are you building?○ What can go wrong?○ What should you do about things that can go wrong?○ Are you doing a good job?

● STRIDE● DREAD

Threat Modeling● Systematic identification of threats, actions, and mitigation strategies

○ What are you building?○ What can go wrong?○ What should you do about things that can go wrong?○ Are you doing a good job?

● STRIDE● DREAD

Go read Threat Modeling: Designing for Security by Adam Shostack

Objectives● Build secure products and services● Secure by design rather than bolting on controls

Pain Points● Model can become out of sync with implementation● Threat modeling isn’t continuous● Additional documentation needs to be maintained

Inside-out vs Outside-in● The threat model generally works from the outside in (towards the assets)

○ This helps reduce redundant or unnecessary work internally○ If an asset is never exposed, do you need to include it in the model?○ Only model what's actually in play

● We advocate working from the inside out○ Assets (code) are modeled directly○ Models are joined and merged to form larger models for a system○ The full picture emerges organically

ThreatSpec: Code-Driven Threat Modeling

ThreatSpec● R-Spec for Threat Modeling● Add threat model context to code● Generate reports dynamically● Security, QA, Developers etc

working closely together (peer review)

Some Vocabulary● Component - Individual part of the system● Boundary - Separation of trust● Threat - The thing that could go wrong● Mitigation - Fixing or working around the threat● Exposure - Not fixing the threat● Acceptance - Accepting the risk of the threat

Grammar Overview@alias boundary|component|threat ID to NAME

@describe boundary|component|threat ID as DESCRIPTION

@mitigates BOUNDARY:COMPONENT against THREAT with MITIGATION [(REFERENCES)]

@exposes BOUNDARY:COMPONENT to THREAT with EXPOSURE [(REFERENCES)]

@transfers THREAT to BOUNDARY:COMPONENT with TRANSFER [(REFERENCES)]

@accepts THREAT to BOUNDARY:COMPONENT with ACCEPTANCE [(REFERENCES)]

@review ???

Example code@mitigates @webapp:FileSystem against unauthorised access with strict file permissions (#122)

@exposes @webapp:App to XSS with insufficient input validation (#124,#133)

@transfers @cwe_319_cleartext_transmission to User:Browser with non-sensitive information (#125)

@accepts arbitrary file writes to @webapp:FileSystem with filename restrictions (#106)

from threatspec.org

Example report

Let’s Encrypt Threat Model● Code base and protocol overview● Our task (read it, understand it, try to model it)

Snippets from Let’s Encryptacme/clent.py

# @mitigates @acme:@client against @cwe_693_protection_mechanism_failure with loads better library if old python version detected

if sys.version_info < (2, 7, 9): # pragma: no cover

requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3()

acme/clent.py

"""

@transfers @cwe_320_key_management_errors to @app:@caller with no key validation or checks carried out

@mitigates @acme:@client against @cwe_295_improper_certificate_validation with verifies SSL by default

@review alg makes sense? RS256?

"""

DER_CONTENT_TYPE = 'application/pkix-cert'

Unchecked Deserializationacme/messages.py

def __init__(self, jobj):

"""

@exposes @acme:@directory to @cwe_36_absolute_path_traversal with possible relative URLs

@exposes @acme:@directory to @cwe_502_deserialization_of_untrusted_data with deserialization of \

data that's not defined in the ACME spec

"""

canon_jobj = util.map_keys(jobj, self._canon_key)

if not set(canon_jobj).issubset(self._REGISTERED_TYPES):

# TODO: acme-spec is not clear about this: 'It is a JSON

# dictionary, whose keys are the "resource" values listed

# in {{https-requests}}'z

raise ValueError('Wrong directory fields')

# TODO: check that everything is an absolute URL; acme-spec is

# not clear on that

self._jobj = canon_jobj

JWK Loading Concernsacme/jose/jwk.py

@classmethod

def load(cls, data, password=None, backend=None):

"""Load serialized key as JWK.

<snip>

@review So if this fails to load asymmetric keys, it assumes use of \

symmetric and loads that instead? Sounds a bit surprising. If the \

key was corrupted, it could contain something relatively predictable \

that might end up be used as a symmetric key without the user noticing

"""

try:

key = cls._load_cryptography_key(data, password, backend)

except errors.Error as error:

logger.debug('Loading symmetric key, asymmetric failed: %s', error)

return JWKOct(key=data)

<snip>

Key Leakageacme/jose/jwk.py

def fields_to_partial_json(self):

"""

@exposes @acme:@client to @cwe_320_key_management_errors by leaking private key material in JSON structure

"""

if isinstance(self.key._wrapped, rsa.RSAPublicKey):

<snip>

else: # rsa.RSAPrivateKey

private = self.key.private_numbers()

public = self.key.public_key().public_numbers()

params = {

'n': public.n,

'e': public.e,

'd': private.d,

'p': private.p,

<snip>

}

return dict((key, self._encode_param(value))

for key, value in six.iteritems(params))

Notable Outcomes● Identified some possible problems with the code (need to check with LE

folks)● Transfers are pretty common - libraries don’t always check stuff● ThreatSpec could aid general code review

Lessons Learned● Up-front investment is steep● Continual maintenance is easy (with educated developers)● ThreatSpec needs more work (e.g. @review tag, grammatical tweaks,

languages)● Dynamic DFDs from call-graphs would have been very helpful

Going Forward● Make the threat model an artifact of assets -- code!● Allow models to be generated inside-out and merged across projects,

teams, and within an enterprise● Let the treat model grow organically along with the code● Generate dynamic DFDs using call-graphs● Test in real systems and in real teams● Experiment with developers

ThreatSpec.org

@ThreatSpec