- What: ZeroPath CTFs based on real CVEs
- Impact: Educational resource for exploit development
ZeroPath Exploit Development CTFs Introduction Want to learn how to exploit complex real world vulnerabilities, but arenât sure where to start? Weâve just released zeropath-ctf , a set of self-contained exploit development exercises based on CVEs from the CISA Known Exploited Vulnerabilities list, along with hints and solutions in case you get stuck. Launching a CTF for CVE-2017-1000367 Background Our CTFs try to walk a middle course between two bad alternatives: On the one hand, diving right into checking out large open source projects with known vulnerabilities can be daunting for a beginner⌠hundreds of thousands of lines of irrelevant code, hours invested getting the application built, configured and running in a sandbox in just the right way, all to try to develop an exploit without a lot of reliable, distilled guidance. On the other, intentionally vulnerable apps or toy vulnerabilities tend to lack the complexity and subtlety of real vulnerabilities⌠developing exploits for them is easy, but youâre not exercising all the muscles you need to do it for real. To solve this problem ZeroPathâs shapeshifter vulnerability generation suite analyzes real world vulnerabilities and produces standalone synthetic lookalikes that prove-ably contain the same key flaws and structure, along with working exploits and walkthroughs for both LLM and human consumption. Weâve used shapeshifter to create CTFs for 10 CVEs, including well-known issues like Baron Samedit, and a range of flaw types, like heap overflows, command injections and TOCTOU race conditions. Each one is packaged in a docker image with a harness around it to verify solutions and walk you through the process of developing your exploit. Video Walkthrough This video walks you through the core functionality of the CTF suite: If youâd prefer written instructions, our README.md is a good starting point. Technology Behind the CTFs Overview These CTFs are only useful if shapeshifter-produced vulnerabilities do in fact mirror the key structure of the real world vulnerabilities theyâre based on. In future posts, weâll go into more detail about how we verify this, and how we apply these synthetic vulnerabilities to benchmarking SAST solutions at scale. Here, weâll do a quick walkthrough of the original issue one of the synthetics is based on, highlighting the key points of similarity. CVE-2017-1000367 Overview CVE-2017-1000367 is a well-known issue in sudo. Itâs a little more complex than many demo vulnerabilities so, itâs a perfect one to dive deeper with to understand how shapeshifter preserves the complexity that matters while still distilling the vuln down to its essence. The heart of the bug is two flaws â one involving improper parsing of user input and another involving trusting devices in world-writable directories, stacked with two exploitable race conditions. Flaw 1: Unsafe parsing of user-provided input The first bug that contributes to the vulnerability is in sudo_ttyname_dev(), which runs at application startup. This function opens /proc/<pid of sudo>/stat, which is a simple text file, and tries to parse it to get the current tty number. Everything starts in `get_process_ttyname()` (`src/ttyname.c:479`). On Linux, sudo reads `/proc/[pid]/stat` to discover its controlling terminal's device number. This file looks like: 1234 (bash) S 1233 1234 1234 34818 1234 ... The fields are space-separated, and field 7 is `tty_nr`. The parser counts spaces to find it: // src/ttyname.c:497-504 char * cp = line ; char * ep = line ; int field = 0 ; while ( * ++ ep != '\0' ) { if ( * ep == ' ' ) { * ep = '\0' ; if ( ++ field == 7 ) { dev_t tdev = strtonum ( cp , INT_MIN , INT_MAX , & errstr ) ; The bug: field 2 (comm) is the process name in parentheses. This doesnât seem like user-controlled input, but it is: the attacker can launch the process using a symlink, and the name of that symlink will become the process name. If the symlink is named "<multiple spaces>34873 ", the stat line becomes: 1234 ( 34873 ) S 1233 1234 1234 34818 ... ^ spaces inside comm ^ The naive space-counting parser hits the spaces inside the parentheses, treats them as field separators and incorrectly reads 34873 as tty_nr â the attacker's chosen device number instead of the real value (34818). In our synthetic vuln, this flaw is reproduced in âget_serial_port()â: static char * get_serial_port ( const char * status_path , char * name_out , size_t name_sz ) { // ... char * cp = line ; char * ep = line ; int field = 0 ; while ( * ++ ep != '\0' ) { /* â VULNERABLE PARSER */ if ( * ep == ' ' ) { * ep = '\0' ; if ( ++ field == 7 ) { /* Extract device number */ Flaw 2: Scanning all of /dev/ including world-writable directories Spoofing a TTY by itself doesnât seem very useful, but another flaw and two race conditions make it much more interesting. The second mistake occurs when sudo tries to open the relevant tty device file â starting by passing spoofed device number 34873 into sudo_ttyname_dev() (src/tty...