1010
1111import java
1212import semmle.code.java.frameworks.Jndi
13+ import semmle.code.java.frameworks.Networking
1314import semmle.code.java.dataflow.TaintTracking
1415import DataFlow:: PathGraph
1516
1617/**
17- * Gets a regular expression for matching private hosts, which only matches the host portion therefore checking for port is not necessary .
18+ * Insecure (non-SSL, non- private) LDAP URL string literal .
1819 */
19- private string getPrivateHostRegex ( ) {
20- result =
21- "(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?"
22- }
23-
24- /**
25- * String of LDAP connections not in private domains.
26- */
27- class LdapStringLiteral extends StringLiteral {
28- LdapStringLiteral ( ) {
20+ class InsecureLdapUrlLiteral extends StringLiteral {
21+ InsecureLdapUrlLiteral ( ) {
2922 // Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives.
3023 exists ( string s | this .getRepresentedString ( ) = s |
3124 s .regexpMatch ( "(?i)ldap://[\\[a-zA-Z0-9].*" ) and
32- not s .substring ( 7 , s .length ( ) ) . regexpMatch ( getPrivateHostRegex ( ) )
25+ not s .substring ( 7 , s .length ( ) ) instanceof PrivateHostName
3326 )
3427 }
3528}
@@ -47,24 +40,15 @@ class TypeHashtable extends Class {
4740/**
4841 * Holds if a non-private LDAP string is concatenated from both protocol and host.
4942 */
50- predicate concatLdapString ( Expr protocol , Expr host ) {
51- (
52- protocol .( CompileTimeConstantExpr ) .getStringValue ( ) .regexpMatch ( "(?i)ldap(://)?" ) or
53- protocol
54- .( VarAccess )
55- .getVariable ( )
56- .getAnAssignedValue ( )
57- .( CompileTimeConstantExpr )
58- .getStringValue ( )
59- .regexpMatch ( "(?i)ldap(://)?" )
60- ) and
43+ predicate concatInsecureLdapString ( Expr protocol , Expr host ) {
44+ protocol .( CompileTimeConstantExpr ) .getStringValue ( ) = "ldap://" and
6145 not exists ( string hostString |
6246 hostString = host .( CompileTimeConstantExpr ) .getStringValue ( ) or
6347 hostString =
6448 host .( VarAccess ) .getVariable ( ) .getAnAssignedValue ( ) .( CompileTimeConstantExpr ) .getStringValue ( )
6549 |
6650 hostString .length ( ) = 0 or // Empty host is loopback address
67- hostString . regexpMatch ( getPrivateHostRegex ( ) )
51+ hostString instanceof PrivateHostName
6852 )
6953}
7054
@@ -76,22 +60,21 @@ Expr getLeftmostConcatOperand(Expr expr) {
7660}
7761
7862/**
79- * String concatenated with `LdapStringLiteral `.
63+ * String concatenated with `InsecureLdapUrlLiteral `.
8064 */
81- class LdapString extends Expr {
82- LdapString ( ) {
83- this instanceof LdapStringLiteral
65+ class InsecureLdapUrl extends Expr {
66+ InsecureLdapUrl ( ) {
67+ this instanceof InsecureLdapUrlLiteral
8468 or
85- concatLdapString ( this .( AddExpr ) .getLeftOperand ( ) ,
69+ concatInsecureLdapString ( this .( AddExpr ) .getLeftOperand ( ) ,
8670 getLeftmostConcatOperand ( this .( AddExpr ) .getRightOperand ( ) ) )
8771 }
8872}
8973
9074/**
91- * Tainted value passed to env `Hashtable` as the provider URL, i.e.
92- * `env.put(Context.PROVIDER_URL, tainted)` or `env.setProperty(Context.PROVIDER_URL, tainted)`.
75+ * Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`.
9376 */
94- predicate isProviderUrlEnv ( MethodAccess ma ) {
77+ predicate isProviderUrlSetter ( MethodAccess ma ) {
9578 ma .getMethod ( ) .getDeclaringType ( ) .getAnAncestor ( ) instanceof TypeHashtable and
9679 ( ma .getMethod ( ) .hasName ( "put" ) or ma .getMethod ( ) .hasName ( "setProperty" ) ) and
9780 (
@@ -106,8 +89,7 @@ predicate isProviderUrlEnv(MethodAccess ma) {
10689}
10790
10891/**
109- * Holds if the value "simple" is passed to env `Hashtable` as the authentication mechanism, i.e.
110- * `env.put(Context.SECURITY_AUTHENTICATION, "simple")` or `env.setProperty(Context.SECURITY_AUTHENTICATION, "simple")`.
92+ * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`.
11193 */
11294predicate isSimpleAuthEnv ( MethodAccess ma ) {
11395 ma .getMethod ( ) .getDeclaringType ( ) .getAnAncestor ( ) instanceof TypeHashtable and
@@ -132,13 +114,13 @@ class LdapAuthFlowConfig extends TaintTracking::Configuration {
132114 LdapAuthFlowConfig ( ) { this = "InsecureLdapAuth:LdapAuthFlowConfig" }
133115
134116 /** Source of non-private LDAP connection string */
135- override predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof LdapString }
117+ override predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof InsecureLdapUrl }
136118
137119 /** Sink of provider URL with simple authentication */
138120 override predicate isSink ( DataFlow:: Node sink ) {
139121 exists ( MethodAccess pma |
140122 sink .asExpr ( ) = pma .getArgument ( 1 ) and
141- isProviderUrlEnv ( pma ) and
123+ isProviderUrlSetter ( pma ) and
142124 exists ( MethodAccess sma |
143125 sma .getQualifier ( ) = pma .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) and
144126 isSimpleAuthEnv ( sma )
0 commit comments