izar / pytm

A Pythonic framework for threat modeling

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Threat Evaluation Improvements: Simplify conditions and first step toward detecting mitigations

nozmore opened this issue · comments

When using pytm to find threats I found most threats do not apply which would require me to re-write conditions to detect applicable components. Instead to address this I added a new condition to the threatlib called 'target_condition" to detect if the target is relevant for the Threat. For example using INP01 : Buffer Overflow via Environment Variables I have a target_condition of 'target.usesEnvironmentVariables' with the 'condition' of target.sanitizesInput is False and target.checksInputBounds is False another example would be applying SQLi to a Server or Process only if one of the outbound data flows as a sink of Database and isSQL = True.

This is basically what I was getting after with #14 although i described it differently.

To be able to see this in report and ensure the target conditions are valid I have taken a step towards detecting mitigations. When applying a threat I have created a ThreatResult class for invalid target, not applicable threats (target_condition = False), mitigated (target_condition == True and condition == False) and Valid. Added lists of Threats for na, mitigated threats in Element.

Things are mostly functional locally but still playing with a few things. I would like to get anyones thoughts as I continue with this.

But wouldn't that amount to having two different conditions, effectively? We already have one check for a target type ("things that only happen in servers") and then we should have the other constraints expressed in Threat.condition.
I am adding a field to the Finding object that shows the (hopefully, I am still toying with it) evaluated Threat.condition with values. The idea is that not only it clarifies where the finding came from but will enable the developer to go back to the model and add any attribute that is either missing or has a default value that led to a false positive. Would this help ameliorate the issue?

Ok "simplify" is arguable and maybe the wrong choice. To capture valid applicable threats target type isn't enough so currently for some threats the threat condition is both a target condition and weakness condition. In my mind breaking these up into separate condition fields simplifies the current usage. Also allows us to identify truly applicable threats where positive annotations prevented a Finding.

Playing devil's advocate here, can't the condition be written as an and between those two fields and go with a single field still, or would that lead to duplication of rules?

Of course it could be a single field since that is the way it works today, using my example of INP01 I did split up its AND condition using the 2 fields. Today if INP01 is not identified I don't know if it is because they did not annotate that they are using env vars or because they had indicated that they have sanitization or checkBounds.

I guess I'll need to see a full example. I keep thinking back to the quality of rules.

{ "SID":"INP05", "target":[ "Server", "Process" ], "target_condition":"any(d.sink.isSQL for d in target.outputs)", "description":"Command Line Execution through SQL Injection", "details":"An attacker uses standard SQL injection methods to inject data into the command line for execution. This could be done directly through misuse of directives such as MSSQL_xp_cmdshell or indirectly through injection of data into the database that would be interpreted as shell commands. Sometime later, an unscrupulous backend application (or could be part of the functionality of the same application) fetches the injected data stored in the database and uses this data as command line arguments without performing proper validation. The malicious data escapes that data plane by spawning new commands to be executed on the host.", "Likelihood Of Attack":"Low", "severity":"Very High", "condition":"target.validatesInput is False", "prerequisites":"The application does not properly validate data before storing in the databaseBackend application implicitly trusts the data stored in the databaseMalicious data is used on the backend as a command line argument", "mitigations":"Disable MSSQL xp_cmdshell directive on the databaseProperly validate the data (syntactically and semantically) before writing it to the database. Do not implicitly trust the data stored in the database. Re-validate it prior to usage to make sure that it is safe to use in a given context (e.g. as a command line argument).", "example":"SQL injection vulnerability in Cacti 0.8.6i and earlier, when register_argc_argv is enabled, allows remote attackers to execute arbitrary SQL commands via the (1) second or (2) third arguments to cmd.php. NOTE: this issue can be leveraged to execute arbitrary commands since the SQL query results are later used in the polling_items array and popen function", "references":"https://capec.mitre.org/data/definitions/108.html, http://cwe.mitre.org/data/definitions/89.html, http://cwe.mitre.org/data/definitions/74.html, http://cwe.mitre.org/data/definitions/20.html, http://cwe.mitre.org/data/definitions/78.html, http://cwe.mitre.org/data/definitions/114.html" }

NOZ04 doesn't currently work any(t.id == 'NOZ03' for t in target.mitigated_threats) yet because mitigations are saved to the element after parsing all elements/threats. I need save them while parsing the threats for this logic to work. That could be useful to have chained threats with different severities/threat conditions.

Thanks, that helps. So, I am still not sold on the need to make it into two separate conditions. I think the semantics of the thing is tripping me. Why do I need condition_1 = "foo is True" and condition_2 = "bar is True" instead of condition (foo is True and bar is True" ?
I'm afraid we would be adding complexity where it is not explicitly needed.
I get your example of why INP01 is not identified, but is that truly an issue? Do we need a complementary report of "here is why we think these threats are not present in your model" ?

If the complementary report could separate out 1. You are not doing a 'thing' and 2. You are doing a 'thing' and you are doing it correctly. You cannot do this without having 2 conditions. This was what I was going after. By adding this doesn't mean it must be used, some cases target_condition could be blank in that it impacts all of that type or for more complicated 'or' checks with multiple pairs of target condition and mitigating controls it may still need to be 1 condition or may need to be 2 threats.

For some simple threats this doesn't apply but if you look at the conditions for a portion of the lib there are positive checks mixed with negative checks so this is already happening but the user is forced to define as a single condition.

I'm warming up to the idea. @colesmj ?

I separated this comment out since the above is directly related to this change and below is more where my head was at, what I could see in the future and another reason why this would be needed.

--

If this were implemented future steps in my head would be to position condition to be mitigation condition and instead of being written as target.validatesInput is False would be target.validatesInput is True. I would probably then create an ordered list of mitigations under each threat with a condition, result, severity, guidance, etc.

Here is a basic example, don't get hung up on the exact condition logic below just the spirit of change for now and why separating out target condition from mitigating control conditions could make sense.

SQLi
-target = Process Server
-target condition = any sink is datastore and datastore isSQL
-mitigation
--m1
---condition = target.parameterizedQueries
---result = no finding
--m2
---condition = target.validatesInput
---result = finding
---guidance = Ensure all dynamic input used in a SQL query is validated prior to execution and validation logic prevents prevents malicious characters from being included.
--m3
---condition = target.sanitizesInput
---result = finding
---guidance = Ensure sanitization routine includes malicious characters which contribute to SQLi. Ensure underlying database respects sanitization and does not decode characters before execution.