I want a shell script to be executable but not readable - linux

I created a script which I want other users on our shared system to execute but not read. I set the permissions as executable for all but revoked the R/W rights.
---x--x--x 1 dilletante staff 0 2013-04-02 11:42 expect.sh
However the script Fails to execute...The reason is simple.. The interpreter also needs to read the script
I want a workaround if any..Can I embed it into some compiled language..Would that work?
If yes, could you point to the resources where I can learn how to do so..

The shell has to be able to read a script to execute it. You are asking for the impossible if it is a script.
You can certainly use 111 permission on an executable program (as produced by the ld command, typically invoked by the compiler of your chosen compiled implementation language). The owner can always change the permission to read the program if they want to, but it is more conventional to use 511 than 111 permission.
There are often compilers for a specific script language that will generate a C program equivalent to the script:
Compilers for shell scripts.
How to compile a Linux shell script as a binary.
Compiling shell scripts.
shc — shell script compiler.
Etc.

If you want this for other users try sudo
Example:
Change execution right
chmod 500 /usr/bin/script.bash
ll /usr/bin/script.bash
-r-x------ 1 <USER> <GROUP> 1174 23. Jan 13:24 /usr/bin/script.bash
As root change sudoers
visudo
## Allows ALL to run /usr/bin/script.bash as <USER> without password
## The asterisk is if you want to use any commandline parameters
ALL ALL=(<USER>) NOPASSWD: /usr/bin/script.bash *
Run script with sudo
sudo /usr/bin/script.bash <PARAMETERS>
For further information concerning sudo read the sudo manpages

There's an alternative to securing your shell scripts. Since the goal here is to make sure no one can read or alter them, you may want to give the following link a try:
http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm
On the above page, all you have to do is submit your shell script (you can submit a sample script first for your peace of mind). A zip file will be generated for you.
Installation:
wget link-to-the-zip-file
unzip the-newly-downloaded-zip-file
cd /tmp/KingLazySHIELD
./install.sh /var/tmp/KINGLAZY/SHIELDX-(name-of-your-script) /bin -force
What the above install command will do for you is:
It'll install the encrypted script in the directory /var/tmp/KINGLAZY/SHIELDX-(name-of-your-script).
It'll place a link to this encrypted script in /bin - that way, you need not type the absolute path to your script each time you want to run it.
Ensures NO ONE can modify the script - Any attempts to modify the encrypted script will render it inoperable...until the attempts are removed.
Ensures absolutely NO ONE can make working copies of it. No one can copy your script to a secluded location and try to screw around with it to see how it works. If they try to, it'll abort and will not run.

I made my own bash obfuscator to overcome some shortcomings of shc which really bugged me (the primary one as being able to see the script in almost clear text with the use of ps).
You could have a look if https://github.com/louigi600/obash serves you any better then shc.

Related

Cron job fails to execute python script that writes to text file

