Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File name of 25 characters or more, corrupt the upload_field_name.path in the http header #128

Closed
VisualGPS opened this issue Feb 21, 2020 · 4 comments

Comments

@VisualGPS
Copy link

When passed to the backend and the file name is larger than 24 characters. the path that references the hashed file name is corrupted.

Is this a limitation for http or is this an issue with nginx-upload-module? Not sure.

Working
Header snippet at 24 characters (file name passed from html form: 012345678901234567890123):

------WebKitFormBoundary8tmTmTyfixCtPtbW
Content-Disposition: form-data; name="firmware.name"

012345678901234567890123
------WebKitFormBoundary8tmTmTyfixCtPtbW
Content-Disposition: form-data; name="firmware.content_type"

application/octet-stream
------WebKitFormBoundary8tmTmTyfixCtPtbW
Content-Disposition: form-data; name="firmware.path"

/tmp/0000000026

Not Working (note the path is shortened)
Header snippet at 27 characters (file name: 012345678901234567890123):

------WebKitFormBoundaryjVkl7a9CMIaR0NEK
Content-Disposition: form-data; name="firmware.name"

012345678901234567890123456
------WebKitFormBoundaryjVkl7a9CMIaR0NEK
Content-Disposition: form-data; name="firmware.content_type"

application/octet-stream
------WebKitFormBoundaryjVkl7a9CMIaR0NEK
Content-Disposition: form-data; name="firmware.path"

/tmp/0000000
@VisualGPS VisualGPS changed the title File name of 24 characters or more, corrupt the upload_field_name.path in the http header File name of 25 characters or more, corrupt the upload_field_name.path in the http header Feb 21, 2020
@fdintino
Copy link
Owner

I'm confused, where are /tmp/0000000026 and /tmp/0000000 coming from? This module doesn't save any files in paths that look like that.

@VisualGPS
Copy link
Author

I'm not sure what part of the upload process names the file upload, but this is what nginx named the uploaded file. In this case it was /tmp/0000000026. Below I tried to explain in more detailed what the problem is. The http headers above shows this.

Environment:

  • Embedded Linux on an arm platform
  • Using Buildroot to build nginx and associated modules, kernel, drivers, and other components.

Snippet from nginx.conf:

# File upload
location /upload/ {
	# Store files to this directory
    	upload_store /tmp;
upload_pass @fileupload;
        	
	upload_set_form_field $upload_field_name.name "$upload_file_name";
	upload_set_form_field $upload_field_name.content_type "$upload_content_type";
	upload_set_form_field $upload_field_name.path "$upload_tmp_path";
 	upload_pass_form_field "^submit$|^description$";
			        	
     	upload_max_file_size 100M;
     	client_max_body_size 100M;
     	# Allow everyone access to uploaded files
     	upload_store_access all:rw;
     	upload_cleanup 400 404 499 500-505;
}
location @fileupload {
     	# Pass it along to our file-handler
     	proxy_pass http://localhost:9005;
}

I’ll start from the beginning of the scenario. Please note, I’m using 0000000026 (the hashed file name of the file uploaded) as an example.

  1. User selects a file to upload from the web browser. Html uses a form with input file tag type.
  2. The file is uploaded by the file upload module in nginx and stored in the /tmp/ directory as some sort of numbered hashed file. In the example I gave was “/tmp/0000000026”.
  3. The snippet above will pass on the file name that was selected by the user, the content type, and the hashed file name of the file uploaded (/tmp/0000000026) to @fileupload.
  4. When http://localhost:9005 receives the http header and the file name ($upload_field_name.name) is less than 25 characters, the http header looks good.
  5. When http://localhost:9005 receives the http header and the file name ($upload_field_name.name) is 25 character or more is when the problem occurs. NOTE: the file /tmp/0000000026 does exist at this point.
    a. $upload_field_name.name shows the file name. In this case it was 25 characters of the actual name the user selected.
    b. $upload_field_name.path starts to show corruption. For each character larger than 24 characters a character is removed from the $upload_field_name.path. In this case the hashed file name turned out to be “/tmp/000000002”. Note that the “6” is missing. If name $upload_field_name.name was 26 characters long, then $upload_field_name.path would yield “/tmp/00000000”. Note the last two characters “26” are missing.
    c. The http header passed to the server located at localhost:9005 shows this behavior.

I hope this make sense. Nonetheless, I’ll provide any information needed. I can rebuild and place logging where ever needed.

@fdintino
Copy link
Owner

fdintino commented Feb 29, 2020

I've tried replicating your issue; here's the curl command I'm running:

curl -i  -X POST   -F file=@/tmp/012345678901234567890123456789012345678901234567890123456  http://127.0.0.1:1984/upload/

In the proxy-pass location, I echo back the form data. Here's what gets returned:

file.content_type = application/octet-stream
file.name = 012345678901234567890123456789012345678901234567890123456
file.path = /tmp/upload/store/7/0000246917

One thing I notice is that the files created by ngx_create_hashed_filename usually start with a directory named 0-9. I don't know if that's a behavior that changes with different nginx versions. Out of curiosity, what do you get for nginx -V?

@VisualGPS
Copy link
Author

I'm closing the issue. I've deleted the repo cache, rebuilt buildroot, all associated software, and the problem magically went away. Although, keeping an eye on the code. Thanks for your comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants