Created
April 11, 2024 19:19
-
-
Save gnyman/b5219f1b51a640dce08bcc1d5f3712bd to your computer and use it in GitHub Desktop.
Stupidly simple php file upload server for local networks.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* == Minimal stupidly simple file upload script == | |
* *DO NOT USE THIS IN A UNTRUSTED ENVIRONMENT* | |
* There very little security. I have tried to block the most obvious thing | |
* (uploading of php files) and directory traversal. But this was done in 30 | |
* minutes mostly with a LLM so I wouldn't trust it at all. Use something | |
* better for a untrusted environment. | |
* | |
* With that said, you can run this by placing it in a folder, naming it | |
* index.php then running php -S 0.0.0.0:8000 in that folder. You can then | |
* navigate to the IP of your computer and upload the files to the same | |
* directory. | |
* | |
* Author: @gnyman | |
* Licence: CC0 | |
*/ | |
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES['files']['name'])) { | |
foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) { | |
if (file_exists($tmpName)) { | |
$originalName = $_FILES['files']['name'][$key]; | |
$baseName = pathinfo($originalName, PATHINFO_FILENAME); | |
$extension = pathinfo($originalName, PATHINFO_EXTENSION); | |
// Prevent path traversal and restrict PHP files | |
if (strpos($originalName, '..') !== false || strtolower($extension) === 'php') { | |
echo "Error: Invalid file type or path traversal attempt.\n"; | |
continue; | |
} | |
$uploadPath = $baseName . '.' . $extension; | |
$counter = 1; | |
while (file_exists($uploadPath)) { | |
$uploadPath = $baseName . '_' . $counter++ . '.' . $extension; | |
} | |
move_uploaded_file($tmpName, $uploadPath); | |
echo htmlspecialchars($uploadPath) . "\n"; | |
} | |
} | |
exit; | |
} | |
?> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
body { font-family: Arial, sans-serif; margin: 20px; } | |
input { font-size: 16px; } | |
#fileList li { color: red; } | |
#fileList li.success { color: green; } | |
</style> | |
</head> | |
<body> | |
<input type="file" multiple onchange="uploadFiles()"> | |
<ul id="fileList"></ul> | |
<script> | |
function uploadFiles() { | |
var files = this.files; | |
var form = new FormData(); | |
var list = document.getElementById('fileList'); | |
list.innerHTML = ''; | |
for (var i = 0; i < files.length; i++) { | |
form.append('files[]', files[i]); | |
var item = document.createElement('li'); | |
item.textContent = files[i].name; | |
list.appendChild(item); | |
} | |
fetch('.', { method: 'POST', body: form }) | |
.then(response => response.text()) | |
.then(data => { | |
var uploadedFiles = data.trim().split('\n'); | |
for (var j = 0; j < list.children.length; j++) { | |
if (uploadedFiles.includes(list.children[j].textContent)) { | |
list.children[j].classList.add('success'); | |
} else { | |
list.children[j].style.color = 'red'; | |
list.children[j].textContent += ' - Upload Failed'; | |
} | |
} | |
}); | |
} | |
document.querySelector('input[type=file]').addEventListener('change', uploadFiles); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment