I develop a C code on Linux (Debian). Time to time, I need to execute some commands through system()
I wonder if it is possible to execute a command via system()as root. If it is not the case, is there any function to execute a command (or run a binary) as root that I can use on the C code?
We met the situation before that we want to execute a root command by a normal user, here is our solution (using setuid/SUID):
assume that:
username: Tom
group: gTom
C program file: my_pro.c
Step 1: Write a C code tool: my_sudo.c
...
int main(int args, char *argv[]) {
if (args < 2)
printf("Usage: my_sudo [cmd] [arg1 arg2 ...]");
// cmd here is the shell cmd that you want execute in "my_pro"
// you can check the shell cmd privilege here
// example: if (argv[1] != "yum") return; we just allow yum execute here
char cmd[MAX_CMD];
int i;
for ( i = 2; i < args; i ++) {
// concatenate the cmd, example: "yum install xxxxx"
strcat(cmd, " ");
strcat(cmd, argv[i]);
}
system(cmd);
}
Step 2: Compile my_sudo.c to get a my_sudo executable file
sudo chown root:gTom my_sudo // user root && gTom group
sudo chmod 4550 my_sudo // use SUID to get root privilege
#you will see my_sudo like this(ls -l)
#-r-sr-x--- 1 root my_sudo 9028 Jul 19 10:09 my_sudo*
#assume we put my_sudo to /usr/sbin/my_sudo
Step 3: In your C code
...
int main() {
...
system("/usr/bin/mysudo yum install xxxxx");
...
}
#gcc && ls -l
#-rwxr--r-- 1 Tom gTom 1895797 Jul 23 13:55 my_pro
Step 4: Execute./my_pro
You can execute the yum install without sudo.
If you are a user on your system that has sudo privileges to run commands as root, just pre-pend sudo to the command.
system("sudo yum install some-package");
If you want anybody to be able to do it, then you have to be administrator on your system, change the owner of the file to be root, and modify the permissions of your executable to run as root. By doing so, you do not need to modify your system() command string with sudo.
chmod +s my_program
chown root my_program
Realize that doing this may open you up to security problems, unless you have proven that your program has no security issues.
The file-system may be such to disallow you from setting the setuid bit on your program. If you need more information along these lines, you should consult SuperUser.
This is one of those bag-o-tricks things to keep in mind. There are security risks, so just be aware of who will use it. In the "system" command you can even execute external scripts...although that opens major security risks because while this binary has to have the permissions re-set every time it's compiled, a script can be changed endlessly and this binary will keep calling it.
#include <stdio.h>
#include <stdlib.h>
//Create as root
//gcc fixmusic.c -o fixmusic
//chmod u+s fixmusic
//now run as non-root user and it should work despite limitations of user
int main(int argc, char *argv[] )
{
setuid(0);
char command[100];
sprintf(command,"/usr/bin/chmod -R a+w /mnt/Local/Music");
system(command);
//This is just optional info if someone cat's the binary
volatile const char comment [] = "INFO: Fixes music permissions";
return 0;
}
Related
I have installed a software named "OMPi" (after make, it generated two executable file ompicc and ompi, and you can use ompicc -x file to do something, and ompi will be called by ompicc).
When I run the command ompicc ~/Documents/example.c in the directory "/my_path/ompi-1.1/compiler" (ompicc is here and ompi is in the sub_path "./ompi/"), an error occurred sh: 1: /my_path/ompi-1.1/compiler/ompi: permission denied. But when I ran the same command in any other directories, the error didn't occur.
sudo chmod 777 -R ompi-1.1 is no use.
I think it may be because the sub_path "./ompi/" get the same name with file ompi. So, I created a directory named "ompi/" in home_path, and then ran the above command. To my surprise, the error didn't occur. It seems that the error only occur when I run the command in the directory: /my_path/ompi-1.1/compiler/
information in terminal
From the looks of it (I have briefly checked ompi's source code), the ompi program is expected by ompicc to be in the same directory. It worked fine after you had created /ompi/ in home directory, because you still had executable of the same name in the same directory as ompicc. It doesn't work in the directory you specified because there's only one ompi there which is a directory.
Line that does the execution in ompicc.c (the constructed command is then ran by a system() call:
sprintf(cmd, "%s%s%s \"%s.pc\" __ompi__%s%s%s%s%s%s%s %s > \"%s\"%s",
usegdb ? "gdb " : "", /* Run gdb instead of running _ompi directly */
RealOmpiName,
usegdb ? " -ex 'set args" : "", /* Pass the arguments */
/* ...further arguments here... */
To confirm that RealOmpiName is 'ompi' i followed the program and
RealOmpiName is traced back to (through external symbol OmpiName)
Makefile.am:
-DOmpiName='"_#PACKAGE_TARNAME#"' \
Which then is used like this (to install the software):
cp -f ompi $(DESTDIR)$(bindir)/_#PACKAGE_TARNAME#
cp -f ompicc $(DESTDIR)$(bindir)/#PACKAGE_TARNAME#cc
I think the installer wouldn't put the two programs together if it didn't require the two to be in the same directory in the first place.
Solution: ompi and ompicc have to be in the same folder/directory.
I am trying to solve this problem, I am only allowed to run ls command and my objective is to read the flag. There is a vulnerable C code which has setuid.
-rwsr-sr-x 1 lameprogrammer lameprogrammer 8579 Sep 15 07:21 vul_c
-rw-r----- 1 lameprogrammer lameprogrammer 154 Sep 15 07:40 flag
I am user attacker and I have to read this flag file. The given C code is
#include <stdlib.h>
#include <stdio.h>
#define FILENAME "/var/challenges/attacker/challenge1/flag"
int main(void)
{
int vert;
vert = system("ls " FILENAME);
if(!vert)
puts("Flag is at " FILENAME " :P ");
else
puts("Sorry! no file is there");
}
I was trying to convert ls into cat so that if that runs then it will read the flag file. To do that I copied all the bin folder into my local space and then I replaced ls with cat and then exported the new PATH. Technically it should replace and my ls command should work like cat but it is not working. The following are my command :
cp -r /bin /home/attacker
cd /home/attacker/bin
rm ls
cp cat ls
export PATH=/home/attacker/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/usr/games
The ls command is not working as cat and output is:
ls: unrecognized option '--color=auto'
Try 'ls --help' for more information.
When I am trying to run ./vul_c it says permission denied and then it is printing Sorry! no file is there.
Any help onto this would be great.
You are in the right direction but you are just putting too much effort for this small thing. Instead of creating a program why don't you create a symlink and then point this to cat.
Try this step:
ln -s /bin/cat ls
Finally, export this and I hope you will be done with your solution. In this, you don't even have to worry about permission. Let me know if it works.
Does the program work? The problem as I see it is that if you use ls in the shell, is that it has an alias that will enable the colouring, i.e. something like
alias ls='ls --color=auto'
Now this is something that cat wouldn't understand. But it would be only for your shell, not the ls command run by that script, because it wouldn't use the aliases. Perhaps something like unalias ls would help in the shell.
Now, the system function cannot run your ls because it doesn't have proper rights - you forgot to chmod +x ls.
Try the following command:
unalias ls
I understand the implications of running a script as root, especially by a web application. However as part of my web application, I need to use curl with tor and this needs resetting the tor ip occasionally. tor can get a new ip when the service is restarted with service tor restart. Since only root can do that, I've written a C wrapper script to do what I need, and compiled it and set setuid root on it, and changed to root user ownership. However, it still asks me root password when it's run as an unprivileged user. As root, a service restart shouldn't ask password.
My script:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void ExecAsRoot (char* str);
int main ()
{
setuid (0);
setvbuf(stdout, NULL, _IONBF, 0);
printf ("Host real ip is: ");
ExecAsRoot("ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'");
ExecAsRoot("/usr/sbin/service tor restart");
// sleep(2);
printf ("Tor should have switched to a new ip by now.\nNew ip is: ");
ExecAsRoot("torify curl ifconfig.co 2>/dev/null");
return 0;
}
void ExecAsRoot (char* str) {
system (str);
}
I've done the following:
chown root restartor
chmod u=rwx,go=xr restartor
Output:
Host real ip is: 7.17.11.23
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to restart 'tor.service'.
Authenticating as: root
Password:
How can I get this to run as web user without supplying root password?
You didn't set the setuid bit in the file permissions:
#-------v
chmod u=srwx,go=xr restartor
I want to use a command in my c code. This command works properly when i am a superuser in terminal (using su) but does not work when I use sudo. I gathered that I can use system() in my c code as follows
system("su -c \"mycommand\"")
myCommand is a command that sends input to some device, like (echo 1 > mydevice)
I compiled my c code using gcc and run the output file. The trouble is, it wants root password from terminal when it comes to this line.
Is there a way I supply password programatically? I did it before with sudo command with -S option, but sudo command does not work for this case. If it is not possible, is there another way to deal with this?
Try this instead,
system("sudo sh -c \"mycommand\"");
I want to create a file in /usr/share/applications/ and put a string on it.
What I have so far:
sudo touch /usr/share/applications/test.desktop
dentry="testing"
sudo echo $dentry >> /usr/share/applications/test.desktop
But this raise an error Permission Denied. What should I do to make it works?
You should create the file using your own pernissions, then sudo cp it into place.
The reason the second command doesn't work is that the redirection is set up by your shell, before sudo even runs. You could work around this by running sudo sh -c 'echo stuff >>file' but this is vastly more risk-prone than a simple sudo cp, and additionally has a race condition (if you run two concurrent instances of this script, they could end up writing the information twice to the file).