New GitHub issue #95499 from cdiemel:<br>

<hr>

<pre>
# Feature or enhancement

The simple HTTP Server from the command line ```python3 -m http.server 80``` only supports ```HEAD``` and ```GET``` requests. I believe it would be beneficial to also allow ```PUT``` requests to allow uploading to the folder where the ```http.server``` module was started.

# Pitch

Currently ```HEAD``` and ```GET``` requests are implemented in stdlib as a PoC/demo of functionality.  Adding a ```PUT``` demo in the code would provide the same PoC/demo of functionality as well as be a feature add for many users in the python community.  The included ```http.server``` is referenced frequently not only to demo simple websites but also as a quick and efficient way to move files from one system to another.  

### Functionality
This is the directory structure I created for testing. 
```file3.txt``` is a simple text file.
```
└── 1
    └── 2
        └── 3
            ├── 4
            │   └── 5
            └── file3.txt

5 directories, 3 files
```
 The web server is started in directory 3 with the command ```python3 -m http.server 80``` and can see the following directory tree.
```

├── 4  
│   └── 5   
└── file3.txt
                                                           
2 directories, 2 files
```
When initially writing a file the server returns ```HTTP 201 Created```
Command: ```curl -X PUT http://127.0.0.1/4/file4.txt -T file3.txt```
1st Response (client): ```"file4.txt" saved```
1st Response (server): ```127.0.0.1 - - [31/Jul/2022 09:52:40] "PUT /4/file4.txt HTTP/1.1" 201 -```

When overwriting a file the server returns ```HTTP 200 OK```
Subsequent Responses (client): ```"file4.txt" overwritten```
Subsequent Responses (server): ```"127.0.0.1 - - [31/Jul/2022 09:52:43] "PUT /4/file4.txt HTTP/1.1" 200 -```


When trying to put a file into a folder that does not exist the server returns ```HTTP 400 Bad Request```
Command: ```curl -X PUT http://127.0.0.1/5/file4.txt -T file3.txt ```
Response (client): ```"file4.txt" unable to be uploaded```
Response (server): ```127.0.0.1 - - [31/Jul/2022 09:53:33] "PUT /5/file4.txt HTTP/1.1" 400 -```

Directory structure after above 3 commands.
```
.
├── 4
│   ├── 5
│   └── file4.txt
└── file3.txt

2 directories, 3 files
```

### Security Concerns
Security concerns were brought up in the [discussion](https://discuss.python.org/t/adding-put-functionality-to-http-server/17745) about the riskiness of adding this feature.  There seems to be little possibility of trying to upload and run a reverse shell because simple demo HTTP server does not interpret any of the code, it reads it as text/binary then sends it out.  I attempted to subvert the process and was only able to get the new feature to serve me HTTP. 


I used the included path functionality from ```self.translatepat()``` and added a few checks in the PUT function to ensure that you cannot place files outside of the current directory tree.  I tried various different versions of ```../../``` and ```./../``` and well as URL encoding to get files placed in odd places and was unable to get them outside of the directory tree I had created.  
Command: ```curl -X PUT http://127.0.0.1/../../../../../../../../dir_traversal.txt -T file3.txt ```
Response (client): ```"dir_traversal.txt" saved```
```
.
├── 4
│   ├── 5
│   └── file4.txt
├── dir_traversal.txt
└── file3.txt

2 directories, 4 files
```
Attempted directory traversal with url-encoding
```../../``` encodes to ```%2E%2E%2F%2E%2E%2F```
```./.././../``` encodes to ```%2E%2F%2E%2E%2F%2E%2F%2E%2E```

Command: ```curl -X PUT http://127.0.0.1/4/5/%2E%2E%2F%2E%2E%2F/dir_traversal3.txt -T file3.txt```
Response (client): ```"dir_traversal3.txt" saved```
Response (server): ```127.0.0.1 - - [31/Jul/2022 10:14:00] "PUT /4/5/%2E%2E%2F%2E%2E%2F/dir_traversal2.txt HTTP/1.1" 200 -```

Command: ```curl -X PUT http://127.0.0.1/4/5/%2E%2F%2E%2E%2F%2E%2F%2E%2E/dir_traversal4.txt -T file3.txt```
Response (client): ```"dir_traversal4.txt" saved```
Response (server): ```127.0.0.1 - - [31/Jul/2022 10:14:36] "PUT /4/5/%2E%2F%2E%2E%2F%2E%2F%2E%2E/dir_traversal3.txt HTTP/1.1" 200 -```
```
.
├── 4
│   ├── 5
│   └── file4.txt
├── dir_traversal2.txt
├── dir_traversal3.txt
├── dir_traversal4.txt
├── dir_traversal.txt
└── file3.txt

2 directories, 7 files
```
It is possible to attempt to craft custom code to exploit the ```shutil.copyfileobj()``` command inside the ```self.copyfile()``` method however I was unable to readily find any examples online of that happening online. Based on the above tests I believe having ```PUT``` ability is no more risky than having ```GET``` ability and complements the already implemented ```GET``` function.

# Previous discussion

[https://discuss.python.org/t/adding-put-functionality-to-http-server/17745](https://discuss.python.org/t/adding-put-functionality-to-http-server/17745)


</pre>

<hr>

<a href="https://github.com/python/cpython/issues/95499">View on GitHub</a>
<p>Labels: type-feature</p>
<p>Assignee: </p>