-2

i try to great users Nickname (words / links).

-Words, work good

-problem links not work (i like to put users identify as link) code

<!--
<!--
<?php
if (isset($_GET['enSubmit']) && isset($_GET['uname']) && isset($_GET['rname'])){
    echo'<meta http-equiv="refresh" content="10">';
    $room=$_GET['rname']; 
    $uname=$_GET['uname'];
    if (!is_dir($room)) mkdir($room);
    $files = scandir($room);
    foreach ($files as $user){
        if ($user=='.' || $user=='..') continue;
        $handle=fopen("$room/$user",'r');
        $time = fread($handle, filesize("$room/$user"));
        fclose($handle);
        if ((time()-$time)>20) unlink("$room/$user");
    }
    $contents='';
    $filename="$room.txt";
    if (file_exists($filename)){
        $handle = fopen($filename, "r");
        $contents = fread($handle, filesize($filename));
        fclose($handle);    
    }
    $handle = fopen("$room/$uname", "w");
    fwrite($handle, time());
    fclose($handle);

    $files = scandir($room);
    $users='';
    foreach ($files as $user) if ($user!='.' && $user!='..') $users.=$user."\n";

    if (isset($_POST['Send'])){
        $text=$_POST['txt'];
        $contents.="$uname: $text";
        $handle = fopen("$filename", "a");
        fwrite($handle, "$uname: $text\n");
        fclose($handle);
    }
?>
<body OnLoad="document.myform.txt.focus()">
<form action="" method="post" name="myform">

    <tr>

    <textarea readonly="readonly"  contenteditable="false"  name="txtusers" style=";width: 163px; height: 365px; background-color: #D1F8D8; font-family: 'times New Roman', Times, serif; font-size: 12pt; font-weight: bold; text-align: center;"><?php echo $users?></textarea></td>
    </tr>

   </table>
</form>

<?php
}else {
?>
   <form method="get" action="">
   <table style="border: 1px solid #000000;width: 452px" align="center">
   <tr>
   <td style="font-family: 'Times New Roman', Times, serif;font-size: 17pt;text-align: left; width: 432px; color: #2214B9;;border-style: solid;border-width: 1px;">Nick Name:</td>
    <td style="border-style: solid; border-width: 1px; font-family: 'Times New Roman', Times, serif; font-size: 17pt; text-align: left; color: #2214B9; width: 430px;">
    <input name="uname" style="font-size: medium; width: 260px; color: #B01919;"></td>
</tr>
     <tr>
     <td style="font-family: 'Times New Roman', Times, serif;font-size: 17pt;text-align: left; width: 432px; color: #2214B9;border-style: solid;border-width: 1px;">Select Room:</td>
    <td style="border-style: solid; border-width: 1px; font-family: 'Times New Roman', Times, serif; font-size: 17pt; text-align: left; color: #2214B9; width: 430px;">
    <select name="rname" style="width: 260px; font-size: medium; color: #B01919;">
    <option selected="">project 1</option>
    </select></td>
   </tr>
    <tr>

    <td style="font-family: 'Times New Roman', Times, serif;font-size: 17pt;text-align: center; color: #2214B9; border-left-style: solid; border-left-width: 1px; border-right-style: none; border-right-width: medium; border-top-style: solid; border-top-width: 1px; border-bottom-style: solid; border-bottom-width: 1px; padding-top:10px;padding-bottom:10px" colspan="2">
    <input name="enSubmit" style="width: 118px; height: 63px; font-size: 30pt; font-family: 'Times New Roman', Times, serif; color: #19B024;" type="submit" value="Enter"></td>
    </tr>
   </table>
    </form>
     <?php
     }
     ?>
      <script>
     el=document.myform.txtt
     if (typeof el.selectionStart == "number") {
     el.selectionStart = el.selectionEnd = el.value.length;
     } else if (typeof el.createTextRange != "undefined") {
     el.focus();
     var range = el.createTextRange();
     range.collapse(false);
     range.select();
     }</script>


    </body>

let us say i want type users identify as link so when i try for example

https://test.com/user_adam

i got error (it work good if username not have "/") :

