Find teammates to form a team of 5 students from the class and choose a team name. Think carefully about who you want to team up with. Successful teams will consist of individuals who:
Once you have settled on your team members and a team name, have one member of your team send an email to the lab TA (with a CC to Prof. Noubir) containing the following information:
Upon receipt, you will receive a team number and credentials to remotely access your team's systems. At that point, you may begin part 2.
useradd(8) command. (Read the man page first for usage
information.) When creating users, use the -G option to
add them to the wheel group as well as the default
initial group. (If you forget to do this when creating an account, see
the man page for group(5) and add them manually with a
text editor.)
sudo(8), to understand how
they may execute privileged commands with their own less-privileged
account. Review the current /etc/sudoers file to
understand currently granted privileges.
NOTE: Be sure to use strong passwords for the accounts. All
systems will be partially exposed to the internet, and password
brute-force attacks have become common-place.
sudo)
/root/bin/disable-stack-protection. To re-enable stack
protections, run /root/bin/enable-stack-protection. (If
your system is ever rebooted, the stack protections will be
re-enabled by default.)
/usr/local/netsec/lab1 which contains three files. The
Makefile will compile the C programs
uppercase.c and lowercase.c. Examine both
programs and discuss within your team what possible security issues
exist with them.
uppercase.c. This program takes a string
in on argv[1] and prints out the same string with all
ASCII lowercase characters changed to uppercase. Think about what
would happen if a user provided a string longer than 512 bytes. Now,
try it out. Run the program with a first argument that is much
longer than 512 bytes.
gdb to run the program again with the same, very
long, first argument. (Hint: set args AAAAAAA...) When
you run the program, and it finishes, record the %eip
address reported when it segfaults. Compare this value to your
string's ASCII hexadecimal
representation (Hint: man ascii). Now, repeatedly
shorten/lengthen your string and re-run uppercase in
gdb to determine the length of the shortest string
needed to control %eip.
main() and run
uppercase again with your shortest (but
%eip-controlling) argv[1]. Once the
breakpoint is reached, find the
address of uppercase's argv[1].
(Hint: print &argv[1])
argv[1] buffer of uppercase and then
overwrite the stack frame return address so that execution continues
within that buffer when main() returns. (Note: since
buf will get modified before main()
returns, you won't be able to jump into that buffer.)
char scode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89"
"\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c"
"\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff"
"\xff\xff/bin/sh";
You may find it helpful to use Aleph1's paper,
Smashing The Stack For Fun and Profit as a tutorial/reference for
this section.main()'s stack frame is.
Running your
exploit or uppercase with a minimal set of
environment variables can help make exploits work more
consistently. See env(1) and execle(3).
0xBFFFFFFA and addresses progressively
decrease as new items are pushed onto it.
0x90 is the
NOP instruction.
uppercase a setuid root program by running
chmod u+s uppercase (as root). Now, run your exploit
again as a non-root user. Once your shellcode runs, use the
id(1) command to determine what user the shell is
executed as. (If everything works correctly, you'll have elevated
privileges to root through this overflow.)
lowercase.c. Notice what happens to
argv[1] before it is copied into
buf. If you
try to exploit this overflow by placing your shellcode in
argv[1], why won't it work? Think about other locations
your shellcode could be stored instead of argv[1].
lowercase which does not embed
the shellcode in buf or argv[1]. Instead,
just repeatedly fill argv[1] with the address where your
shellcode resides. (There's at least two places in
lowercase's address space that you can stuff your
shellcode.)
sudo command? If
sudo is used to grant access to a specific account, why
is this better than simply giving that user's password to those who
need it?
uppercase.c and
lowercase.c to make them safe from buffer
overflow attacks? You are encouraged to answer this question by
including a code diff of each program. (See: diff(1).
Universal diffs are preferred.)
buf were instead allocated via malloc(3)
in these vulnerable programs, would the same techniques for
exploitation work? Why or why not?
uppercase which
includes the stack frames for main() and
strcpy() and all local variables for
main(). Also, include the location of
main()'s return address and how it gets overwritten by an
overflown buf. Finally, include argv[1] in
the diagram as well, relative to the stack frames. (Exact offsets
aren't that important here, but relative locations are.)