Threatspec is a tool for code-driven threat modeling. It allows threat models to be codified alongside software as it is developed. This enables the threats to evolve organically in the software development lifecycle. In this talk we will present Threatspec and show how it can be applied to Let’s Encrypt.
4. 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
5. 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
6. 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
8. Pain Points
● Model can become out of sync with implementation
● Threat modeling isn’t continuous
● Additional documentation needs to be maintained
9. 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
11. ThreatSpec
● R-Spec for Threat Modeling
● Add threat model context to code
● Generate reports dynamically
● Security, QA, Developers etc
working closely together (peer
review)
12. 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
13. 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 ???
14. 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
16. Let’s Encrypt Threat Model
● Code base and protocol overview
● Our task (read it, understand it, try to model it)
17. Snippets from Let’s Encrypt
acme/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'
18. Unchecked Deserialization
acme/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
19. JWK Loading Concerns
acme/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>
20. Key Leakage
acme/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))
21. 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
22. 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
23. 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