Python: Add query for insecure SSH host key policies in Paramiko.

This commit is contained in:
Taus Brock-Nannestad
2019-03-18 16:45:54 +01:00
parent 285f8b06bd
commit 52278b25d9
8 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
In the Secure Shell (SSH) protocol, host keys are used to verify the identity of
remote hosts. Accepting unknown host keys may leave the connection open to
man-in-the-middle attacks.
</p>
</overview>
<recommendation>
<p>
Do not accept unknown host keys. For the Paramiko library in particular, avoid
setting the missing host key policy to either <code>AutoAddPolicy</code> or
<code>WarningPolicy</code>, as both of these will continue even when the host
key is unknown. The default <code>RejectPolicy</code> throws an exception when
unknown host keys are encountered.
</p>
</recommendation>
<example>
<p>
The following example opens a connection to <code>example.com</code> with the
missing host key policy set to <code>AutoAddPolicy</code>. If the host key
verification fails, the client will continue to interact with the server, even
though the connection may be compromised.
</p>
<sample src="examples/paramiko_host_key.py" />
</example>
<references>
<li>
Paramiko documentation: <a href="http://docs.paramiko.org/en/2.4/api/client.html?highlight=set_missing_host_key_policy#paramiko.client.SSHClient.set_missing_host_key_policy">set_missing_host_key_policy</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,32 @@
/**
* @name Accepting unknown host keys.
* @description Accepting unknown host keys can allow man-in-the-middle attacks.
* @kind problem
* @problem.severity error
* @precision high
* @id py/missing-host-key-validation
* @tags security
* external/cwe/cwe-295
*/
import python
private ModuleObject theParamikoClientModule() { result = ModuleObject::named("paramiko.client") }
private ClassObject theParamikoSSHClientClass() {
result = theParamikoClientModule().attr("SSHClient")
}
private ClassObject unsafe_paramiko_policy(string name) {
(name = "AutoAddPolicy" or name = "WarningPolicy") and
result = theParamikoClientModule().attr(name)
}
from CallNode call, string name
where
call = theParamikoSSHClientClass()
.declaredAttribute("set_missing_host_key_policy")
.(FunctionObject)
.getACall() and
call.getAnArg().refersTo(unsafe_paramiko_policy(name))
select call, "Setting missing host key policy to " + name + " may be unsafe."

View File

@@ -0,0 +1,9 @@
from paramiko.client import SSHClient, AutoAddPolicy
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy)
client.connect("example.com")
# ... interaction with server
client.close()

View File

@@ -0,0 +1,2 @@
| paramiko_host_key.py:5:1:5:49 | ControlFlowNode for Attribute() | Setting missing host key policy to AutoAddPolicy may be unsafe. |
| paramiko_host_key.py:7:1:7:49 | ControlFlowNode for Attribute() | Setting missing host key policy to WarningPolicy may be unsafe. |

View File

@@ -0,0 +1 @@
Security/CWE-295/MissingHostKeyValidation.ql

View File

@@ -0,0 +1,7 @@
from paramiko.client import AutoAddPolicy, WarningPolicy, RejectPolicy, SSHClient
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy) # bad
client.set_missing_host_key_policy(RejectPolicy) # good
client.set_missing_host_key_policy(WarningPolicy) # bad

View File

@@ -0,0 +1,15 @@
class SSHClient(object):
def __init__(self, *args, **kwargs):
pass
def set_missing_host_key_policy(self, *args, **kwargs):
pass
class AutoAddPolicy(object):
pass
class WarningPolicy(object):
pass
class RejectPolicy(object):
pass