C programming - execute another program with sudo privileges - c

i have a C program that opens an mp3 and extract the jpg artwork in the same folder. If i execute this program with no root privileges i get a crash. If i execute it with sudo it works normally.
Now, i need another C programs who launch the previous program when it needs a jpg artwork for the selected mp3.
I tried to call popen("./firstProgram test.mp3" , "r") function or system("/(absolute path)/firstProgram test.mp3") function by calling them even with sudo in the command or not and either with relative or absolute paths. But no version seems to work.
How can i launch the first program from the second one with success?
Thanks!

fork and then use execl
char sudo[]="/usr/bin/sudo";
char pbin[]="/usr/local/bin/puppet";
NOTICE("running puppet: %s %s",sudo,pbin);
errno=0;
execl(sudo,sudo,pbin,(char *)NULL);
/* we should never get as far as this */
obviously I recommend reading man execl for further info

Unix (Linux) systems have contained a C Programming Manual in them since possibly forever. Look in Section 2, "System Calls".
This Wikipedia Page explains the Unix Manual "sections"
It is section 2 of the manual you can read about "System Calls"
Try the command: man 2 setuid
This will give you the manual for the setuid() system call which I think is what you want.
That manual page will also list references to other related system calls that may be what you want.
Remember when compiling C programs and using system calls that do low-level hardware access, to use the -O2, or -O3 option to gcc. There is a mention of it in the manual.
Ultimately the setuid() system call makes a running process started by one user change the UID of that running process to be running as some other user. (For example, you may see the Apache running as "apache", even though it was started by root).
setuid(0) lets you be root.

Related

Why is this C program doing nothing in Ubuntu?

My very simple C program just hangs and I don’t know why.
I am trying to make a simple executable to handle multiple monotonous actions for me every time I start a new programming session.
So I decided with something simple (below) yet every time I run it, the app just hangs, never returns. So I have to Ctrl-C out of it. I have added printf commands to see if it goes anywhere, but those never appear.
My build command returns no error messages:
gcc -o tail tail.c
Just curious what I am missing.
#include <stdio.h>
#include <unistd.h>
int main() {
chdir("\\var\\www");
return 0;
}
There are at least two problems with the source code:
It is unlikely that you have a sub-directory called \var\www in your current directory — Ubuntu uses / and not \ for path separators.
Even if there was a sub-directory with the right name, your program would change directory to it but that wouldn't affect the calling program.
You should check the return value from chdir() — at minimum:
if (chdir("/var/www") != 0)
{
perror("chdir");
exit(EXIT_FAILURE);
}
And, as Max pointed out, calling your program by the name of a well-known utility such as tail is likely to lead to confusion. Use a different name.
Incidentally, don't use test as a program name either. That, too, will lead to confusion as it is a shell built-in as well as an executable in either /bin or /usr/bin. There is also a program /bin/cd or /usr/bin/cd on your machine — it will check that it can change directory, but won't affect the current directory of your shell. You have to invoke it explicitly by the full pathname to get it to run at all because cd is another shell built-in.
Two things:
First, that's not what Linux paths look like
Second, check the return value from chdir()
ie
if (chdir("/var/www") != 0)
printf("failed to change directory");
Finally, the effect of chdir() lasts for the duration of the program. It will not change the current directory of your shell once this program finishes.
The other answers adequately cover the issues in your C code. However, the reason you are seeing it hang is because you chose the name tail for your program.
In Linux, tail is a command in /usr/bin in most setups, and if you just type tail at the command line, the shell searches the $PATH first, and runs this. Without any parameters, it waits for input on its stdin. You can end it by pressing control-d to mark the end of file.
You can bypass the $PATH lookup by typing ./tail instead.
$ tail
[system tail]
$ ./tail
[tail in your current directory]
It is a good idea to use ./ as a habit, but you can also avoid confusion by not naming your program the same as common commands. Another name to avoid is test which is a shell built-in for testing various aspects of files, but appears to do nothing as it reports results in its system return code.

Equivalent of bash's -x debug flag for C programs?

I always use the -x (or debug flag) when it come to bash script, or shell scripts in general.
Now i'm curious to know, is there an equivalent, either using a specific compiler options, (i use gcc, but i don't mind any other compilers) or by using a specific code in my project?
Basically i just wanted a way to emulate what bash does (using the debug flag) which show which command/function was launched first, in order, and also show the output of said function, with additional errors message etc.But for C.
I'm aware of most debug option out there, especially considering the compiler, but i really wish i could do this in my C projects too.(especially the part where it show what is executed in order, like bash does with -x)
NB: There isn't any goal in this specific question beside the question itself, as i'm just curious if this exist, and thus don't have any need for it beside the actual knowledge acquired from said answered question.
Yes, you can mimic this behaviour with a debugger.
With GDB for instance you can write "Init Files" and "Command Files" in which you can write a simple loop:
break main
run
while 1
next
end
If you put a file named .gdbinit in the directory where you start gdb, this file will be executed or gdb will lead you on the way to configure it in order that it will be executed.
The other option is to pipe this file into your gdb-call:
gdb a.out < debug_me_like-x
Where the "debug_me_like-x" file is the one mentioned above.
As a reference for the "Command Files" have a look here.

