HTML/PHP : File Upload Portal


I had a requirement to be able to receive a file from the third-party source that would be uploaded to public files server where it would be scanned and then I’ll pick it up after the scam was completed for security, so I thought how hard can it be to write a simple script to do that?

Well not very really.......this is it running here (this service is now offline)

Virus Scan

This solution would upload files from the "outside" sources to a folder on the webserver that is protected by ClamAV so they get a good virus scan when they are downloaded, however these files will also be scanner with other "internal" technologies before they are available to end users.

Trust IP Firewall

I would also consider a firewall based IP address to only allow trusted IP addresses from accessing the website to prevent further unauthorised actions, this could easily be an NSG or other access control list.

MD5 Hash Checking

If this 3rd party or sending supplier support MD5 hashes then the server can validate these as well, this would not be a website activity, but more a human intervention for the moment, as this can be bypassed with the MD5 has changer.

Criteria

I did not want a website it just allowed you to upload any files, that would get abused, so let’s get the criteria right before we start doing getting coding.

  1. A bright red background that’s very simple to use and tell you what it does
  2. A requirement to enter a valid code from a file, not in a web served directory
  3. The code box needs to be a password for you so you can’t see what’s entered (from shoulder surfers)
  4. The option to upload multiple files at the same time
  5. When you entered the code and selected the files that will be uploaded to a "/upload" directory with the name of the code you’ve entered as the folder
  6. Site needs to be protected with reCAPTCHAv3 to stop "bots"
  7. There for my requirements need to be a file upload limit of 2 MB
Welcome Page

This is what I came up with and I like the simplistic design, it does what it says on the tin.



First we need the welcome page that will be in html format, you will need to give the correct keys for reCAPTCHA which will be covered later on in this guide.

<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>File Upload : Welcome</title>
  <link rel="stylesheet" href="./style.css">
 <!-- Include reCAPTCHA v3 script -->
  <script src="https://www.google.com/recaptcha/api.js?render=<site_key>"></script>
  <script>
    // Execute reCAPTCHA v3 when the page is loaded
    grecaptcha.ready(function() {
      grecaptcha.execute('<server_key>', {action: 'upload'}).then(function(token) {
        // Add the reCAPTCHA token to the form data
        document.getElementById('recaptcha_token').value = token;
      });
    });
  </script>
</head>
<body>
  <br>
  <h1>A6N Networks Upload <span>This will upload a file to a secure server that is subject to virus/malware<br>These files will only be accessed by authorized employees<br>There is currently a 2MB limit on uploads!!!</span></h1>

  <form action="upload.php" method="post" enctype="multipart/form-data">
  <br>
  <div>
      <label for="upload_id">Upload ID:</label>
      <input type="password" id="upload_id" name="upload_id" required>
    </div>
    <div class="custom-file-upload">
      <input type="file" id="file" name="myfiles[]" multiple />
    </div>
    <br><br><br><br>
    <input type="submit" value="Upload">
  </form>
  <p>Remember <a href="#">Privacy Policy</a> applies to anything uploaded</p>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="./script.js"></script>
</body>
</html>

reCAPTCHA Setup

This is required for the site protection, first you need to navigate to reCAPTCHA admin website which is here

Once here you will need to click on the "+" icon on the upper right then you will need to know the label and the type which for this example is v3 and invisible, you will also need to know the website it will be used on - once you have this submit the details.


Then from the main menu choose this website and click the cog icon (or the settings) then you need the site key and the secret key, this is in my HTML anyway so not really that secret - but the domain controls usage!


Upload Button : Calls post.php to "do the magic"

When you click the upload button you call post.php which looks like this, first it checks that the ID is in the file, ensure this file it not in your webserver activate website directory that would be a security problem, then it does the magic with the upload and folders, the folder that is served by Apache is the "html" folder.

If you get the code correct you end up on the "success" webpage and it you get it wrong or enter an invalid one you end up the "failure" webpage.

<?php
// Define the path to the validid.txt file outside the web server folder
$validIdsFile = '/var/www/online.txt';

