What's new arround internet

Last one

Src Date (GMT) Titre Description Tags Stories Notes
Blog.webp 2024-05-05 00:00:00 BSIDESSF 2024 Écritures: ne peut pas donner (exploitation CGI)
BSidesSF 2024 Writeups: Can\\'t Give In (CGI exploitation)
(lien direct)
The premise of the three challenges cant-give-in, cant-give-in-secure, and cant-give-in-securer are to learn how to exploit and debug compiled code that\'s loaded as a CGI module. You might think that\'s unlikely, but a surprising number of enterprise applications (usually hardware stuff - firewalls, network “security” appliances, stuff like that) is powered by CGI scripts. You never know! This challenge was inspired by one of my co-workers at GreyNoise asking how to debug a CGI script. I thought it\'d be cool to make a multi-challenge series in case others didn\'t know! This write-up is intended to be fairly detailed, to help new players understand their first stack overflow! Part 1: cant-give-in The vulnerability First, let\'s look at the vuln! All three challenges have pretty similar vulnerabilities, but here\'s what the first looks like: char *strlength = getenv("CONTENT_LENGTH"); if(!strlength) { printf("ERROR: Please send data!"); exit(0); } int length = atoi(strlength); read(fileno(stdin), data, length); if(!strcmp(data, "password=MyCoolPassword")) { printf("SUCCESS: authenticated successfully!"); } else { printf("ERROR: Login failed!"); } The way CGI works - a fact that I\'d forgotten since learning Perl like 20 years ago - is that the headers are processed by Apache and sent to the script as environmental variables, and the body (ie, POST data) is sent on stdin. In that script, we read the Content-Length from a variable, then read that many bytes of the POST body into a static buffer. That\'s a fairly standard buffer overflow, with the twist that it\'s in a CGI application! We can demonstrate the issue pretty easily by running the CGI directly (I\'m using dd to produce 200 characters without cluttering up the screen): Tool Vulnerability Threat ★★★
Blog.webp 2023-04-24 00:08:44 BSIDESSF 2023 Écritures: White plat (réversion Java plus simple)
BSidesSF 2023 Writeups: Flat White (simpler Java reversing)
(lien direct)
Ceci est un article pour Flat-White et Vulnerability ★★★
Blog.webp 2023-04-24 00:08:44 BSIDESSF 2023 Rédactions: Sortez (Difficiel Inverse Engineering + Exploitation)
BSidesSF 2023 Writeups: Get Out (difficult reverse engineering + exploitation)
(lien direct)
This is a write-up for three challenges: getout1-warmup getout2-gettoken getout3-apply They are somewhat difficult challenges where the player reverses a network protocol, finds an authentication bypass, and performs a stack overflow to ultimately get code execution. It also has a bit of thematic / story to it! Writeup Getout is based on a research project I did over the winter on Rocket Software\'s UniData application. UniData (and other software they make) comes with a server called UniRPC, which functions very similarly to getoutrpc. My intention for the three parts of getout are: Solving getout1-warmup requires understanding how the RPC protocol works, which, as I said, is very similar to UniRPC In getout2-gettoken, I emulated CVE-2023-28503 as best I could In getout3-apply, I emulated CVE-2023-28502 but made it much, much harder to exploit Let\'s take a look at each! getout1-warmup The warmup is largely about reverse engineering enough of the protocol to implement it. You can find libgetout.rb in my solution, but the summary is that: You connect to the RPC service You send messages to the server, which are basically just a header, then a body comprised of a series of packed fields (integers, strings, etc) The first message starts with an integer opcode: Opcode 0 = “list services” Opcode 1 = “execute a service” Once a service is executed, a different binary takes over, which implements its own sub-protocol (though the packet formats are the same) For getout1-warmup, you just have to connect to the service and it immediately sends you the flag. On the server, it looks like: int main(int argc, char *argv[]) { int s = atoi(argv[1]); packet_body_t *response = packet_body_create_empty(); packet_body_add_int( Vulnerability Prediction ★★
Blog.webp 2023-04-24 00:08:44 BSIDESSF 2023 Écritures: Too-Latte (exploitation Java de difficulté moyenne)
BSidesSF 2023 Writeups: too-latte (medium-difficulty Java exploitation)
(lien direct)
too-latte is a challenge I wrote based on CVE-2023-0669, which is an unsafe deserialization vulnerability in Fortra\'s GoAnywhere MFT software. I modeled all the vulnerable code off, as much as I could, that codebase. It\'s obviously themed quite differently. Write-up If you use a tool like jadx to unpack the servlets, you\'ll find, through some layers of indirection, this code in TokenWorker.java (that operates on the token parameter): public static String unbundle(String token, KeyConfig keyConfig) throws Exception { token = token.substring(0, token.indexOf("$")); return new String(decompress(verify(decrypt(decode(token.getBytes(StandardCharsets.UTF_8)), keyConfig.getVersion()), keyConfig)), StandardCharsets.UTF_8); } The decode function decodes the token parameter from Base64. The decrypt function decrypts the token with a static key. The actual decryption code is under several layers of indirection, because Java is Java, but the TokenEncryptor class has a key, IV, and algorithm: private static final byte[] IV = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 Tool Vulnerability ★★
Blog.webp 2023-01-23 20:14:17 Blast from the Past: How Attackers Compromised Zimbra With a Patched Vulnerability (lien direct) Last year, I worked on a vulnerability in Zimbra (CVE-2022-41352 - my AttackerKB analysis for Rapid7) that turned out to be a new(-ish) exploit path for a really old bug in cpio - CVE-2015-1194. But that was patched in 2019, so what happened? (I posted this as a tweet-thread awhile back, but I decided to flesh it out and make it into a full blog post!) cpio is an archive tool commonly used for system-level stuff (firmware images and such). It can also extract other format, like .tar, which we'll use since it's more familiar. cpio has a flag (--no-absolute-filenames), off by default, that purports to prevent writing files outside of the target directory. That's handy when, for example, extracting untrusted files with Amavis (like Zimbra does). The problem is, symbolic links can point to absolute paths, and therefore, even with --no-absolute-filenames, there was no safe way to extract an untrusted archive (outside of using a chroot environment or something similar, which they really ought to do). Much later, in 2019, the cpio team released cpio version 2.13, which includes a patch for CVE-2015-1194, with unit tests and everything. Some (not all) modern OSes include the patched version of cpio, which should be the end of the story, but it's not! I'm currently writing this on Fedora 35, so let's try exploiting it. We can confirm that the version of cpio installed with the OS is, indeed, the fixed version: ron@fedora ~ $ cpio --version cpio (GNU cpio) 2.13 Copyright (C) 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Phil Nelson, David MacKenzie, John Oleynick, and Sergey Poznyakoff. That means that we shouldn't be able to use symlinks to write outside of the target directory, so let's create a .tar file that includes a symlink and a file written through that symlink (this is largely copied from this mailing list post: ron@fedora ~ $ mkdir cpiotest ron@fedora ~ $ cd cpiotest ron@fedora ~/cpiotest $ ln -s /tmp/ ./demo ron@fedora ~/cpiotest $ echo 'hello' > demo/imafile ron@fedora ~/cpiotest $ tar -cvf demo.tar demo demo/imafile demo demo/imafile ron@fedora ~/cpiotest $ Tool Vulnerability APT 17 ★★★★
Blog.webp 2022-06-17 20:19:21 BSidesSF 2022 Writeups: Game-y Challenges (Turtle, Guessme) (lien direct) Hey folks, This is my (Ron's / iagox86's) author writeups for the BSides San Francisco 2022 CTF. You can get the full source code for everything on github. Most have either a Dockerfile or instructions on how to run locally. Enjoy! Here are the four BSidesSF CTF blogs: shurdles1/2/3, loadit1/2/3, polyglot, and not-for-taking mod_ctfauth, refreshing turtle, guessme loca, reallyprettymundane Turtle While discussing how we could appeal to current trends, I had the idea of making a challenge based on Wordle, called Turdle. My husband talked me out of "Turd", so we ended up with Turtle. I could swear growing up that we had a "game" called E-Z-Logic in elementary school, on the Apple ]['s we had. It was a graphical version of the logo programming language. You could move the little turtle around, and had to navigate mazes. I tried and failed to find a reference to it, so it may never have existed. Anyway, combining this mythical game and Wordle, I came up with an impossible Wordle clone: you move the turtle around, and have to match the directions/distances. The original "vulnerability" was supposed to be that you could submit future solutions, and I looked at using a broken RNG or something for future dates. But honestly, solving the current day was difficult enough that I really only had to do that. Ohwell. :) The vulnerability was in the 2-digit dates used to calculate the path. If you rewind by exactly 100 years, the solution is the same. So you just have to get the solution for 1922, and there ya go! Solution is here. Honestly, this challenge was like 5% writing a challenge, and 95% making it look pretty. I thought it was pretty cool, though. :) Guessme I had the idea that I wanted to make a challenge based on Base64 ambiguity. I've tweeted about it a couple times in the past year, because I thought it was interesting! The idea of [guessme[(https://github.com/BSidesSF/ctf-2022-release/tree/main/guessme) is that you're given a list of "clues" (which mean nothing), and you have one chance to guess the solution, which is checked using an encrypted base64-encoded token that the user also gets. If you guess wrong, you're sent the answer and it "blacklists" the encrypted token so you can't guess again. The problem is that base64 is ambiguous! Each base64 character represents six bits of binary data, so four base64 characters are 24 bits or three bytes. But five base64 characters represent 30 bits, or 3.5 bytes. Since you obviously can't have half of a byte, the last 4 bits are disregarded. If you change those bits, you can create a new encoding without changing the original data! My solution naively increments the final character until it works. Not the cleanest solution, but it works eventually! uity. I've tweeted about it a couple times in the past year, because I thought it was interesting! The idea of guessme is that you're given a list of Vulnerability ★★★★
Blog.webp 2022-06-17 20:19:18 BSidesSF 2022 Writeups: Apache Challenges (mod_ctfauth, refresh) (lien direct) Hey folks, This is my (Ron's / iagox86's) author writeups for the BSides San Francisco 2022 CTF. You can get the full source code for everything on github. Most have either a Dockerfile or instructions on how to run locally. Enjoy! Here are the four BSidesSF CTF blogs: shurdles1/2/3, loadit1/2/3, polyglot, and not-for-taking mod_ctfauth, refreshing turtle, guessme loca, reallyprettymundane Refreshing - Reverse proxy mischief The Refreshing challenge implements a reverse proxy that checks the query string for mischief, and attaches a header if it's bad. If the PHP application with a blatant vulnerability sees that header, it prints an error and does not render. This was actually based entirely on CVE-2022-1388 (the name "Refreshing" is a nod to F5) - you can see my Rapid7 writeup on AttackerKB. This was absolutely new to me when I worked on that vuln: the Connection HTTP header can remove headers when proxying. That means if you set Connection: Xyz while proxying through Apache, it will remove the header Xyz when forwarding. This worked out of the box on Apache! I initially tried Nginx, and it did not work there - not sure why, maybe they don't implement that header the same? Anyway, to solve this, all you have to do is set the header Connection: X-Security-Danger on the request, then take advantage of the path traversal on the PHP site: $ curl -H 'Connection: X-Security-Danger' 'http://refreshing-d7c0f337.challenges.bsidessf.net/index.php?file=../../../../../../../flag.txt' CTF{press_f5_to_continue} mod_ctfauth - A custom Apache authentication module mod_ctfauth is a fairly simple Apache authentication plugin. It checks a username and token, then decides whether to grant access. I wrote it at the very last minute, because at work I was reverse engineering some Apache plugins and thought it'd be a good excuse to learn. And it worked! I've been re-using the container to test out more Apache stuff this week! The source for the challenge is here. As you can see, it's really pretty straight forward - you can expect something more interesting next year, now that I know how these plugins work! The bulk of the challenge is the following code (I removed a bunch of extra checks to shorten it down): char *username = (char*)apr_table_get(r->headers_in, USERNAME_HEADER); if(strcmp(username, "ctf")) { return AUTHZ_DENIED; } char* header = (char*)apr_table_get( r->headers_in, HEADER); char *encoded_token = header + strlen(TOKEN_PREFIX); int actual_length = apr_base64_decode(decoded_token, encoded_token); [...] apr_md5_ctx_t md5; apr_md5_init(&md5); apr_md5_update(&md5, SECRET, strlen(SECRET)); apr_md5_update(&md5, username, strlen(username)); apr_md5_update(&md5, SECRET, strlen(SECRET)); char buffer[HASH_LENGTH]; apr_md5_final(buffer, &md5); if(memcmp(buffe Vulnerability ★★★★
Blog.webp 2021-03-18 17:07:36 BSidesSF CTF 2021 Author writeup: glitter-printer, a buffer underflow where you modify the actual code (lien direct) Hi Everybody! This is going to be a challenge-author writeup for the Glitter Printer challenge from BSides San Francisco 2021. First, a bit of history: the original idea I had behind Glitter Printer was to make a video game challenge involving cartridge-swap, where I'd write a handful of simple video games in 100% x86 code with no imports or anything (like an old fashioned cartridge game), and the player could swap between them without memory being re-initialized. Folks used to do this sorta thing on NES, and maybe I'll use it in a future challenge, but I decided to make this a bit simpler. While experimenting with writing libraries without libc, I realized just how much work it was going to be to write a bunch of games, and decided to simplify. My next ide was to write a “driver” type thing, where a blob of code is loaded into +RWX memory and the player could go wild on it. The the name Glitter Printer came across my radar, I don't even remember why, and that gave me the idea to do an LPR server. That's quite the background! The code So I don't know if anybody actually noticed, but I implemented a good chunk of the Line Printer (LPR) RFC correctly. Well, I tried to anyways, I didn't actually test it with a real client. The hard part was introducing a realistic-looking vulnerability - in many of my CTF challenges, the vuln comes naturally. So naturally, in fact, that I often don't even need to plan it in advance! I ended up settling on an integer underflow. If you look at the source (specifically, core.c), you can see that the main loop reads a single byte, then performs an action accordingly: void _start(queue_t *queues) { while(1) { char command = read_byte(STDIN); if(command == 1) { print_waiting_jobs(); } else if(command == 2) { receive_job(queues); } else if(command == 3) { queue_state_list(queues, 0); } else if(command == 4) { queue_state_list(queues, 1); } else if(command == 5) { // 05 Queue SP Agent SP List LF - Remove jobs } else { exit(6); } } } As part of several commands (such as receive_job()), an ASCII number is sent to choose a queue to operate on. The queue number isn't a byte (like “\x01”), it's a number like “123” that needs to be parsed. And by the way, this is still how LPR actually works! Here's the code I used for parsing numbers.. I'm pretty sure I just grabbed this from Stack Overflow: int read_number(char *terminator) { int result = 0; while(1) { // Read a single byte char buffer = read_byte(); // If it's not a valid byte, we're done (and we consume the terminator) if(buffer < '0' || buffer > '9') { Vulnerability Guideline ★★★★
Last update at: 2024-05-19 23:08:19
See our sources.
My email:

To see everything: Our RSS (filtrered) Twitter