Need Assistance Understanding a Vulnerability Issue

I would appreciate some assistance in understanding a C++ issue. I'm taking a course in CyberSecurity that relies on C++ for its examples. My background is Dot-Net so I'm more than a bit lost. I'm jamming to learn C++ but I'm not at the point to understand this yet.
If someone can help me understand these so I can at least start to understand how the issue is derived and take it from there. This is NOT homework. It's examples given that I'm struggling to understand and there is no interaction available to discuss with others.

==============================================
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <string.h>

#define S 100
#define N 1000

int main(int argc, char *argv[]) {
	char out[S];
	char buf[N];
	char msg[] = "Welcome to the argument echoing program\n";
	int len = 0;
	buf[0] = '\0';
	printf(msg);
	while (argc) {
		sprintf(out, "argument %d is %s\n", argc-1, argv[argv-1]);
		argc--;
		strncat(buf,out,sizeof(buf)-len-1);
		len = strlen(buf);
	}
	printf("%s",buf);
	return 0;
}

=============================================

#1:
This code above is vulnerable to a buffer overflow.
What is the name of the buffer that can be overflowed?

#2:
In the code above - what line of code can overflow the vulnerable buffer?

#3:
One line can be changed and make the buffer overflow go away. What line would that be?

#4:
What attacks is the program vulnerable to?
Code injection, data corruption, reading arbitrary addressed in memory, all of them

#5:
If I changed printf("%s",buf) to printf(buf) then the program would be vulnerable to what sort of attack?
Heap overflow, format string attack, user-after-free attack, all of them.

Thanks to whomever takes the time to help!!
Last edited on
This is not a homework site. We're not going to do your homework for you.
Make an attempt to answer the questions and we'll point you in the right direction.

This is C, not C++.

PLEASE USE CODE TAGS (the <> formatting button) when posting code.
It makes it easier to read your code and also easier to respond to your post.
http://www.cplusplus.com/articles/jEywvCM9/
Hint: You can edit your post, highlight your code and press the <> formatting button.

I've done the homework and passed the test.

Odd, then, that all you supplied were the questions.
#1: there are two "buffers" (arrays) being modified. One of them is being modified in an unsafe way. (There is no limit to the size of the input copied to the buffer.)
Hint: look at the documentation for the functions doing the modifications: sprintf() and strncat().

#2: See #1.

#3: See #1.

#4: Any time you can overflow a buffer into memory marked executable then all bets are off.
Hint: Consider the location of the variables and the location of the code.

#5: Again, this is a question that requires you to read the documentation (sprintf() and printf() do much the same thing -- the only difference is where the output goes).
Hint: What if buf contained the string "%s"?

That code, BTW, is C, and it is very poorly designed. I can't imagine it ever passing a code review, even if the security vulnerabilities were handled. I suppose it counts as a good bad example, though.

Hope this helps.
These were "self test" questions, not the end of section tests. Those didn't deal with this and I was able to handle them with a 83%. Wasn't great - but it was passing.
I'm really trying hard to understand this stuff because it's the foundation of so much of the course. Looking at the questions I got (above) I just wasn't able to grasp what-did-what-to-what. I was hoping if someone posted the responses I could reverse engineer my way into seeing what was happening...and why.
I can see how it looked like some kid trying to punch his way through the course and for that I apologize. I would have responded the same way. My excuse is I'm 71 and some stuff just doesn't compute as easily :-)
These distance learning things are great in that they open so much education for people. The big negative is not being able to raise my hand and get a question answered. Once one starts getting behind on something so fundamental the slope gets very steep. I'm trying to "get" this.
Much appreciation to Duoas for the assist. I'll go try to get smarter now.
1) Both out and buf can overflow.

2)
Line 15: out can overflow. Consider if argv[1] is >= 100 bytes. You will try to format 117 or more bytes into out.

Line 17: buf can conceivably overflow. This would take say 10 arguments > 100 bytes each. However, you may run into an OS limit on the total size of the command line before this happens.

3) Change line 4 to a large number (1000). This would not prevent the possibility of overflowing out, just reduce the likelihood. Again, OS limits on the total size of a command line come into play here.

4) code injection, data corruption

5) Format string attack. The user is supplying the format string and can supply anything they want.

Edit: doug4 is correct, line 17 prevents buf from overflowing.
Last edited on
I disagree with @AbstractionAnon about buf overflowing. The code uses strncat which only concatenates "n" characters to the string. The n appears to be correctly calculated to prevent buffer overflow.

As far as #3, change line 15 to be snprintf rather than sprintf. That way you can prevent overflow, not merely reduce the likelihood.
Line 17 is still an issue -- strncat() prevents too many characters from being written, but by causing an overflow, you know that the resulting character string will not be null-terminated, so the attacker gets to look at your code.
strncat() writes a null character at the end.
The terminating null character is always appended in the end (so the maximum number of bytes the function may write is count+1). http://en.cppreference.com/w/c/string/byte/strncat
argv[argv-1]... one hopes that's a typo.

Given that the OP asked for assistance in understanding a C++ issue, it seems only fair that he be given actual C++ code as a solution.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
#include <sstream>

int main(int argc, char *argv []) {

    std::ostringstream buf;
    std::ostringstream out;

    while (argc--) {
        out << "argument " << argc << " is " << argv[argc] << '\n';
        buf << out.str();
        out.str("");
    }

    std::cout << buf.str();
}


strncat() writes a null character at the end.
Oop! Yep, I was thinking of strncpy().
Topic archived. No new replies allowed.