Skip to main content

byp4ss3d picoMini by CMU-Africa Solution

A web application hides content behind multiple layers of authentication. Find a way to bypass the controls and retrieve the flag.

Published: April 2, 2026Updated: August 13, 2026

Description

An identity verification portal accepts file uploads but blocks PHP files. Bypass the restriction to achieve remote code execution and read the flag.

Open the file upload portal.

Prepare a webshell and a .htaccess configuration file.

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Attempt direct PHP upload (blocked)
    Observation
    The description says the portal blocks PHP files. The first thing to confirm is what the filter actually checks, so try a plain shell.php upload and read the error to see whether it is extension-based or content-based.
    Trying to upload shell.php is rejected by the extension filter. The server explicitly blocks .php files.
    Learn more

    Extension-based upload filters are a common but weak defense against malicious file uploads. The server checks the file extension against a blocklist (or allowlist) before saving the file. Blocklist approaches - blocking specific extensions like .php, .jsp, .asp - are inherently fragile because attackers can often find alternative extensions that the server still executes.

    This is classified as an unrestricted file upload vulnerability(CWE-434) and appears on OWASP's list of critical web application risks. A secure file upload must validate the file's actual content (MIME type, magic bytes), not just its extension, and must never store uploaded files in a location the web server can execute.

    Common bypass techniques include: uploading with alternative extensions (.php5, .phtml, .phar), double extensions (shell.php.jpg), case variation (shell.PHP), null byte injection (shell.php%00.jpg), and - as used in this challenge - reconfiguring the server itself to execute arbitrary extensions.

  2. Step 2Upload a .htaccess to remap .jpg as PHP
    Observation
    The filter rejects .php extensions but says nothing about Apache configuration files. So upload a .htaccess with an AddType directive and the server will treat an allowed extension like .jpg as executable PHP.
    Create a .htaccess file containing AddType application/x-httpd-php .jpg. This Apache directive tells the server to execute .jpg files as PHP. Upload it to the same directory as future uploads.
    bash
    echo 'AddType application/x-httpd-php .jpg' > .htaccess
    What didn't work first

    Tried: Try uploading shell.php5 or shell.phtml instead of using .htaccess

    Alternative PHP extensions like .php5 and .phtml sometimes execute, but only when the server already has AddHandler or AddType entries for them in its main config. On a hardened install those are absent, so the file is served as plain text. The .htaccess approach works whatever the server config, because it injects the handler directive into the upload directory itself.

    Tried: Upload the .htaccess file but name it htaccess.txt thinking the dot-prefix is cosmetic

    Apache treats a file as a directory configuration override only when the name matches AccessFileName exactly, which is .htaccess by default. A file called htaccess.txt is just text and Apache ignores it. Keep the leading dot and no extension for the directive to take effect.

    Learn more

    .htaccess files are per-directory configuration files that Apache processes before serving any request from that directory. They allow directory owners to override server-wide settings without touching the main Apache configuration. The AddType directive maps a MIME type to file extensions, telling Apache how to handle files with that extension.

    AddType application/x-httpd-php .jpg instructs Apache's mod_php handler to execute any .jpg file as PHP code. Once this .htaccess is in place, every .jpg file in that directory is a potential code execution vector - regardless of whether the extension filter would have blocked it as PHP.

    The key insight is that the application's upload filter only checked the extension of the uploaded file. It did not restrict which configuration files could be uploaded. Servers that allow .htaccess should validate uploaded filenames against a strict allowlist (including hidden files starting with a dot) and ideally store uploads outside the web root entirely.

  3. Step 3Upload a PHP webshell as a .jpg
    Observation
    With the .htaccess in place remapping .jpg to PHP, a minimal webshell named shell.jpg passes the extension filter and still gets interpreted as PHP by Apache. That is remote code execution.
    Create shell.jpg containing a simple PHP command execution payload. Upload it - the .htaccess causes Apache to execute it as PHP despite the .jpg extension.
    bash
    echo '<?php echo system($_GET["cmd"]); ?>' > shell.jpg
    bash
    curl 'https://<host>/uploads/shell.jpg?cmd=cat+/var/www/flag.txt'
    What didn't work first

    Tried: Browse directly to shell.jpg after uploading it before uploading .htaccess

    Without the .htaccess in place, Apache has no instruction to treat .jpg as PHP, so it serves the file as an image and the browser shows garbled content or offers a download. Upload the .htaccess first, so the directive is live before any request reaches the webshell.

    Tried: Use shell.jpg?cmd=cat /flag.txt or cat /flag assuming a common CTF flag path

    The flag location varies per instance. Guessing /flag.txt or /flag may return 'No such file or directory', which makes a working webshell look broken. Here the path is /var/www/flag.txt, and running ls / or find / -name 'flag*' first is what confirms it.

    Learn more

    A webshell is a script uploaded to a web server that allows the attacker to issue operating system commands through HTTP requests. The minimal one-liner <?php echo system($_GET["cmd"]); ?> reads the cmd URL parameter and passes it to the OS via system(), returning the output in the HTTP response. This turns any GET request into a remote command execution interface.

    After uploading, the attacker browses to the file's URL with a ?cmd= query parameter. Because .htaccess remapped .jpg to PHP, Apache passes the file through the PHP interpreter, which executes the shell command. Common targets include cat /etc/passwd, id, ls /, and - in CTF scenarios - reading a flag file at a known path.

    Real-world defenses against this chain include: storing uploads outside the document root (unreachable by URL), disabling .htaccess processing with AllowOverride None, stripping execution permissions from upload directories, and serving user content from a separate origin (subdomain or CDN) that cannot execute server-side code.

Interactive tools
  • JWT DecoderDecode JSON Web Tokens and inspect the header, payload, and signature. Useful for web exploitation challenges.
  • Flask Session DecoderDecode Flask / itsdangerous session cookies. Splits payload, decompresses zlib, parses JSON, and verifies the HMAC signature when given the secret.

Flag

Reveal flag

picoCTF{s3rv3r_byp4ss_...}

.htaccess files configure Apache per-directory - uploading one that remaps file extensions turns any uploaded file into a potential webshell.

Key takeaway

Unrestricted file upload bugs come from validating uploads by extension alone rather than by content type and execution context. A blocklist of dangerous extensions is always incomplete, because a server configuration file like Apache's .htaccess can remap any innocuous extension to an executable handler and make the original filter irrelevant. The real defense is storing uploads outside the web root, so even a successfully uploaded PHP file is unreachable by HTTP.

Related reading

Useful tools for Web Exploitation

Where to go next