Skip to content

Instantly share code, notes, and snippets.

@Kagee
Last active November 27, 2023 10:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kagee/f35ed25216369481437210753959d372 to your computer and use it in GitHub Desktop.
Save Kagee/f35ed25216369481437210753959d372 to your computer and use it in GitHub Desktop.
MISP and LDAP using the ApacheSecureAuth module

Important

- The ApacheSecureAuth / LDAP login code in MISP is a 
- 3rd party contribution and untested (including security)
- by the MISP-project team. However, you are free to enable
- it and report back to the developers if you run into any issues.
- This guide is a work in progress and
- not considered a completed product.

Table of Contents

Assumptions and limitations

  • MISP is running on a Debian-based (i.e Ubuntu) system.
    • The general "Login flow explanation" etc. is the same for other systems, but for i.e. RedHat-based distroes some paths and commands must be changed.
  • MISP is running behind a Apache 2.4 or newer webserver.
  • You are connecting to a AD LDAP server. (Should also work with Samba AD LDAP)
  • We assume MISP is installed in /var/www/MISP

Requirements

Before starting, you should have the following access and data. You can see examples on required data in Example data.

MISP Server:

  • Terminal (ssh) access to the server MISP is running on
  • sudo (root) access to the server MISP is running on
  • The server MISP is running on must be able to connect to the AD LDAP port
    • This may require allowing both LDAP and TLS in a firewall on port TCP/389.

Active Directory:

  • The domain name of the AD domain
  • A hostname for connecting to AD via LDAP
  • Information on wheter you should connect using LDAP+STARTTLS (recommended, uses port 389), LDAP over TLS ("LDAPS", uses port 636), or unencrypted LDAP (uses port 389)
  • A service user (read-only is enough) for the AD LDAP you are connecting to.
    • The DN, UPN and password for this service user
  • The DN for a group that will be used to control MISP access
  • A test user for testing the MISP login
    • This user should be a member of the access group, either directly or via nested group memberships.

Example data

In this guide we will use the following example data

Item Value
Domain Netbios name EXAMPLE
Domain name example.com
Hostname of AD server(s) ad.example.com
MISP Access group CN=R_MISP_Access,OU=Misp,OU=Access Groups,DC=example,DC=com
AD Service account DN CN=srv_misp,OU=Service Users,DC=example,DC=com
AD Service account UPN srv_misp@example.com
AD Service account password ServiceUserPassword1234
Example user username user101
Example user DN CN=Example User,OU=Users,DC=example,DC=com
Example user UPN user101@example.com
Example user password MySecretPassword1234

Test LDAP connection and credentials

  • ldapsearch -D 'CN=some_service_user,OU=Service Users,DC=example,DC=com' -W -H 'ldap://ad.example.com' -b 'dc=example,dc=com' '(uid=<your username>)' '*'

When ldapsearch asks for a password, enter the password for the some_service_user-user. This is the user we are trying to connect as, as spesified with -D.

Now, it is probably going to fail. If you get your ldapsearch to work on the first try i owe you a pint of beer/soda.

When your first try fail, ldapsearch just LOVES to return the impressively unhelpful error message Can't contact LDAP server (-1). Add -d 9 (debug level 9) to the command line to get more useful error messages.

  • ldapsearch -d 9 -D 'CN=some_service_user,OU=Service Users,DC=example,DC=com' -W -H 'ldap://ad.example.com' -b 'dc=ad,dc=example,dc=com' '(uid=<your username>)' '*'

Login flow explanation

Everything from step 3 to 7 is part of what the webserver does, and must be configured in the webserver config (possibly somewhere like /etc/apache2/sites-enabled/misp.conf). Step 8 to 13 happens in the MISP code, and is configured in the normal MISP config.php. (possibly somewhere like /var/www/MISP/app/Config/config.php)

  1. User visits misp.domain.
  2. user is forwarded to misp.domain/user/login.
  3. Webserver has been configured to require LDAP authentication and possibly authorization on that URL.
  4. The webserver will return a http 401 unauthorized to the users browser, with information about how to authorize.
  5. With Apache and LDAP, the default will trigger the users browser to pop up a standard "HTTP Basic Auth" popup box where the user can enter their AD credentials.
  6. The browser will reload misp.domain/user/login, but also transmit the username and password the user supplied in step 5. (Unencrypted, so using https is important).
  7. The webserver will connect to AD over LDAP using the configured ad service account. It will then try to authenticate the user using the supplied username and password, and potentially check that the user is in a required group (authorization). Is this step fails, go to step 4.
  8. If step 7 is successful, the webserver will start the PHP process, and render misp.domain/user/login using the MISP source code. It will transmit the username as part of the request (either just username or username@ad.domain depending on setting) in a HTTP request header, quite often called REMOTE_USER or HTTP_REMOTE_USER.
  9. The correct header name must be configured in ApacheSecureAuth.apaceEnv (I think the default here is REMOTE_USER)
  10. Once the MISP code sees a request to misp.domain/user/login that has this HTTP request header set, it will buypass the normal MISP login form.
  11. The MISP code will connect to AD over LDAP suing the settings configurd in ApacheSecureAuth.*. Depending on the values and searches configured there, it will retrieve information on the users, for example their configured email address (from the AD "mail" field) or some other attribute that will be user in the MISP email field (i.e. userprincipalname)
  12. If the user data of found, and a user exists in the MISP DB with that identification (mail, upn, other), the user will be logged inn.
  13. If the user is not found in the DB, a new user will be configured with the default role and organization. (ldapDefaultOrg and ldapDefaultRoleId)