Warning: fopen(project 1/https://test.com/user_adam): failed to open stream: No such file or directory in C:\xampp\htdocs\linkey\live.php on line 24

Warning: fwrite() expects parameter 1 to be resource, bool given in C:\xampp\htdocs\linkey\live.php on line 25

Warning: fclose() expects parameter 1 to be resource, bool given in C:\xampp\htdocs\linkey\live.php on line 26

the link which i tried

http://localhost/linkey/live.php?uname=https://test.com/user_adam&rname=project%201&enSubmit=Enter
Diana adam
  • 49
  • 7
  • 2
    Well the `fopen()` failed obviously – RiggsFolly Feb 06 '19 at 18:46
  • 2
    I cant read this with the indentation all over the place... For example at first glance it looks like this if condition `if ($user=='.' || $user=='..') continue;` ends where the foreach actually ends, because of the indentation. Readability is always the number 1 concern for me when I code, If I cant glance at it and see how it's structured, how can I make sense of it? – ArtisticPhoenix Feb 06 '19 at 18:47
  • HTML? Where do you start the ``
    – RiggsFolly Feb 06 '19 at 18:53
  • Another big issue for me is what I call "Variable Confusion" which is where variables are not sensible named, a few examples `foreach ($files as $user){` A file is not a `$user` and here is another `$room=$_GET['rname']; $uname=$_GET['uname'];` One is named good the other not so much. This may not seem like a big deal, but it goes back to readability. See I think you are saying your missing the `links` but those are really called `users` except that `user` is a file. So it's very confusing as to what is what. – ArtisticPhoenix Feb 06 '19 at 18:57
  • I won't really get into how the organization and logic is all over the place, or how your vulnerable to Directory Transversal attacks. I wish I could help you, but I don't even know which of the several `fopen` calls is failing. It looks like you are trying to open a file named this `project 1/https://test.com/user_adam` but I can't be sure where that comes from. If that is true, well that's obviously a bad filename. Another issue that ties in with the Directory Transversal, is that we cant be sure the code is fine and the GET values are bad as it's possible to pass all kinds of stuff in GET – ArtisticPhoenix Feb 06 '19 at 19:06
  • I think the only way to solve this is if you can explain "exactly" what this means `(it work good if username not have "/")` What is username, is it this: `users identify as link so when i try for example https://test.com/user_adam` if so which `/` – ArtisticPhoenix Feb 06 '19 at 19:12
  • If you are trying to separate the username from this link `https://test.com/user_adam` Then do `$username = ltrim(strrchr('https://test.com/user_adam', '/'),'/');` see this [Sandbox](http://sandbox.onlinephpfunctions.com/code/8115a87abf33a61613228f36b2e9cfee8be68610) This assumes that username will be at the end of a string with a `/` in it. You can also use `explode` and `end` [Sanbox](http://sandbox.onlinephpfunctions.com/code/2da60778891a4e04eaf1d7af985dcaf72cd79346) which is a bit more flexible but less performant. – ArtisticPhoenix Feb 06 '19 at 19:19
  • Possible duplicate of [Reference - What does this error mean in PHP?](https://stackoverflow.com/questions/12769982/reference-what-does-this-error-mean-in-php) – Mike Doe Feb 06 '19 at 20:05

1 Answers1

1

Ok I think I figured it out.

Basically it's bad input, the file your having issues with based on the error

Warning: fopen(project 1/https://test.com/user_adam): failed to open stream: No such file or directory

I would really hope you do not have files named this project 1/https://test.com/user_adam. But based on what you go on to say:

let us say i want type users identify as link so when i try for example https://test.com/user_adam i got error (it work good if username not have "/") :

And this:

http://localhost/linkey/live.php?uname=https://test.com/user_adam&rname=project%201&enSubmit=Enter

Which shows me that uname = uname=https://test.com/user_adam and rname = rname=project 1. Or in English rname is the folder, and uname is the users name. Which is all dandy until you put a URL in there.

What I would do is something like this:

 $uname=$_GET['uname'];
 $arr_name = expode('/', $uname); //this offers a small amount of protection too (see below)
 $uname = end($arr_name);

Which in this case will leave $uname with everything after the last / or user_adam. Then your path becomes project 1/user_adam.

Directory Transversal

However, you are wide open for directory transversal attacks (digging into the code it's even worse then I first suspected). This is where a malicious user can pass things like this (%2F is / in url encoding)

  http://localhost/linkey/live.php?rname=..%2F..%2Fsomefolder&uname=foo&enSubmit=bar

What that does, is scandir() will look for this folder ../../somefolder. Now say that folder contains all your PHP files then it will open them and likely delete them with unlink:

if (isset($_GET['enSubmit']) && isset($_GET['uname']) && isset($_GET['rname'])){
    echo'<meta http-equiv="refresh" content="10">';

    $room=$_GET['rname'];  //../../somefolder
    $uname=$_GET['uname']; //foo

    if (!is_dir($room)) mkdir($room);

    $files = scandir($room); //../../somefolder
    foreach ($files as $user){
        //$user = somefile.php
        if ($user=='.' || $user=='..') continue; //fails (or false here)

        $handle=fopen("$room/$user",'r'); // ../../somefolder/somefile.php

        $time = fread($handle, filesize("$room/$user")); //time will be a non number string, likly
        fclose($handle);
        if ((time()-$time)>20) unlink("$room/$user"); //time() - string(or 0) is almost always > 20 ... or TRUE here.
    }
 ....
}

You can test the condition for unlink here by assuming that the first line of a php file starts with <?php. In any case we can assume it will be a non-numeric string. Then when it's converted to an integer ( converted by subtraction ) its number value is actually 0. Then time() - 0 is time() which is way more then 20.

  var_dump( (time()-'<?php')>20); //true

Sandbox

And because that condition cannot stop it this next bit runs:

 unlink("$room/$user"); //unlink('../../somefolder/somefile.php')

Basically by passing that "stuff", If I know the location of a PHP file that the user running PHP ( on the server ) has access to I can delete it. Or I can basically delete any "known" files from any folder on your server that PHP can access. How would I know them, well all I have to do is look at the URL in most cases. I would have to test this to be sure, but I don't see anything that indicates it would not work. God forbid someone puts ../../public_html in there and wipes your site from the face of the earth (hope you have backups of your server)...

You might think well this is just a start project. But what if you or a user of yours accidentally puts in a folder that contains PHP files or other files you don't want deleted? It can happen.

This is really Important, so I thought I should mention it.

Cheers.

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38