Unauthorized SSRF vulnerability in controllers.console.remote_files.RemoteFileUploadApi
Self Checks
- [x] This is only for bug report, if you would like to ask a question, please head to Discussions.
- [x] I have searched for existing issues search for existing issues, including closed ones.
- [x] I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
- [x] [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
- [x] Please do not modify this template :) and fill in all the required fields.
Dify version
1.0.0
Cloud or Self Hosted
Self Hosted (Docker)
Steps to reproduce
The class controllers.console.remote_files.RemoteFileUploadApi will get the URL parameter to initiate the request externally through ssrf_proxy.head, but actually ssrf_proxy.head calls core.helper.ssrf_ proxy.make_request, will also unconditionally outbound request, theoretically if this is a business function, please do the authentication process for the interface, do not let unauthorized users access the
- controllers.console.remote_files.RemoteFileUploadApi
POST /console/api/remote-files/upload HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:135.0) Gecko/20100101 Firefox/135.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Priority: u=0, i
Content-Type: application/json
{"url":"http://192.168.1.94:1234"}
At this point my terminal received the request normally
Restoration Recommendations
If this is a normal function that requires access to a remote address, then it is recommended to authenticate the interface
✔️ Expected Behavior
If this is a normal function that requires access to a remote address, then it is recommended to authenticate the interface
❌ Actual Behavior
No response
Hey @UzJu! I'm here to help you with any bugs, questions, or contributions you have for the project. Let me know how I can assist you!
To address the unauthorized SSRF vulnerability in the RemoteFileUploadApi class, you should implement proper authentication to ensure that only authorized users can access remote URLs. Here's a solution you can consider:
-
Add Authentication: Use the
@login_requireddecorator to ensure that the user is authenticated before accessing the endpoint. -
Authorization Check: Implement a function to verify if the user is authorized to access the specified URL. This function should contain your business logic for authorization.
Here's an example implementation:
from flask_login import login_required
class RemoteFileUploadApi(WebApiResource):
@marshal_with(file_fields_with_signed_url)
@login_required
def post(self, app_model, end_user):
parser = reqparse.RequestParser()
parser.add_argument("url", type=str, required=True, help="URL is required")
args = parser.parse_args()
url = args["url"]
# Check if the user is authorized to access the URL
if not is_user_authorized_to_access_url(end_user, url):
raise RemoteFileUploadError("User is not authorized to access this URL.")
try:
resp = ssrf_proxy.head(url=url)
if resp.status_code != httpx.codes.OK:
resp = ssrf_proxy.get(url=url, timeout=3, follow_redirects=True)
if resp.status_code != httpx.codes.OK:
raise RemoteFileUploadError(f"Failed to fetch file from {url}: {resp.text}")
except httpx.RequestError as e:
raise RemoteFileUploadError(f"Failed to fetch file from {url}: {str(e)}")
file_info = helpers.guess_file_info_from_response(resp)
if not FileService.is_file_size_within_limit(extension=file_info.extension, file_size=file_info.size):
raise FileTooLargeError
content = resp.content if resp.request.method == "GET" else ssrf_proxy.get(url).content
try:
upload_file = FileService.upload_file(
filename=file_info.filename,
content=content,
mimetype=file_info.mimetype,
user=end_user,
source_url=url,
)
except services.errors.file.FileTooLargeError as file_too_large_error:
raise FileTooLargeError(file_too_large_error.description)
except services.errors.file.UnsupportedFileTypeError:
raise UnsupportedFileTypeError
return {
"id": upload_file.id,
"name": upload_file.name,
"size": upload_file.size,
"extension": upload_file.extension,
"url": file_helpers.get_signed_file_url(upload_file_id=upload_file.id),
"mime_type": upload_file.mime_type,
"created_by": upload_file.created_by,
"created_at": upload_file.created_at,
}, 201
def is_user_authorized_to_access_url(user, url):
# Implement your logic to check if the user is authorized to access the URL
return True # Placeholder implementation
This code ensures that the user is logged in and authorized to access the URL before proceeding with the file upload process [1][2].
To continue talking to Dosu, mention @dosu.
Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other
I noticed that Squid's configuration doesn't limit the IP addresses that can be accessed, is this some kind of risk? After all, the interface doesn't need to be authenticated
Personally, I think that if there is a need for an external request, then there must be a permission check on the interface, so that people who do not need to log in, can't call the interface directly.
Hi, @UzJu. I'm Dosu, and I'm helping the Dify team manage their backlog. I'm marking this issue as stale.
Issue Summary:
- An unauthorized SSRF vulnerability was reported in the
RemoteFileUploadApiclass. - You suggested implementing authentication to prevent exploitation.
- There is a potential risk with Squid's configuration not limiting accessible IP addresses.
- Emphasized the importance of permission checks for external requests.
Next Steps:
- Please let us know if this issue is still relevant to the latest version of the Dify repository by commenting here.
- If there is no further activity, this issue will be automatically closed in 15 days.
Thank you for your understanding and contribution!
hi, are there any fixes or workaround yet?
Is this security issue resolved now?
See https://github.com/langgenius/dify/pull/24393#issue-3348714677