Exploiting SUID files with LD_PRELOAD and IFS

I've been reading about IFS exploitation and LD_PRELOAD Privilege escalation by overriding functions. Although these are two completely different questions, I've decided to post them together and hope that isn't a problem. Though both of these are very old, I've been told that they can both still be used for privilege escalation and I would love to look into that. However, I've ran into some problems.
So, let's begin by making the SUID file, /tmp/suid.
#include <unistd.h>
int main() {
system("/bin/date");
}
This calls /bin/date. The idea is that we can change the internal field separator and deceive the file into running something else with the privileges that it currently holds. This can be done (or can it?) by making a new file called bin contain the malicious code that the attacker put in a custom location. Then we change the $PATH variable and make it so that locations are first searched inside our custom path, where our malicious fake binary is located. Then by changing the internal field separator to '/', instead of running /bin/date the program will run /tmp/fakepath/bin with argument date, which can potentially trigger privilege escalation.
When I attempt the method described dankalia.com, it fails. /bin/date gets executed instead. If I just type bin date into the console the malicious binary does get started, but it doesn't when it's being invoked through /tmp/suid.
I thought that the vulnerability is patched and that it simply ignores the IFS variable, but then a post on stackoverflow got me interested. (C: IFS System() Vulnerability). Can anyone confirm to me if this works or not, and what I am doing wrong? Thanks.
As for the LD_PRELOAD, I'll keep it rather simple.
define _GNU_SOURCE
#include <stdio.h>
int puts(const char *str) {
printf("lel");
}
Use the following command line to compile:
gcc –Wall –fPIC –shared –o puts.so puts.c –ldl
Then, override the function puts with preload tricks:
LD_PRELOAD=./puts.so ./vuln_program_that_uses_puts
This works quite well. However, when dealing with a SUID file and when we're talking about privilege escalation, this ain't happening. LD_PRELOAD doesn't work well with SUID files and for a good reason. I've been told that "you can get it to work but that it's hard". Ideas?
Thanks in advance, and sorry for the long questions.
I've been told that "you can get it to work but that it's hard". Ideas?
The operating system is wise to these sorts of tricks, and most are remediated now. Te general idea is setuid, sudo and friends don't use an unprivileged user's environment.
The following offers more reading:
suid-binary vulnerabilities
Breaking the links: Exploiting the linker
If all you want is a setuid binary to break into the system:
shutdown the computer
mount the hard drive
rename ls (or other program like date)
copy sudo to ls (or other program like date)
unmount and reboot

What does initialize_main (&argc, &argv) do?

I 'm reading coreutils source code to learn programming under linux.
I find that in most of the programs like ls.c, cat.c, they invoke the macro function initialize_main() at the first few lines. So I looked into system.h to find the implementation:
/* Redirection and wildcarding when done by the utility itself.
Generally a noop, but used in particular for native VMS. */
#ifndef initialize_main
# define initialize_main(ac, av)
#endif
I don't understand why define such a macro and I don't understand the comment.
The first step in understanding the comment is to know what VMS is. So here's a link for that:
http://en.wikipedia.org/wiki/OpenVMS
The next step is to understand redirection and wildcarding. In Linux and other members of the unix family, a command like
cat foo* > /tmp/foolist
will call the main function of cat with argv containing the matches for foo*. The output file /tmp/foolist will already be open as stdout before main is entered.
VMS doesn't do that. cat will find the unexpanded string "foo*" and the redirection operator > in its argv. So the utility itself (cat) must do the redirection (opening the output file) and wildcarding (replacing "foo*" with "foo1", "foo2", "foo3"). That's what initialize_main will do on VMS. On unix, it'll do nothing ("Generally a noop").
This is left over from times gone by. OpenVMS is an operating system which roughly competed with Unix in the past. There is still a fair amount of OpenVMS running in the world, but HP have dropped support for it and it will be going away in the next 10-15 years.
Anyway, this function is used on OpenVMS to allow stdout and stderr redirection on VMS.
Since cat foo.txt > stuff.txt on Unix, the cat command only sees one argument foo.txt, but on VMS, which knows nothing of the > symbol, the cat command sees 3 arguments.
The code inside initialize_main on VMS, allows the basic unix style commands to support output redirection, such as ls and
OpenVMS later added a command called pipe which allows redirection to work via any command.
You can view the source code for initialize_main on VMS here: Link

How can a currently running C program find out what directory it is located in?

Say I have a command line C program which is currently executing, and I want to read a file or execute another binary in the same directory - how can I find out what directory that is?
Note that I'm not looking for the current working directory. The user may have invoked my original program in any of the following ways (and possibly others I don't know about).
../../program
/home/matt/program
PATH=$PATH:/home/matt program
Ideally I'm looking for something which will work on a unix system and windows via MinGW.
http://c-faq.com/osdep/exepath.html
According to the C FAQ it can't be done reliably
Finding current executable's path without /proc/self/exe
Concat getcwd() and dirname(argv[0])

Resources