2021-01-26 HTB Waldo walkthrough

目标机IP:10.10.10.87

信息搜集

照常进行nmap扫描
nmap -sC -sV -A -oN 10.10.10.87.txt 10.10.10.87

nmap.png

发现80端口开放,扫描目录无果,进去探测一番

Get user.txt

枚举

点进网站发现没什么东西,顺手点开源码发现list.js有一些值得注意的内容

function writeList(listNum, data){ 
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST","fileWrite.php",false);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send('listnum=' + listNum + '&data=' + data);
    if (xhttp.readyState === 4 && xhttp.status === 200) {
        return xhttp.responseText;
    }else{
    }
}


function deleteList(listNum){ 
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST","fileDelete.php",false);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send('listnum=' + listNum);
    if (xhttp.readyState === 4 && xhttp.status === 200) {
        listLists();
        return xhttp.responseText;
    }else{
    }
}

function readDir(path){ 
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST","dirRead.php",false);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send('path=' + path);
    if (xhttp.readyState === 4 && xhttp.status === 200) {
        return xhttp.responseText;
    }else{
    }
}


function readFile(file){ 
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST","fileRead.php",false);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send('file=' + file);
    if (xhttp.readyState === 4 && xhttp.status === 200) {
        return xhttp.responseText;
    }else{
    }
}

这四个函数分别利用XHR访问四个不同的php文件,而且貌似进行一定程度上敏感的读写操作,十分值得注意。
那么现在就构造出了一种攻击思路:
将反弹webshell写入一个php文件->对文件进行访问获取shell
但是接下来进行枚举过程中,发现了一些问题:

首先读所有的文件,把代码读下来:

fileRead.php
<?php
if($_SERVER['REQUEST_METHOD'] === "POST"){
$fileContent['file'] = false;
header('Content-Type: application/json');
if(isset($_POST['file'])){

    header('Content-Type: application/json');
    $_POST['file'] = str_replace( array("../", "..\""), "", $_POST['file']); ../ .."
    if(strpos($_POST['file'], "user.txt") === false){
        $file = fopen("/var/www/html/" . $_POST['file'], "r");
        $fileContent['file'] = fread($file,filesize($_POST['file']));  
        fclose();
    }
    }
    echo json_encode($fileContent);
}


fileWrite.php
<?php

if($_SERVER['REQUEST_METHOD'] === "POST"){
    header('Content-Type: application/json');
    $condition['result'] = false;
    if(isset($_POST['listnum'])){
        if(is_numeric($_POST['listnum'])){
            $myFile = "/var/www/html/.list/list" . $_POST['listnum'];
            $handle = fopen($myFile, 'w');
            $data = $_POST['data'];
            fwrite($handle, $data);
            fclose();
            $condition['result'] = true;
        }
    }
    echo json_encode($condition);
}

fileDelete.php
<?php
if($_SERVER['REQUEST_METHOD'] === "POST"){
    if(isset($_POST['listnum'])){
        header('Content-Type: application/json');
        if(is_numeric($_POST['listnum'])){
            $myFile = "/var/www/html/.list/list" . $_POST['listnum'];
            unlink($myFile);
            header('Content-Type: application/json');
            echo '[true]';
        }else{
        header('Content-Type: application/json');
        echo '[false]';
    }
}else{
    header('Content-Type: application/json');
    echo '[false]';
}
}

dirRead.php
<?php

if($_SERVER['REQUEST_METHOD'] === "POST"){
    if(isset($_POST['path'])){
        header('Content-type: application/json');
        $_POST['path'] = str_replace( array("../", "..\""), "", $_POST['path']);
        echo json_encode(scandir("/var/www/html/" . $_POST['path']));
    }else{
        header('Content-type: application/json');
        echo '[false]';
    }
}

发现文件写入过程中对文件名有is_numeric限制,文件读取和目录读取过程有preg_replace进行目录限制。
因此没办法直接写入php文件进去,思路中断。

换个思路

preg_replace是可以绕过的,利用重写的方式:
..././ => ../
对各种系统里的文件进行读取后,在用户目录下发现了令人感兴趣的东西:
ssh的私钥
最终通过ssh私钥登录成功获取到user.txt