Configure Apache for LDAP authentication and authorization

The "1.2.840.113556.1.4.1941" is a OID called LDAP_MATCHING_RULE_IN_CHAIN. It is a common solution to support (both) nested and non-nested AD groups via LDAP (you can read about it in google)

# For turning on LDAP Debug output
# LDAPLibraryDebug 7
<VirtualHost ....>

...

<Location "/users/login">
    AuthType Basic
    AuthName "MISP"
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://.../...?uid?sub?(objectclass=*)" STARTTLS
    AuthLDAPBindDN ",,,"
    AuthLDAPBindPassword ",,,"
    LDAPReferrals off
    Require valid-user
    Require ldap-filter memberof:1.2.840.113556.1.4.1941:=...
</Location>
...
</VirtualHost>

Configure MISP for LDAP usage

'ApacheSecureAuth' => array(
     // Possibly REDIRECT_REMOTE_USER or HTTP_REMOTE_USER. DO NOT USE PHP_AUTH_USER
    'apacheEnv'          => 'REMOTE_USER', 
    'ldapServer'         => 'ldap://...',
    'starttls'           => true,
    'ldapProtocol'       => 3,
    'ldapNetworkTimeout' => 10,
    'ldapReaderUser'     => '...',
    'ldapReaderPassword' => '...', // the LDAP reader user password
    'ldapDN'             => '...',
    'ldapSearchFilter'   => '', // Search filter to limit results from ldapsearh fx to specific group. FX
    'ldapDN' => 'dc=internal,dc=example,dc=com',
    'ldapSearchFilter' => '(memberof:1.2.840.113556.1.4.1941:=CN=AllowMISPLogin,OU=MISP,OU=Access Groups,DC=intern,DC=example,DC=com)',
    'ldapSearchAttribut' => 'samaccountname', // LOWERCASE
    'ldapFilter'         => array('mail','userprincipalname'),
    'ldapDefaultRoleId'  => 3,
    'ldapDefaultOrg'     => '1',
    'ldapAllowReferrals' => false,
    'ldapEmailField' => array('userprincipalname'),
    'updateUser' => true,
  ),

Terminology

Term Explanation
AD (Active Directory) Active Directory is a directory service developed by Microsoft for Windows domain networks. Active Directory uses LDAP, Microsoft's version of Kerberos, and DNS. More
DN (Distinguished name) The LDAP API references an LDAP object by its distinguished name (DN). A DN is a sequence of relative distinguished names (RDN) connected by commas. More
LDAP (the protocol) The Lightweight Directory Access Protocol (LDAP) is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services. Directory services play an important role in developing intranet and Internet applications by allowing the sharing of information about users, systems, networks, services, and applications throughout the network. More
LDAP (unencrypted) Raw, unencrypted LDAP. You should not be using this. Denoted using the URI schema ldap://. Unencrypted LDAP uses port TCP/389.
LDAP with TLS (StartTLS) The standardized way of protecting LDAP with TLS. Unfortunately it uses the same URI schema as unencrypted LDAP (`ldap://) and the same port, TCP/389.
LDAPS (LDAP over SSL/TLS) A non-standard way of doing LDAP over an established TLS connection. Upon connect, the client and server establish TLS before any LDAP messages are transferred (without a StartTLS operation). LDAPS is often denoted using the URI schema ldaps://, and uses port TCP/636.
UPN In Microsoft Active Directory, a User Principal Name (UPN) is a username and domain in an email address format. In a UPN, the username is followed by a separator "at sign" (@) followed by the active directory's internet domain. More

Unsorted notes

  • Oct 5 15:13:26 HOSTNAME MISP: error: [Error] Call to undefined function ldap_set_option() -> install php-ldap (same name in debian/red hat)
  • must install mod_ldap in red hat, find name of same pacakge in debian
  • Error in LDAP search query: Bad search filter -> remeber to have ( ) around filter in cofig.php
  • example: apache config for login with mail: AuthLDAPUrl ldap://ad-server01:389/DC=company,DC=com?mail?sub STARTTLS
  • consider setting REDIRECT_REMOTE_USER as default in example
  • example search ldapsearch -x -H ldap://ad-server01:389 -vvv -D "CN=srv_misp,OU=MISP,OU=Serice Accounts,DC=company,DC=com" -W -b "OU=company,DC=company,DC=com" "(mail=name@company.com)(memberOf=CN=MISP-Admin,OU=Service Croups,OU=company_KE,DC=company,DC=com)"
  • Local admin: You will have to change the email of the local admin account to match one in AD or you can technically still make the local admin account work, if it is a requirement. just setup a vhost on another port or domain that points to the same MISP instance, and don't include the Auth config. Then you will be presented with the default login screen there, and can log in with local account(s).
  • it should work for non-debian/non-ubuntu, just replace everywhere it says "apache2" with httpd.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment