def test_defaults(self): tm = TM("TM") user = Actor("User", data="HTTP") server = Server("Server", port=443, protocol="HTTPS", isEncrypted=True, data="JSON") db = Datastore( "PostgreSQL", isSQL=True, port=5432, protocol="PostgreSQL", isEncrypted=False, data="SQL resp", ) req_get = Dataflow(user, server, "HTTP GET") query = Dataflow(server, db, "Query", data="SQL") result = Dataflow(db, server, "Results", isResponse=True) resp_get = Dataflow(server, user, "HTTP Response", isResponse=True) req_post = Dataflow(user, server, "HTTP POST", data="JSON") resp_post = Dataflow(server, user, "HTTP Response", isResponse=True) tm.check() self.assertEqual(req_get.srcPort, -1) self.assertEqual(req_get.dstPort, server.port) self.assertEqual(req_get.isEncrypted, server.isEncrypted) self.assertEqual(req_get.protocol, server.protocol) self.assertEqual(req_get.data, user.data) self.assertEqual(query.srcPort, -1) self.assertEqual(query.dstPort, db.port) self.assertEqual(query.isEncrypted, db.isEncrypted) self.assertEqual(query.protocol, db.protocol) self.assertNotEqual(query.data, server.data) self.assertEqual(result.srcPort, db.port) self.assertEqual(result.dstPort, -1) self.assertEqual(result.isEncrypted, db.isEncrypted) self.assertEqual(result.protocol, db.protocol) self.assertEqual(result.data, db.data) self.assertEqual(resp_get.srcPort, server.port) self.assertEqual(resp_get.dstPort, -1) self.assertEqual(resp_get.isEncrypted, server.isEncrypted) self.assertEqual(resp_get.protocol, server.protocol) self.assertEqual(resp_get.data, server.data) self.assertEqual(req_post.srcPort, -1) self.assertEqual(req_post.dstPort, server.port) self.assertEqual(req_post.isEncrypted, server.isEncrypted) self.assertEqual(req_post.protocol, server.protocol) self.assertNotEqual(req_post.data, user.data) self.assertEqual(resp_post.srcPort, server.port) self.assertEqual(resp_post.dstPort, -1) self.assertEqual(resp_post.isEncrypted, server.isEncrypted) self.assertEqual(resp_post.protocol, server.protocol) self.assertEqual(resp_post.data, server.data)
def test_defaults(self): tm = TM("TM") user_data = Data("HTTP") user = Actor("User", data=user_data) user.controls.authenticatesDestination=True json_data = Data("JSON") server = Server( "Server", port=443, protocol="HTTPS", isEncrypted=True, data=json_data ) sql_resp = Data("SQL resp") db = Datastore( "PostgreSQL", port=5432, protocol="PostgreSQL", data=sql_resp, ) db.controls.isEncrypted=False db.type = DatastoreType.SQL worker = Process("Task queue worker") req_get_data = Data("HTTP GET") req_get = Dataflow(user, server, "HTTP GET", data=req_get_data) server_query_data = Data("SQL") server_query = Dataflow(server, db, "Query", data=server_query_data) result_data = Data("Results") result = Dataflow(db, server, "Results", data=result_data, isResponse=True) resp_get_data = Data("HTTP Response") resp_get = Dataflow(server, user, "HTTP Response", data=resp_get_data, isResponse=True) req_post_data = Data("JSON") req_post = Dataflow(user, server, "HTTP POST", data=req_post_data) resp_post = Dataflow(server, user, "HTTP Response", isResponse=True) sql_data = Data("SQL") worker_query = Dataflow(worker, db, "Query", data=sql_data) Dataflow(db, worker, "Results", isResponse=True) cookie = Data("Auth Cookie", carriedBy=[req_get, req_post]) self.assertTrue(tm.check()) self.assertEqual(req_get.srcPort, -1) self.assertEqual(req_get.dstPort, server.port) self.assertEqual(req_get.controls.isEncrypted, server.controls.isEncrypted) self.assertEqual( req_get.controls.authenticatesDestination, user.controls.authenticatesDestination ) self.assertEqual(req_get.protocol, server.protocol) self.assertTrue(user.data.issubset(req_get.data)) self.assertEqual(server_query.srcPort, -1) self.assertEqual(server_query.dstPort, db.port) self.assertEqual(server_query.controls.isEncrypted, db.controls.isEncrypted) self.assertEqual( server_query.controls.authenticatesDestination, server.controls.authenticatesDestination ) self.assertEqual(server_query.protocol, db.protocol) self.assertTrue(server.data.issubset(server_query.data)) self.assertEqual(result.srcPort, db.port) self.assertEqual(result.dstPort, -1) self.assertEqual(result.controls.isEncrypted, db.controls.isEncrypted) self.assertEqual(result.controls.authenticatesDestination, False) self.assertEqual(result.protocol, db.protocol) self.assertTrue(db.data.issubset(result.data)) self.assertEqual(resp_get.srcPort, server.port) self.assertEqual(resp_get.dstPort, -1) self.assertEqual(resp_get.controls.isEncrypted, server.controls.isEncrypted) self.assertEqual(resp_get.controls.authenticatesDestination, False) self.assertEqual(resp_get.protocol, server.protocol) self.assertTrue(server.data.issubset(resp_get.data)) self.assertEqual(req_post.srcPort, -1) self.assertEqual(req_post.dstPort, server.port) self.assertEqual(req_post.controls.isEncrypted, server.controls.isEncrypted) self.assertEqual( req_post.controls.authenticatesDestination, user.controls.authenticatesDestination ) self.assertEqual(req_post.protocol, server.protocol) self.assertTrue(user.data.issubset(req_post.data)) self.assertEqual(resp_post.srcPort, server.port) self.assertEqual(resp_post.dstPort, -1) self.assertEqual(resp_post.controls.isEncrypted, server.controls.isEncrypted) self.assertEqual(resp_post.controls.authenticatesDestination, False) self.assertEqual(resp_post.protocol, server.protocol) self.assertTrue(server.data.issubset(resp_post.data)) self.assertListEqual(server.inputs, [req_get, req_post]) self.assertListEqual(server.outputs, [server_query]) self.assertListEqual(worker.inputs, []) self.assertListEqual(worker.outputs, [worker_query]) self.assertListEqual(cookie.carriedBy, [req_get, req_post]) self.assertSetEqual(set(cookie.processedBy), set([user, server])) self.assertIn(cookie, req_get.data) self.assertSetEqual( set([d.name for d in req_post.data]), set([cookie.name, "HTTP", "JSON"]) )
# Servers eureka_service_discovery = Server("Eureka Service Discovery") nginx_backend_server = Server("Nginx Backend Reverse Proxy and Load Balancer") # Processes react_webapp = Process("Webserver - React Frontend") identity_service = Process("Flask Identity Service") image_service = Process("Flask Image Service") resources_service = Process("Flask Resouces Service") search_service = Process("Flask Search Service") elastic_search_resources = Process("Flask Elastic Search Resources") # Data Storages identity_db = Datastore("Identity - Mongo Atlas DB") token_blacklist_db = Datastore("Token Blacklist DB - Mongo Atlas DB") resources_db = Datastore("Resources - Mongo Atlas DB") s3_bucket = Datastore("AWS S3 Bucket - Persistent") # Monitoring kibana = Process("Kibana Visualising Dashboard") elastic_search_monitoring = Process("Elasticsearch Monitoring") logstash = Process("Logstash") heartbeat = Process("Heartbeat") apm_server = Process("Apm Server") # Boundraries hosted_services = Boundary("LetterApp DMZ") mongo_atlas = Boundary("Mongo Atlas Cluster") aws = Boundary("AWS VPC")
def test_defaults(self): tm = TM("TM") user = Actor("User", data="HTTP", authenticatesDestination=True) server = Server("Server", port=443, protocol="HTTPS", isEncrypted=True, data="JSON") db = Datastore( "PostgreSQL", isSQL=True, port=5432, protocol="PostgreSQL", isEncrypted=False, data="SQL resp", ) worker = Process("Task queue worker") req_get = Dataflow(user, server, "HTTP GET") server_query = Dataflow(server, db, "Query", data="SQL") result = Dataflow(db, server, "Results", isResponse=True) resp_get = Dataflow(server, user, "HTTP Response", isResponse=True) req_post = Dataflow(user, server, "HTTP POST", data="JSON") resp_post = Dataflow(server, user, "HTTP Response", isResponse=True) worker_query = Dataflow(worker, db, "Query", data="SQL") Dataflow(db, worker, "Results", isResponse=True) self.assertTrue(tm.check()) self.assertEqual(req_get.srcPort, -1) self.assertEqual(req_get.dstPort, server.port) self.assertEqual(req_get.isEncrypted, server.isEncrypted) self.assertEqual(req_get.authenticatesDestination, user.authenticatesDestination) self.assertEqual(req_get.protocol, server.protocol) self.assertEqual(req_get.data, user.data) self.assertEqual(server_query.srcPort, -1) self.assertEqual(server_query.dstPort, db.port) self.assertEqual(server_query.isEncrypted, db.isEncrypted) self.assertEqual(server_query.authenticatesDestination, server.authenticatesDestination) self.assertEqual(server_query.protocol, db.protocol) self.assertNotEqual(server_query.data, server.data) self.assertEqual(result.srcPort, db.port) self.assertEqual(result.dstPort, -1) self.assertEqual(result.isEncrypted, db.isEncrypted) self.assertEqual(result.authenticatesDestination, False) self.assertEqual(result.protocol, db.protocol) self.assertEqual(result.data, db.data) self.assertEqual(resp_get.srcPort, server.port) self.assertEqual(resp_get.dstPort, -1) self.assertEqual(resp_get.isEncrypted, server.isEncrypted) self.assertEqual(resp_get.authenticatesDestination, False) self.assertEqual(resp_get.protocol, server.protocol) self.assertEqual(resp_get.data, server.data) self.assertEqual(req_post.srcPort, -1) self.assertEqual(req_post.dstPort, server.port) self.assertEqual(req_post.isEncrypted, server.isEncrypted) self.assertEqual(req_post.authenticatesDestination, user.authenticatesDestination) self.assertEqual(req_post.protocol, server.protocol) self.assertNotEqual(req_post.data, user.data) self.assertEqual(resp_post.srcPort, server.port) self.assertEqual(resp_post.dstPort, -1) self.assertEqual(resp_post.isEncrypted, server.isEncrypted) self.assertEqual(resp_post.authenticatesDestination, False) self.assertEqual(resp_post.protocol, server.protocol) self.assertEqual(resp_post.data, server.data) self.assertListEqual(server.inputs, [req_get, req_post]) self.assertListEqual(server.outputs, [server_query]) self.assertListEqual(worker.inputs, []) self.assertListEqual(worker.outputs, [worker_query])
def test_defaults(self): internet = Boundary("Internet") cloud = Boundary("Cloud") user = Actor("User", inBoundary=internet) server = Server("Server") db = Datastore("DB", inBoundary=cloud) func = Datastore("Lambda function", inBoundary=cloud) request = Dataflow(user, server, "request") response = Dataflow(server, user, "response") user_query = Dataflow(user, db, "user query") server_query = Dataflow(server, db, "server query") func_query = Dataflow(func, db, "func query") default = { "SID": "", "description": "", "condition": "", "target": ["Actor", "Boundary", "Dataflow", "Datastore", "Server"], "details": "", "severity": "", "mitigations": "", "example": "", "references": "", } testCases = [ { "target": server, "condition": "target.oneOf(Server, Datastore)" }, { "target": server, "condition": "not target.oneOf(Actor, Dataflow)" }, { "target": request, "condition": "target.crosses(Boundary)" }, { "target": user_query, "condition": "target.crosses(Boundary)" }, { "target": server_query, "condition": "target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.enters(Boundary)" }, { "target": func_query, "condition": "not target.exits(Boundary)" }, { "target": request, "condition": "not target.enters(Boundary)" }, { "target": request, "condition": "target.exits(Boundary)" }, { "target": response, "condition": "target.enters(Boundary)" }, { "target": response, "condition": "not target.exits(Boundary)" }, { "target": user, "condition": "target.inside(Boundary)" }, ] for case in testCases: t = Threat({**default, **{"condition": case["condition"]}}) self.assertTrue( t.apply(case["target"]), "Failed to match {} against {}".format(case["target"], case["condition"]), )
market.inBoundary = internet alertApi = Server("Alert<br/>API-y") alertApi.inBoundary = internet authApi = Server("Auth<br/>API-y") authApi.inBoundary = internet allAuth = Server("All Auth") allAuth.inBoundary = internet phoneCloud = Server("Phone<br/>Provider<br/>Cloud") firensurfCloud = Server("Fire n' Surf .gov") dbB = Datastore("Oracle Table B") dbB.inBoundary = internet dbR = Datastore("Oracle Table R") dbR.inBoundary = internet dbT = Datastore("Oracle Table T") dbT.inBoundary = internet user_to_app = Dataflow(user, app, "use") app_to_buyapi = Dataflow(app, buyApi, "HTTPS<br/>JSON") app_to_phonecloud = Dataflow(app, phoneCloud, " ") app_to_rentapi = Dataflow(app, rentApi, "HTTPS<br/>JSON") app_to_authapi = Dataflow(app, authApi, "HTTPS<br/>JSON") app_to_dbt = Dataflow(authApi, dbT, "Token-y") allauth_to_dbt = Dataflow(allAuth, dbT, " ")
def test_defaults(self): tm = TM("my test tm", description="aa", isOrdered=True) internet = Boundary("Internet") cloud = Boundary("Cloud") user = Actor("User", inBoundary=internet) server = Server("Server") db = Datastore("DB", inBoundary=cloud, isSQL=True) func = Datastore("Lambda function", inBoundary=cloud) request = Dataflow(user, server, "request") response = Dataflow(server, user, "response", isResponse=True) user_query = Dataflow(user, db, "user query") server_query = Dataflow(server, db, "server query") func_query = Dataflow(func, db, "func query") default_target = [ "Actor", "Boundary", "Dataflow", "Datastore", "Server" ] testCases = [ { "target": server, "condition": "target.oneOf(Server, Datastore)" }, { "target": server, "condition": "not target.oneOf(Actor, Dataflow)" }, { "target": request, "condition": "target.crosses(Boundary)" }, { "target": user_query, "condition": "target.crosses(Boundary)" }, { "target": server_query, "condition": "target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.enters(Boundary)" }, { "target": func_query, "condition": "not target.exits(Boundary)" }, { "target": request, "condition": "not target.enters(Boundary)" }, { "target": request, "condition": "target.exits(Boundary)" }, { "target": response, "condition": "target.enters(Boundary)" }, { "target": response, "condition": "not target.exits(Boundary)" }, { "target": user, "condition": "target.inside(Boundary)" }, { "target": func, "condition": "not any(target.inputs)" }, { "target": server, "condition": "any(f.sink.oneOf(Datastore) and f.sink.isSQL " "for f in target.outputs)", }, ] self.assertTrue(tm.check()) for case in testCases: t = Threat(SID="", target=default_target, condition=case["condition"]) self.assertTrue( t.apply(case["target"]), "Failed to match {} against {}".format( case["target"], case["condition"], ), )
mcomps = Boundary("Master Control Components") worker = Boundary("Worker") contain = Boundary("Container") # Actors miu = Actor("Malicious Internal User") ia = Actor("Internal Attacker") ea = Actor("External Actor") admin = Actor("Administrator") dev = Actor("Developer") eu = Actor("End User") # Server & OS Components etcd = Datastore("N-ary etcd servers") apiserver = Server("kube-apiserver") kubelet = Server("kubelet") kubeproxy = Server("kube-proxy") scheduler = Server("kube-scheduler") controllers = Server("CCM/KCM") pods = Server("Pods") iptables = Process("iptables") # Component <> Boundary Relations etcd.inBoundary = mcdata mcdata.inBoundary = apisrv apiserver.inBoundary = apisrv kubelet.inBoundary = worker kubeproxy.inBoundary = worker pods.inBoundary = contain
from pytm.pytm import TM, Server, Datastore, Dataflow, Boundary, Actor tm = TM("my test tm") tm.description = "This is a sample threat model of a very simple system - a web-based comment system. The user enters comments and these are added to a database and displayed back to the user. The thought is that it is, though simple, a complete enough example to express meaningful threats." User_Web = Boundary("User/Web") Web_DB = Boundary("Web/DB") user = Actor("User") user.inBoundary = User_Web web = Server("Web Server") web.OS = "CloudOS" web.isHardened = True db = Datastore("SQL Database (*)") db.OS = "CentOS" db.isHardened = False db.inBoundary = Web_DB db.isSql = True db.inScope = False user_to_web = Dataflow(user, web, "User enters comments (*)") user_to_web.protocol = "HTTP" user_to_web.dstPort = 80 user_to_web.data = 'Comments in HTML or Markdown' user_to_web.order = 1 user_to_web.note = "This is a note\nmulti-line" web_to_user = Dataflow(web, user, "Comments saved (*)") web_to_user.protocol = "HTTP"
# Define components api_search = Server("api_search") api_search.inBoundary = API api_search.inScope = True api_search.providesConfidentiality = True api_reservation = Server("api_reservation") api_reservation.inBoundary = API api_reservation.inScope = True api_rating = Server("api_rating") api_rating.inBoundary = API api_rating.inScope = True db_search = Datastore("Restaurants") db_search.inBoundary = DB db_search.inScope = True db_search.authenticatesSource = True db_rating = Datastore("Ratings") db_rating.inBoundary = DB db_rating.inScope = False db_reservations = Datastore("Reservations") db_reservations.inBoundary = DB db_reservations.inScope = False # Define flows search_user_to_api = Dataflow(user, api_search, "User enters search") search_user_to_api.isEncrypted = True #JIRA TEST-0001
def test_defaults(self): internet = Boundary("Internet") cloud = Boundary("Cloud") user = Actor("User", inBoundary=internet) server = Server("Server") db = Datastore("DB", inBoundary=cloud) func = Datastore("Lambda function", inBoundary=cloud) request = Dataflow(user, server, "request") response = Dataflow(server, user, "response") user_query = Dataflow(user, db, "user query") server_query = Dataflow(server, db, "server query") func_query = Dataflow(func, db, "func query") default_target = [ "Actor", "Boundary", "Dataflow", "Datastore", "Server" ] testCases = [ { "target": server, "condition": "target.oneOf(Server, Datastore)" }, { "target": server, "condition": "not target.oneOf(Actor, Dataflow)" }, { "target": request, "condition": "target.crosses(Boundary)" }, { "target": user_query, "condition": "target.crosses(Boundary)" }, { "target": server_query, "condition": "target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.crosses(Boundary)" }, { "target": func_query, "condition": "not target.enters(Boundary)" }, { "target": func_query, "condition": "not target.exits(Boundary)" }, { "target": request, "condition": "not target.enters(Boundary)" }, { "target": request, "condition": "target.exits(Boundary)" }, { "target": response, "condition": "target.enters(Boundary)" }, { "target": response, "condition": "not target.exits(Boundary)" }, { "target": user, "condition": "target.inside(Boundary)" }, ] for case in testCases: t = Threat(SID="", target=default_target, condition=case["condition"]) self.assertTrue( t.apply(case["target"]), "Failed to match {} against {}".format(case["target"], case["condition"]), )
from pytm.pytm import TM, Boundary, Server, Actor, Datastore, Dataflow, SetOfProcesses tm = TM("Generic CMS example") tm.description = "This is a sample threat model for the Threat Model Cookbook." internet = Boundary("Internet") user = Actor("Generic/Privilege User") webserver = Server("Web Server") webserver.inBoundary = internet user_to_webserver = Dataflow(user, webserver, "HTTPS") db = Datastore("db") db.inBoundary = internet db_to_webserver = Dataflow(webserver, db, " ") adminuser = Actor(" admin ") admin_to_webserver = Dataflow(adminuser, db, "unsecure<br/>mysql<br/>connection") cdn = SetOfProcesses("CDN network") user_to_cdn = Dataflow(user, cdn, "HTTP") webserver_to_cdn = Dataflow(webserver, cdn, "Push to Bucket") tm.process()