[APPSEC-801] Migrate S4433 to LaYC format. (#2307)
This commit is contained in:
parent
fe5c2e4c2f
commit
117d6b9c7e
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -3,6 +3,10 @@
|
|||||||
{
|
{
|
||||||
"language": "markdown",
|
"language": "markdown",
|
||||||
"scheme": "file"
|
"scheme": "file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "asciidoc",
|
||||||
|
"scheme": "file"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
5
rules/S4433/common/description.adoc
Normal file
5
rules/S4433/common/description.adoc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
When configured to accept the Anonymous or Unauthenticated authentication
|
||||||
|
mechanism, an LDAP server will accept connections from clients that do not
|
||||||
|
provide a password or other authentication credentials. Such users will be
|
||||||
|
able to read or modify part or all of the data contained in the hosted
|
||||||
|
directory.
|
3
rules/S4433/common/fix/code-rationale.adoc
Normal file
3
rules/S4433/common/fix/code-rationale.adoc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
The following code indicates an anonymous LDAP authentication vulnerability
|
||||||
|
because it binds to a remote server using an Anonymous Simple authentication
|
||||||
|
mechanism.
|
30
rules/S4433/common/impact.adoc
Normal file
30
rules/S4433/common/impact.adoc
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
An attacker exploiting unauthenticated access to an LDAP server can access the
|
||||||
|
data that is stored in the corresponding directory. The impact varies depending
|
||||||
|
on the permission obtained on the directory and the type of data it stores.
|
||||||
|
|
||||||
|
==== Authentication bypass
|
||||||
|
|
||||||
|
If attackers get write access to the directory, they will be able to alter
|
||||||
|
most of the data it stores. This might include sensitive technical data such as
|
||||||
|
user passwords or asset configurations. Such an attack can typically lead to
|
||||||
|
an authentication bypass on applications and systems that use the affected
|
||||||
|
directory as an identity provider.
|
||||||
|
|
||||||
|
In such a case, all users configured in the directory might see their identity
|
||||||
|
and privileges taken over.
|
||||||
|
|
||||||
|
==== Sensitive information leak
|
||||||
|
|
||||||
|
If attackers get read-only access to the directory, they will be able to read
|
||||||
|
the data it stores. That data might include security-sensitive pieces of
|
||||||
|
information.
|
||||||
|
|
||||||
|
Typically, attackers might get access to user account lists that they can use
|
||||||
|
in further intrusion steps. For example, they could use such lists to perform
|
||||||
|
password spraying, or related attacks, on all systems that rely on the affected
|
||||||
|
directory as an identity provider.
|
||||||
|
|
||||||
|
If the directory contains some Personally Identifiable Information, an attacker
|
||||||
|
accessing it might represent a violation of regulatory requirements in some
|
||||||
|
countries. For example, this kind of security event would go against the
|
||||||
|
European GDPR law.
|
10
rules/S4433/common/rationale.adoc
Normal file
10
rules/S4433/common/rationale.adoc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Lightweight Directory Access Protocol (LDAP) servers provide two main
|
||||||
|
authentication methods: the _SASL_ and _Simple_ ones. The _Simple
|
||||||
|
Authentication_ method also breaks down into three different mechanisms:
|
||||||
|
|
||||||
|
* _Anonymous_ Authentication
|
||||||
|
* _Unauthenticated_ Authentication
|
||||||
|
* _Name/Password_ Authentication
|
||||||
|
|
||||||
|
A server that accepts either the _Anonymous_ or _Unauthenticated_ mechanisms will
|
||||||
|
accept connections from clients not providing credentials.
|
3
rules/S4433/common/resources/documentation.adoc
Normal file
3
rules/S4433/common/resources/documentation.adoc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
=== Documentation
|
||||||
|
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc4513#section-5[RFC 4513 - Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms] - Bind operations
|
@ -1,6 +1,5 @@
|
|||||||
== Resources
|
=== Standards
|
||||||
|
|
||||||
* https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/[OWASP Top 10 2021 Category A7] - Identification and Authentication Failures
|
* https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/[OWASP Top 10 2021 Category A7] - Identification and Authentication Failures
|
||||||
* https://owasp.org/www-project-top-ten/2017/A2_2017-Broken_Authentication[OWASP Top 10 2017 Category A2] - Broken Authentication
|
* https://owasp.org/www-project-top-ten/2017/A2_2017-Broken_Authentication[OWASP Top 10 2017 Category A2] - Broken Authentication
|
||||||
* https://cwe.mitre.org/data/definitions/521[MITRE, CWE-521] - Weak Password Requirements
|
* https://cwe.mitre.org/data/definitions/521[MITRE, CWE-521] - Weak Password Requirements
|
||||||
* https://web.archive.org/web/20220922153922/https://ldapwiki.com/wiki/Simple%20Authentication[ldapwiki.com]- Simple Authentication
|
|
@ -1,12 +1,22 @@
|
|||||||
|
include::../common/rationale.adoc[]
|
||||||
|
|
||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
include::../description.adoc[]
|
include::../common/description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== What is the potential impact?
|
||||||
|
|
||||||
This rule raises an issue when an LDAP connection is created with ``++AuthenticationTypes.Anonymous++`` or ``++AuthenticationTypes.None++``.
|
include::../common/impact.adoc[]
|
||||||
|
|
||||||
[source,csharp]
|
== How to fix it
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
include::../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
DirectoryEntry myDirectoryEntry = new DirectoryEntry(adPath);
|
DirectoryEntry myDirectoryEntry = new DirectoryEntry(adPath);
|
||||||
myDirectoryEntry.AuthenticationType = AuthenticationTypes.None; // Noncompliant
|
myDirectoryEntry.AuthenticationType = AuthenticationTypes.None; // Noncompliant
|
||||||
@ -14,16 +24,35 @@ myDirectoryEntry.AuthenticationType = AuthenticationTypes.None; // Noncompliant
|
|||||||
DirectoryEntry myDirectoryEntry = new DirectoryEntry(adPath, "u", "p", AuthenticationTypes.None); // Noncompliant
|
DirectoryEntry myDirectoryEntry = new DirectoryEntry(adPath, "u", "p", AuthenticationTypes.None); // Noncompliant
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
|
||||||
|
|
||||||
[source,csharp]
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
DirectoryEntry myDirectoryEntry = new DirectoryEntry(myADSPath); // Compliant; default DirectoryEntry.AuthenticationType property value is "Secure" since .NET Framework 2.0
|
DirectoryEntry myDirectoryEntry = new DirectoryEntry(myADSPath); // Compliant; default DirectoryEntry.AuthenticationType property value is "Secure" since .NET Framework 2.0
|
||||||
|
|
||||||
DirectoryEntry myDirectoryEntry = new DirectoryEntry(myADSPath, "u", "p", AuthenticationTypes.Secure);
|
DirectoryEntry myDirectoryEntry = new DirectoryEntry(myADSPath, "u", "p", AuthenticationTypes.Secure);
|
||||||
----
|
----
|
||||||
|
|
||||||
include::../see.adoc[]
|
//=== How does this work?
|
||||||
|
|
||||||
|
//=== Pitfalls
|
||||||
|
|
||||||
|
//=== Going the extra mile
|
||||||
|
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
//=== Documentation
|
||||||
|
|
||||||
|
include::../common/resources/documentation.adoc[]
|
||||||
|
|
||||||
|
//=== Articles & blog posts
|
||||||
|
//=== Conference presentations
|
||||||
|
//=== Standards
|
||||||
|
|
||||||
|
include::../common/resources/standards.adoc[]
|
||||||
|
|
||||||
|
//=== Benchmarks
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
@ -42,4 +71,4 @@ include::../highlighting.adoc[]
|
|||||||
=== on 5 Apr 2018, 12:10:55 Alexandre Gigleux wrote:
|
=== on 5 Apr 2018, 12:10:55 Alexandre Gigleux wrote:
|
||||||
https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.directoryentry.authenticationtype?view=netcore-2.0#System_DirectoryServices_DirectoryEntry_AuthenticationType
|
https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.directoryentry.authenticationtype?view=netcore-2.0#System_DirectoryServices_DirectoryEntry_AuthenticationType
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
endif::env-github,rspecator-view[]
|
@ -1,9 +0,0 @@
|
|||||||
An LDAP client authenticates to an LDAP server with a "bind request" which provides, among other, a https://web.archive.org/web/20220922153922/https://ldapwiki.com/wiki/Simple%20Authentication[simple authentication method].
|
|
||||||
|
|
||||||
Simple authentication in LDAP can be used with three different mechanisms:
|
|
||||||
|
|
||||||
* _Anonymous Authentication Mechanism_ by performing a bind request with a username and password value of zero length.
|
|
||||||
* _Unauthenticated Authentication Mechanism_ by performing a bind request with a password value of zero length.
|
|
||||||
* _Name/Password Authentication Mechanism_ by performing a bind request with a password value of non-zero length.
|
|
||||||
|
|
||||||
Anonymous binds and unauthenticated binds allow access to information in the LDAP directory without providing a password, their use is therefore strongly discouraged.
|
|
@ -1,12 +1,22 @@
|
|||||||
|
include::../common/rationale.adoc[]
|
||||||
|
|
||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
include::../description.adoc[]
|
include::../common/description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== What is the potential impact?
|
||||||
|
|
||||||
This rule raises an issue when an LDAP connection is created with ``++Context.SECURITY_AUTHENTICATION++`` set to ``++"none"++``.
|
include::../common/impact.adoc[]
|
||||||
|
|
||||||
[source,java]
|
== How to fix it
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
include::../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
// Set up the environment for creating the initial context
|
// Set up the environment for creating the initial context
|
||||||
Hashtable<String, Object> env = new Hashtable<String, Object>();
|
Hashtable<String, Object> env = new Hashtable<String, Object>();
|
||||||
@ -20,25 +30,44 @@ env.put(Context.SECURITY_AUTHENTICATION, "none"); // Noncompliant
|
|||||||
DirContext ctx = new InitialDirContext(env);
|
DirContext ctx = new InitialDirContext(env);
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
|
||||||
|
|
||||||
[source,java]
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
// Set up the environment for creating the initial context
|
// Set up the environment for creating the initial context
|
||||||
Hashtable<String, Object> env = new Hashtable<String, Object>();
|
Hashtable<String, Object> env = new Hashtable<String, Object>();
|
||||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||||
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");
|
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=Example");
|
||||||
|
|
||||||
// Use simple authentication
|
// Use simple authentication
|
||||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||||
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
|
env.put(Context.SECURITY_PRINCIPAL, "cn=local, ou=Unit, o=Example");
|
||||||
env.put(Context.SECURITY_CREDENTIALS, getLDAPPassword());
|
env.put(Context.SECURITY_CREDENTIALS, getLDAPPassword());
|
||||||
|
|
||||||
// Create the initial context
|
// Create the initial context
|
||||||
DirContext ctx = new InitialDirContext(env);
|
DirContext ctx = new InitialDirContext(env);
|
||||||
----
|
----
|
||||||
|
|
||||||
include::../see.adoc[]
|
//=== How does this work?
|
||||||
|
|
||||||
|
//=== Pitfalls
|
||||||
|
|
||||||
|
//=== Going the extra mile
|
||||||
|
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
//=== Documentation
|
||||||
|
|
||||||
|
include::../common/resources/documentation.adoc[]
|
||||||
|
|
||||||
|
//=== Articles & blog posts
|
||||||
|
//=== Conference presentations
|
||||||
|
//=== Standards
|
||||||
|
|
||||||
|
include::../common/resources/standards.adoc[]
|
||||||
|
|
||||||
|
//=== Benchmarks
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
@ -50,4 +79,4 @@ include::../message.adoc[]
|
|||||||
|
|
||||||
include::../highlighting.adoc[]
|
include::../highlighting.adoc[]
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
endif::env-github,rspecator-view[]
|
@ -1,21 +1,34 @@
|
|||||||
|
include::../common/rationale.adoc[]
|
||||||
|
|
||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
include::../description.adoc[]
|
include::../common/description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== What is the potential impact?
|
||||||
|
|
||||||
[source,php]
|
include::../common/impact.adoc[]
|
||||||
|
|
||||||
|
== How to fix it
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
include::../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,php,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
$ldapconn = ldap_connect("ldap.example.com");
|
$ldapconn = ldap_connect("ldap.example.com");
|
||||||
|
|
||||||
if ($ldapconn) {
|
if ($ldapconn) {
|
||||||
$ldapbind = ldap_bind($ldapconn); // Noncompliant; anonymous authentication, no user/password provided
|
$ldapbind = ldap_bind($ldapconn); // Noncompliant
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
|
||||||
|
|
||||||
[source,php]
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,php,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
$ldaprdn = 'uname';
|
$ldaprdn = 'uname';
|
||||||
$ldappass = 'password';
|
$ldappass = 'password';
|
||||||
@ -27,7 +40,25 @@ if ($ldapconn) {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
include::../see.adoc[]
|
//=== How does this work?
|
||||||
|
|
||||||
|
//=== Pitfalls
|
||||||
|
|
||||||
|
//=== Going the extra mile
|
||||||
|
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
//=== Documentation
|
||||||
|
|
||||||
|
include::../common/resources/documentation.adoc[]
|
||||||
|
|
||||||
|
//=== Articles & blog posts
|
||||||
|
//=== Conference presentations
|
||||||
|
//=== Standards
|
||||||
|
|
||||||
|
include::../common/resources/standards.adoc[]
|
||||||
|
|
||||||
|
//=== Benchmarks
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
@ -42,4 +73,4 @@ Provide username and password to authenticate the connection.
|
|||||||
|
|
||||||
include::../highlighting.adoc[]
|
include::../highlighting.adoc[]
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
endif::env-github,rspecator-view[]
|
@ -1,10 +1,22 @@
|
|||||||
|
include::../common/rationale.adoc[]
|
||||||
|
|
||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
include::../description.adoc[]
|
include::../common/description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== What is the potential impact?
|
||||||
|
|
||||||
[source,python]
|
include::../common/impact.adoc[]
|
||||||
|
|
||||||
|
== How to fix it
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
include::../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
import ldap
|
import ldap
|
||||||
|
|
||||||
@ -17,9 +29,10 @@ def init_ldap():
|
|||||||
connect.bind('cn=root', None) # Noncompliant
|
connect.bind('cn=root', None) # Noncompliant
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
|
||||||
|
|
||||||
[source,python]
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
import ldap
|
import ldap
|
||||||
import os
|
import os
|
||||||
@ -27,13 +40,31 @@ import os
|
|||||||
def init_ldap():
|
def init_ldap():
|
||||||
connect = ldap.initialize('ldap://example:1389')
|
connect = ldap.initialize('ldap://example:1389')
|
||||||
|
|
||||||
connect.simple_bind('cn=root', os.environ.get('LDAP_PASSWORD')) # Compliant
|
connect.simple_bind('cn=root', os.environ.get('LDAP_PASSWORD'))
|
||||||
connect.simple_bind_s('cn=root', os.environ.get('LDAP_PASSWORD')) # Compliant
|
connect.simple_bind_s('cn=root', os.environ.get('LDAP_PASSWORD'))
|
||||||
connect.bind_s('cn=root', os.environ.get('LDAP_PASSWORD')) # Compliant
|
connect.bind_s('cn=root', os.environ.get('LDAP_PASSWORD'))
|
||||||
connect.bind('cn=root', os.environ.get('LDAP_PASSWORD')) # Compliant
|
connect.bind('cn=root', os.environ.get('LDAP_PASSWORD'))
|
||||||
----
|
----
|
||||||
|
|
||||||
include::../see.adoc[]
|
//=== How does this work?
|
||||||
|
|
||||||
|
//=== Pitfalls
|
||||||
|
|
||||||
|
//=== Going the extra mile
|
||||||
|
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
//=== Documentation
|
||||||
|
|
||||||
|
include::../common/resources/documentation.adoc[]
|
||||||
|
|
||||||
|
//=== Articles & blog posts
|
||||||
|
//=== Conference presentations
|
||||||
|
//=== Standards
|
||||||
|
|
||||||
|
include::../common/resources/standards.adoc[]
|
||||||
|
|
||||||
|
//=== Benchmarks
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user