getuser.png

Get root.txt

更换账户

从我的角度来讲这点还是挺难的
最开始还是用LinEnum来进行枚举,然而没有发现任何有用的线索
一时之间卡在这里不知道该怎么处理才好
后面突然想到之前拿到的monitor私钥在nobody账户,那么用nobody直接ssh连接monitor不知是否可行
尝试后发现可行:

ssh

发现shell受限,利用ssh强制转换shell
ssh -i .ssh/.monitor monitor@10.10.10.87 -t sh
app-dev目录下有个logmonitor应用,查看logmonitor.c可以看到能够利用logMonitor监控各种日志

/*******************************************
*
*This is an application to print out common log files
*
********************************************/

#include "logMonitor.h"

void printUsage() {
    printf("Usage: %s [-aAbdDfhklmsw] [--help]\n", PROGRAMNAME);
}


int main(int argc, char** argv){
        int opt = 0;
        char filename[26];
        {
                //temporary variables for parsing
                static struct option long_options[] ={
                        /* These options don’t set a flag.
                        We distinguish them by their indices. */
                        {"auth", no_argument, 0, 'a'},
                        {"alternatives", no_argument, 0, 'A'},
                        {"btmp", no_argument, 0, 'b'},
                        {"dpkg", no_argument, 0, 'd'},
                        {"daemon", no_argument, 0, 'D'},
                        {"faillog", no_argument, 0, 'f'},
                        {"help", no_argument, 0, 'h'},
                        {"kern", no_argument, 0, 'k'},
                        {"lastlog", no_argument, 0, 'l'},
                        {"messages", no_argument, 0, 'm'},
                        {"syslog", no_argument, 0, 's'},
                        {"wtmp", no_argument, 0, 'w'},
                        {0,0,0,0}
                };
                //parse the command line arguments
                int option_index = 0;
                while((opt = getopt_long (argc, argv, "aAbdDfhklmsw", long_options, &option_index)) != -1 ){
                        switch (opt) {
                                case 'a' :
                                        strncpy(filename, "/var/log/auth.log", sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'A' :
                                        strncpy(filename, "/var/log/alternatives.log", sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'b' :
                                        strncpy(filename, "/var/log/btmp",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'd' :
                                        strncpy(filename, "/var/log/daemon.log",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'D' :
                                        strncpy(filename, "/var/log/dpkg.log",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'f' :
                                        strncpy(filename, "/var/log/faillog",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'h' :
                                        printUsage();
                                        exit(1);
                                case 'k' :
                                        strncpy(filename, "/var/log/kern.log",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'l' :
                                        strncpy(filename, "/var/log/lastlog",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'm' :
                                        strncpy(filename, "/var/log/messages",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 's' :
                                        strncpy(filename, "/var/log/syslog",sizeof(filename));
                                        printFile(filename);
                                        break;
                                case 'w' :
                                        strncpy(filename, "/var/log/wtmp",sizeof(filename));
                                        printFile(filename);
                                        break;
                                default:
                                        printUsage();
                                        exit(EXIT_FAILURE);
                        }
                }
        }
        return 1;
}

但是实际运行,并没有足够权限,这一点十分奇怪。
进入目录下v0.1版本,发现0.1版本有权限,上网搜索一下是linux capabilities的问题。
用户sh有tac权限,直接读取 root.txt
完事

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • writeup链接: https://pan.baidu.com/s/1mip9WaG 密码: ypza 获取权限...
    苏州暮雨阅读 4,540评论 0 0
  • 概述 目标靶机是一台Linux机器,部署了一个网站,但是网站被人日了,黑客留下了一些线索和工具在服务上,我们需要利...
    半夜菊花茶阅读 4,520评论 0 0
  • 总算是挺过了期末12门的魔鬼考试日程,迎来了寒假......这次寒假打算学的还挺多的,也希望自己能坚持学习,把知识...
    byc_404阅读 4,371评论 0 2
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 11,043评论 0 5
  • 城空了,有树长出来 我的城死了 铸起它的人,杀死它的人 不愿因为这件事而骄傲 一座城的终结 永远因为终结这件事而显...
    于十六阅读 7,926评论 6 17

友情链接更多精彩内容