// Check if files were uploaded
if (isset($_FILES['myfiles']) && isset($_POST['upload_id'])) {
    // Retrieve the upload ID
    $upload_id = $_POST['upload_id'];
    
    // Load valid IDs from the file
    $valid_ids = file($validIdsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    
    // Check if the entered upload ID is valid
    if (in_array($upload_id, $valid_ids)) {
        // Create a folder with the upload ID if it doesn't exist
        $uploadDirectory = 'uploads/' . $upload_id . '/';
        if (!file_exists($uploadDirectory)) {
            mkdir($uploadDirectory, 0777, true);
        }
        
        // Iterate through uploaded files
        foreach ($_FILES['myfiles']['tmp_name'] as $key => $tmp_name) {
            $file_name = $_FILES['myfiles']['name'][$key];
            $file_tmp = $_FILES['myfiles']['tmp_name'][$key];
            
            // Move uploaded file to the folder with the upload ID
            move_uploaded_file($file_tmp, $uploadDirectory . $file_name);
        }
        
        // Redirect the user to a success page
        header("Location: <success html page in https format>");
        exit; // Make sure to stop further script execution
    } else {
        // Redirect the user to the error page
        header("Location: <fail html page in https format>");
        exit; // Make sure to stop further script execution
    }
} else {
    // Redirect the user to the error page
    header("Location: <fail html page in https format>");
    exit; // Make sure to stop further script execution
}
?>

Success Website - Green, bold and clean

This is what the success website looks like, there could be an option to add a automatic redirect here rather than a click here, but I think this works for now.

Note : The HTML is really not required for this, its very simple the CSS does all the formatting



Failure : Red, bold and clean

This is what happens when you enter an incorrect code or try to make one up, you get a failed screen and the process ends there, you need to use the back button to try again.

Note : The HTML is really not required for this, its very simple the CSS does all the formatting


Adding an Approval website

If you then want to add a portal where you can enter your codes with a valid token, or in this case an IP address, stopping everyone from doing this defeating the point, I started with a basic form that captured all the details


The HTML for that is very simple this is how it looks:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload Code Authorization</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>Upload Code Authorization</h1><br>
        <form action="process.php" method="post">
        This process requires a token, if this token is not present in your request then the request will fail!<>
            <label for="name">Name:</label>
            <input type="text" id="name" name="name" required><br><br>
            <label for="email">Email Address:</label>
            <input type="email" id="email" name="email" required><br><br>
            <label for="company">Company Name:</label>
            <input type="text" id="company" name="company" required><br><br>
            <button type="submit">Submit</button>
        </form>
    </div>
</body>
</html>

Capturing data and creating the "valid" codes file

The HTML website does nothing without the PHP backend code in process.php that looks like this and this does all the magic.

<?php
// Define approved IP addresses
$approved_ips = array(
    '10.2.50.11', // Trusted IP
    '123.456.789.2', // Trusted IP
    // Add more approved IP addresses as needed
);

// Get visitor's IP address
$visitor_ip = $_SERVER['REMOTE_ADDR'];

// Check if visitor's IP is in the approved list
if (in_array($visitor_ip, $approved_ips)) {
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
        $name = $_POST["name"];
        $email = $_POST["email"];
        $company = $_POST["company"];

        // Generate a unique code (20 characters)
        $unique_code = substr(md5(uniqid(rand(), true)), 0, 20);

        // Specify the file path for storing unique codes
        $file_path_all_data = '/var/www/codes.txt';
        $file_path_code_only = '/var/www/online.txt';

        // Store all data (including code) in one file
        $data_all = "$name, $email, $company, $unique_code\n";
        file_put_contents($file_path_all_data, $data_all, FILE_APPEND | LOCK_EX);

        // Store only the code in another file
        $data_code_only = "$unique_code\n";
        file_put_contents($file_path_code_only, $data_code_only, FILE_APPEND | LOCK_EX);

        // Redirect to a success page
        header("Location: https://testgrid.a6n.co.uk/authorise/sucess.html");
        exit();
    } else {
        // Redirect back to the form if accessed directly
        header("Location: index.html");
        exit();
    }
} else {
    // Redirect unauthorized access to an error page
    header("Location: https://testgrid.a6n.co.uk/authorise/fail.html");
    exit();
}
?>

Files of Magic for access

The following two files do all the magic with the data, the first one writes the data you have entered to "codes.txt" and the second one writes the generated code from the script to "online.txt" this is the same file that the previous script looks at for valid access codes.

        $file_path_all_data = '/var/www/codes.txt';
        $file_path_code_only = '/var/www/online.txt';

Previous Post Next Post

نموذج الاتصال