Escape Username before using it in any search filter
This commit is contained in:
parent
ef8d313042
commit
c0a43f4800
|
|
@ -2,9 +2,16 @@
|
||||||
''''[ -z $LOG ] && export LOG=/dev/stdout # '''
|
''''[ -z $LOG ] && export LOG=/dev/stdout # '''
|
||||||
''''which python >/dev/null && exec python -u "$0" "$@" >> $LOG 2>&1 # '''
|
''''which python >/dev/null && exec python -u "$0" "$@" >> $LOG 2>&1 # '''
|
||||||
|
|
||||||
# Copyright (C) 2014-2015 Nginx, Inc.
|
# Copyright (C) 2014-2022 Nginx, Inc.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import base64
|
||||||
|
import ldap
|
||||||
|
from ldap.filter import escape_filter_chars
|
||||||
|
import argparse
|
||||||
|
|
||||||
import sys, os, signal, base64, ldap, argparse
|
|
||||||
if sys.version_info.major == 2:
|
if sys.version_info.major == 2:
|
||||||
from Cookie import BaseCookie
|
from Cookie import BaseCookie
|
||||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
@ -23,6 +30,7 @@ if not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Requests are processed in separate thread
|
# Requests are processed in separate thread
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
if sys.version_info.major == 2:
|
if sys.version_info.major == 2:
|
||||||
from SocketServer import ThreadingMixIn
|
from SocketServer import ThreadingMixIn
|
||||||
elif sys.version_info.major == 3:
|
elif sys.version_info.major == 3:
|
||||||
|
|
@ -88,9 +96,9 @@ class AuthHandler(BaseHTTPRequestHandler):
|
||||||
except:
|
except:
|
||||||
self.auth_failed(ctx)
|
self.auth_failed(ctx)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
ctx['user'] = user
|
|
||||||
ctx['pass'] = passwd
|
ctx['pass'] = passwd
|
||||||
|
ctx['user'] = ldap.filter.escape_filter_chars(user)
|
||||||
|
|
||||||
# Continue request processing
|
# Continue request processing
|
||||||
return False
|
return False
|
||||||
|
|
@ -228,7 +236,7 @@ class LDAPAuthHandler(AuthHandler):
|
||||||
ldap_obj.bind_s(ctx['binddn'], ctx['bindpasswd'], ldap.AUTH_SIMPLE)
|
ldap_obj.bind_s(ctx['binddn'], ctx['bindpasswd'], ldap.AUTH_SIMPLE)
|
||||||
|
|
||||||
ctx['action'] = 'preparing search filter'
|
ctx['action'] = 'preparing search filter'
|
||||||
searchfilter = ctx['template'] % { 'username': ctx['user'] }
|
searchfilter = ctx['template'] % {'username': ctx['user']}
|
||||||
|
|
||||||
self.log_message(('searching on server "%s" with base dn ' + \
|
self.log_message(('searching on server "%s" with base dn ' + \
|
||||||
'"%s" with filter "%s"') %
|
'"%s" with filter "%s"') %
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,15 @@ http {
|
||||||
proxy_pass http://backend/;
|
proxy_pass http://backend/;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /query-injection {
|
||||||
|
auth_request /auth-query-injection;
|
||||||
|
|
||||||
|
error_page 401 =200 /login;
|
||||||
|
|
||||||
|
proxy_pass http://backend/;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
location /login {
|
location /login {
|
||||||
proxy_pass http://backend/login;
|
proxy_pass http://backend/login;
|
||||||
|
|
||||||
|
|
@ -221,6 +230,24 @@ http {
|
||||||
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location = /auth-query-injection {
|
||||||
|
internal;
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:8888;
|
||||||
|
|
||||||
|
proxy_pass_request_body off;
|
||||||
|
proxy_set_header Content-Length "";
|
||||||
|
|
||||||
|
proxy_set_header X-Ldap-URL "ldap://127.0.0.1:8083";
|
||||||
|
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
|
||||||
|
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||||
|
proxy_set_header X-Ldap-BindPass "secret";
|
||||||
|
|
||||||
|
proxy_set_header X-CookieName "nginxauth";
|
||||||
|
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
||||||
|
|
||||||
|
proxy_set_header X-Ldap-Template '(|(&(memberOf=superadmin)(cn=%(username)s))(&(memberOf=admin)(cn=%(username)s)))';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,7 +348,7 @@ EOF
|
||||||
$t->write_file_expand("initial.ldif", <<'EOF');
|
$t->write_file_expand("initial.ldif", <<'EOF');
|
||||||
dn: dc=test,dc=local
|
dn: dc=test,dc=local
|
||||||
dc: test
|
dc: test
|
||||||
description: BlaBlaBla
|
description: Test-OU
|
||||||
objectClass: dcObject
|
objectClass: dcObject
|
||||||
objectClass: organization
|
objectClass: organization
|
||||||
o: Example, Inc.
|
o: Example, Inc.
|
||||||
|
|
@ -333,7 +360,7 @@ objectclass: organizationalunit
|
||||||
|
|
||||||
dn: cn=user1,ou=Users,dc=test,dc=local
|
dn: cn=user1,ou=Users,dc=test,dc=local
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
cn: User number one
|
cn: User1
|
||||||
sn: u1
|
sn: u1
|
||||||
uid: user1
|
uid: user1
|
||||||
userpassword: user1secret
|
userpassword: user1secret
|
||||||
|
|
@ -343,7 +370,7 @@ ou: Users
|
||||||
|
|
||||||
dn: cn=user2,ou=Users,dc=test,dc=local
|
dn: cn=user2,ou=Users,dc=test,dc=local
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
cn: User number one
|
cn: User2
|
||||||
sn: u2
|
sn: u2
|
||||||
uid: user2
|
uid: user2
|
||||||
userpassword: user2secret
|
userpassword: user2secret
|
||||||
|
|
@ -353,7 +380,7 @@ ou: Users
|
||||||
|
|
||||||
dn: cn=user3,ou=Users,dc=test,dc=local
|
dn: cn=user3,ou=Users,dc=test,dc=local
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
cn: User number one
|
cn: User3
|
||||||
sn: u3
|
sn: u3
|
||||||
uid: user3
|
uid: user3
|
||||||
userpassword: user3secret
|
userpassword: user3secret
|
||||||
|
|
@ -378,13 +405,13 @@ objectclass: organizationalunit
|
||||||
|
|
||||||
dn: ou=more,ou=Users,dc=test,dc=local
|
dn: ou=more,ou=Users,dc=test,dc=local
|
||||||
dc: test
|
dc: test
|
||||||
description: BlaBlaBla
|
description: Test-OU
|
||||||
objectClass: dcObject
|
objectClass: dcObject
|
||||||
objectClass: organizationalUnit
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
dn: cn=user4, ou=more, ou=Users,dc=test,dc=local
|
dn: cn=user4, ou=more, ou=Users,dc=test,dc=local
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
cn: User number one
|
cn: User4
|
||||||
sn: u4
|
sn: u4
|
||||||
uid: user4
|
uid: user4
|
||||||
userpassword: user4secret
|
userpassword: user4secret
|
||||||
|
|
@ -441,7 +468,7 @@ $t->run_daemon('/bin/sh', "$d/auth_daemon.sh");
|
||||||
$t->waitforsocket('127.0.0.1:' . port(8888))
|
$t->waitforsocket('127.0.0.1:' . port(8888))
|
||||||
or die "Can't start auth daemon";
|
or die "Can't start auth daemon";
|
||||||
|
|
||||||
$t->plan(21);
|
$t->plan(22);
|
||||||
|
|
||||||
$t->run();
|
$t->run();
|
||||||
|
|
||||||
|
|
@ -500,10 +527,17 @@ like(http_get_auth('/ref1', 'user4', 'user4secret'), qr!LOGIN PAGE!,
|
||||||
'server2 user via referral on server1');
|
'server2 user via referral on server1');
|
||||||
|
|
||||||
# unknown user on referred server, result is empty dn
|
# unknown user on referred server, result is empty dn
|
||||||
like(http_get_auth('/ref1', 'userx', 'blah'), qr!LOGIN PAGE!,
|
like(http_get_auth('/ref1', 'unknow_user', 'unknowpassword'), qr!LOGIN PAGE!,
|
||||||
'unknown user with referral on server1');
|
'unknown user with referral on server1');
|
||||||
|
|
||||||
|
|
||||||
|
# LDAP Query Injection result in 401
|
||||||
|
like(http_get_auth('/query-injection', 'user1))(|(cn=user1', 'user1secret'), qr!LOGIN PAGE!,
|
||||||
|
'Injection Attempt in Username will be escaped and blocked.');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
sub http_get_auth {
|
sub http_get_auth {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue