Python : Improve the PAM authentication bypass query

The current PAM auth bypass query which was contributed by me a few months back, alert on a vulenrable function but does not check if the function is actually function. This leads to a lot of fasle positives.

With this PR, I add a taint-tracking configuration to check if the username parameter can actually be supplied by an attacker.

This should bring the FP's significantly down.
This commit is contained in:
Porcupiney Hairs
2022-10-03 02:31:43 +05:30
committed by porcupineyhairs
parent a964325724
commit db231a111c
7 changed files with 158 additions and 27 deletions

View File

@@ -1 +1,10 @@
| pam_test.py:48:18:48:44 | ControlFlowNode for pam_authenticate() | This PAM authentication call may lead to an authorization bypass, since 'pam_acct_mgmt' is not called afterwards. |
edges
| pam_test.py:70:16:70:22 | ControlFlowNode for request | pam_test.py:70:16:70:27 | ControlFlowNode for Attribute |
| pam_test.py:70:16:70:27 | ControlFlowNode for Attribute | pam_test.py:75:14:75:40 | ControlFlowNode for pam_authenticate() |
nodes
| pam_test.py:70:16:70:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| pam_test.py:70:16:70:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| pam_test.py:75:14:75:40 | ControlFlowNode for pam_authenticate() | semmle.label | ControlFlowNode for pam_authenticate() |
subpaths
#select
| pam_test.py:75:14:75:40 | ControlFlowNode for pam_authenticate() | pam_test.py:70:16:70:22 | ControlFlowNode for request | pam_test.py:75:14:75:40 | ControlFlowNode for pam_authenticate() | This PAM authentication call may lead to an authorization bypass, since `pam_acct_mgmt` is not called afterwards. |

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=2 -p ../lib

View File

@@ -1,6 +1,7 @@
from ctypes import CDLL, POINTER, Structure, byref
from ctypes import c_char_p, c_int
from ctypes.util import find_library
from flask import Flask, request, redirect
class PamHandle(Structure):
@@ -40,11 +41,11 @@ pam_acct_mgmt.argtypes = [PamHandle, c_int]
class pam():
def authenticate_bad(self, username, service='login'):
def authenticate_bad_but_good(self, username, service='login'):
handle = PamHandle()
conv = PamConv(None, 0)
retval = pam_start(service, username, byref(conv), byref(handle))
# This is not fine but we don't alert here as there is a possibility that the function is not actually used
retval = pam_authenticate(handle, 0)
auth_success = retval == 0
@@ -61,3 +62,31 @@ class pam():
auth_success = retval == 0
return auth_success
app = Flask(__name__)
@app.route('/bad')
def bad():
username = request.args.get('username', '')
handle = PamHandle()
conv = PamConv(None, 0)
retval = pam_start(service, username, byref(conv), byref(handle))
retval = pam_authenticate(handle, 0)
auth_success = retval == 0
return auth_success
@app.route('/good')
def good():
username = request.args.get('username', '')
handle = PamHandle()
conv = PamConv(None, 0)
retval = pam_start(service, username, byref(conv), byref(handle))
retval = pam_authenticate(handle, 0)
if retval == 0:
retval = pam_acct_mgmt(handle, 0)
auth_success = retval == 0
return auth_success