I need to run a python script on a remote server (I'm not the owner of this server, so I cannot check var/log/syslog). The script is put in a folder with other files that the scripts depends on to be able to run. The script will write out a text files, the information being written includes runtime of the script.
If I executed the script manually, it will write text file with all correct information. However, when I set a test cron job to make sure my script run and the output file looks like what I'd like, the output file has only one line that includes a very small float which I assume to be the runtime of the script. The default python version of the server is python 2.7. However, my script need python3 to run. Below is the crontab command that I use
# crontab command
# the time is just an example
23 23 13 4 6 /usr/bin/python3 /home/user_name/path/to/file.py
I have tried using just python3 files.py and python3.5 files.py, same result for all cases.
All the files in the folder I tried to run my scripts and my script itself is chmod 707
Also, side question, I'm sharing this server with other people; however, I don't want them to be able to open my files, what chmod should I set my files and folder to so that cron would still be able to execute my files and people won't be able to view it (beside the owner of the server)
First, permissions:
Every user has a crontab, and the entries in a user's crontab run as that user.
The three numbers in a files permission are user, group and other.
Typically a user has their own group, and they are the only member of it.
So that means if you want to keep your stuff to your self, only grant permissions to your user (and optionally, your group, which is the same thing if you're the only member). Your crontab will have no trouble accessing anything your user can access.
Thus, give all the relevant directories and all the text files ownership of user_name:user_name and permissions of 660 (only you can read and write to them). Give all the executable files the same ownership but permissions of 770 (so you can also execute them).
Then, if you have ssh access, just execute /usr/bin/python3 /home/user_name/path/to/file.py from the command line to see where it's falling over. Assuming you don't have ssh access, then you need to capture the output from the crontab execution. Use this crontab line:
23 23 13 4 6 /usr/bin/python3 /home/user_name/path/to/file.py > /home/user_name/output.txt 2>&1
That will redirect all STDERR to STDOUT (the 2>&1 bit) and redirect STDOUT to output.txt (the > bit).
Let that run and check the contents of output.txt. I'm guessing you'll find Python had trouble getting access to something and bombed out before writing much to the file.

linux file access read/write by root, execute by all

I'm trying to create a shell script that can only be read/written by root but can be executed by everyone. I created a file test.sh, set ownership to "chown root:me test.sh" and set permissions to "chmod 711 test.sh", hoping this would do the trick. However, this results in a file that always needs sudo in order to execute. Is it possible to edit the rights such that anyone (without using sudo) can execute the script, but only root (using sudo) can read/write the file?
this is not possible to be achieved, at least with shell scripts.
In fact, at the moment of the execution, the shell program (I presume Bash) needs to read the content of the shell file and the process runs with your user name and permissions.
Having said this, the BASH program (ZSH, SH or any other shell follow the same rules) needs to be able to read the content of the file and this can be achieved only by granting read privileges +r. So, the bare minimum would be a 755 permission model.
An alternative is to run an actual program which does the job and wouldn't require read permission in order to be executed. But this is a totally different pattern.
This response explains it as well.
https://unix.stackexchange.com/questions/34202/can-a-script-be-executable-but-not-readable

Why do we need execution permission although we can run any script without it using "bash script file"?

I am wondering when and why do we need execution permission in linux although we can run any script without execute permission when we execute that script using the syntax bellow?
bash SomeScriptFile
Not all programs are scripts — bash for example isn't. So you need execute permission for executable programs.
Also, when you say bash SomeScriptFile, the script has to be in the current directory. If you have the script executable and in a directory on your PATH (e.g. $HOME/bin), then you can run the script without the unnecessary circumlocution of bash $HOME/bin/SomeScriptFile (or bash ~/bin/SomeScriptFile); you can simply run SomeScriptFile. This economy is worth having.
Execute permission on a directory is somewhat different, of course, but also important. It permits the 'class of user' (owner, group, others) to access files in the directory, subject to per-file permissions also allowing that.
Executing the script by invoking it directly and running the script through bash are two very different things.
When you run bash ~/bin/SomeScriptFile you are really just executing bash -- a command interpreter. bash in turns load the scripts and runs it.
When you run ~/bin/SomeSCriptFile directly, the system is able to tell this file is a script file and finds the interpreter to run it. There is a big of magic invoking the #! on the first line to look for the right interpreter.
The reason we run scripts directly is that the user (and system) couldn't know or care of the command we are running is a script or a compiled executable.
For instance, if I write a nifty shell script called fixAllIlls and later I decide to re-write it in C, as long a I keep the same interface, the users don't have to do anything different.
To them, it is just a program to run.
edit
The operating system checks permissions first for several reasons:
Checking permissions is faster
In the days of old, you could have SUID scripts, so one needed to check the permission bits.
As a result, it was possible to run scripts that you could not actually read the contents of. (That is still true of binaries.)

sudo inside of a script with a command that needs input (bash)

I want to make a script that changes screen brightness and, among others, need this command:
echo "$number" | sudo tee /sys/class/backlight/intel_backlight/brightness
The script asks me for my root password which i think is unnecessary for it only changes the brightness. I tried adding sudo -S and echo-ing the password but not only did i confuse myself with what input goes where, but the script writes out the [sudo] password for user: prompt which is anoying. How do i make the script runable by everyone (both from inside of the script and outside, i do this as an exercise to learn more)?
You might configure your system so that sudo does not ask for any password. I don't recommend doing this (put ALL=NOPASSWD: in your /etc/sudoers file at appropriate place), since it is a security hole.
But what you really want would be to make a setuid executable (BTW /usr/bin/sudo is itself a setuid executable). It is tricky to understand, and you can make huge mistakes (opening large security holes). Read also carefully execve(2) & Advanced Linux Programming. Spend several hours to understand the setuid thing (if you misunderstand it, you'll have security issues). See also credentials(7) & capabilities(7).
For security reasons, shell scripts cannot be made setuid. So you can code a tiny wrapper in C which would run the script thru execve after appropriate calls (e.g. to setresuid(2) and friends), compile that C program as a setuid executable (so chown root and chmod u+s your executable). In your particular case you don't even need to code a C program starting a shell command (you just should fopen the /sys/class/backlight/intel_backlight/brightness pseudo-file then fprintf into it, and fclose it).
Actually, I don't believe that doing all that is necessary, because you should be able to configure your system to let your screen brightness be set by non root. I have no idea how to do that precisely (but that is a different question).

shell script run when I am root but I get a permission denied when it is invoked from a Makefile (still as root)

I need to run a Make script that invokes a shell script.
I can run the shell script directly as root but when running make on the makefile (still as root) make is denied permission to run the same shell script?
The offending line in the Makefile is that one:
PLATFORM=$(shell $(ROOT)/systype.sh)
I could go in and hardcode the value of every PLATFORM variable of every Makefile scrip on the system but that would be pointless fix, I'd like to understand why there is that Permission Denied error:
make[1]: execvp: ../systype.sh: Permission denied
PS: The content of the shell script is not the issue even if the shell script only contain ls or echo linux the Permission is Denied to the Make utility to run the shell script.
PS: I am not a make expert by an mean so if the explanation is related to Make please be as specific as you can.
In your comments above you say when you "run it manually" you use . scriptname.sh, is that correct? You use . followed by scriptname.sh?
That does not run the script, that sources the script. Your statement that scriptname.sh will execute with and without the x permission since it is a shell script is wrong. You can source the script if you have read permissions. But you cannot execute the script unless you have execute permissions.
"Sourcing" means that a new shell is not started: instead your current shell (where you type that command) reads the contents of the script and runs them just as if you'd typed them in by hand, in the current shell. At the end all the side-effects (directory changes, variable assignments, etc.) that were performed in that script are still available in your current script.
"Executing" means that the script is treated like a program, but the program is a new shell that's started, which then reads the contents of the script and executes it. Once the script ends the shell exits and all side-effects are lost.
The $(shell ...) function in make will not source your script (unless you also use . there, which you did not). It will try to run your script. The error you show implies that either systype.sh did not have the execution bit set, or else that it had an invalid #! line. There's no other explanation I can think of.
If sourcing the file really does what you want then why not just use the same method in $(shell ...) that you use in your own personal use:
PLATFORM=$(shell . $(ROOT)/systype.sh)
If changing the user permission didn't work, are you sure that whatever user owns the script is the same user you're using to invoke make? You say you're "running as root"; is the script owned by root? Or is it owned by you and you're running sudo make or similar?
I don't know why you don't just use:
chmod +x systype.sh
and call it a day.
Adding execution permission to the file Group rather that the file User fixed the issue.
PS: I wonder why? It seems the Make utility run shell scripts not with the same user that started Make...

Resources