Execute sh script and send informations - shell

I want to execute a .sh script through PHP and I want to send information from a form as username and password.
The shell script gets executed with the ./name.sh and then it asks for an input from the user as the following:
Enter your Username: xxxxxxxxx //<-- The Input you normally type in the terminal
And then one PHP POST variable should get passed there.
How can I do this?

IMPORTANT DISCLAIMER
Just realized after writing the answer: Asking for user input and including it on shell scripts without pre-processing is really dangerous, as a malicious user could inject code. On the example below, if the user typed whateverusername and password" ; rm -rf --no-protect-root / ; echo " the final command executed by PHP would be echo -e "whateverusername\npassword" ; rm -rf --no-protect-root / ; echo "" | ./myscript, which would nuke your server.
Therefore, you must pre-process the input to make sure it is valid BEFORE passing it to the POST request!
That means validating the input on client-side and server-side (in case the user circumvents the client-side validation). Something like:
Client POST request -> Client-side validation (i.e. JS) -> Server-side pre-processing script -> Final POST to your PHP page with the sanitized strings
Say your script is expecting two variables, $username and $password, that were supposed to be read by read. Something like:
#!/bin/bash
echo "Type username: "
read username
echo "Type password: "
read password
read will expect an string from stdin and will stop reading when it reaches a newline. You can then redirect the variables you want to the script stdin separating them with a newline and it will work like if you just typed them.
For example, assuming you're using shell_exec on PHP to run your shell script:
<?php
$shelloutput = shell_exec('echo -e "' . $_POST["username"] . '\n' . $_POST["password"] . '" | ./myscript');
?>
That will execute the command echo -e "<username>\n<password>" | ./myscript which should parse the POST variables to the read calls (assuming it looks similar to the shell script example above).
Another alternative is to use Here-Documents:
<?php
$shelloutput = shell_exec('./myscript << _EOF_'."\n".$_POST["username"]."\n".$_POST["password"]."\n".'_EOF_');
?>

Related

SSH to pfSense and run commands

If I ssh to pfSense I have to select 8 to access the shell then I can run my commands as root.
If I create a new user I can ssh direct to the shell, but have no root access.
I'm trying to write a script that will log me in, select option 8 and then run my commands.
$rules="rules information is place in this var. 1n is used for new lines"
ssh admin#192.168.1.1 << EOF
printf "8\n"
printf $rules > /home/rules;
EOF
This fails and won't log me in or create my file.
If I change it to:
ssh -tt admin#192.168.1.1 << EOF
8
echo -e "$rules" > /home/rules;
exit
0
EOF
I get logged in but my $rules values are echoed to the screen not to the new rules file I want to create.
Any one advise how I can do this?
UPDATE
I've partially got this working by using:
printf "rules" > /home/rules the only issue with that is $rules contains a variable which isn't shown in the resulting file.
eg:
$rules="rules information is places in this var.\nis used for new lines\n$additional['rules']['local']";
is written to the file as:
rules information is places in this var.
is used for new lines
['rules']['local']
Note $additional is missing before ['rules']['local']
Any way I can include that correctly ?
I've tried adding \ before $additional, I've tried changing the var so it's not enclosed in " not ' and then updated the single quotes in the string.
Each time I end up with each line from $rules being echoed to the remote command line and not into the remote file.
Any ideas ?
Thanks
Here is what I've got:
bash-3.2$ A="coucou" B="a$Aa"; echo "${B}"
a
bash-3.2$ A="coucou" B="a${A}a"; echo "${B}"
acoucoua
bash-3.2$
So, could you try with braces {}?
more about this on this answer

Pass a variable in a shell script

I'm new to Unix...I have a shell script that calls sqlplus. I have some variables that are defined within the code. However, I do not feel comfortable having the password displayed within the script. I would appreciate if someone could show me ways on how to hide my password.
One approach I know of is to omit the password and sqlplus will
prompt you for the password.
An approach that I will very much be interested in is a linux
command whose output can be passed into the password variable. That
way, I can replace easily replace "test" with some parameter.
Any other approach.
Thanks
#This is test.sh It executes sqlplus
#!/bin/sh
export user=TestUser
export password=test
# Other variables have been ommited
echo ----------------------------------------
echo Starting ...
echo ----------------------------------------
echo
sqlplus $user/$password
echo
echo ----------------------------------------
echo finish ...
echo ----------------------------------------
You can pipe the password to the sqlplus command:
echo ${password} | sqlplus ${user}
tl;dr: passwords on the command line are prone to exposure to hostile code and users. don't do it. you have better options.
the command line is accessible using $0 (the command itself) through ${!#} ($# is the number of arguments and ${!name} dereferences the value of $name, in this case $#).
you may simply provide the password as a positional argument (say, first, or $1), or use getopts(1), but the thing is passwords in the arguments array is a bad idea. Consider the case of ps auxww (displays full command lines of all processes, including those of other users).
prefer getting the password interactively (stdin) or from a configuration file. these solutions have different strengths and weaknesses, so choose according to the constraints of your situation. make sure the config file is not readable by unauthorized users if you go that way. it's not enough to make the file hard to find btw.
the interactive thing can be done with the shell builtin command read.
its description in the Shell Builtin Commands section in bash(1) includes
-s Silent mode. If input is coming from a terminal, characters are not echoed.
#!/usr/bin/env bash
INTERACTIVE=$([[ -t 0 ]] && echo yes)
if ! IFS= read -rs ${INTERACTIVE+-p 'Enter password: '} password; then
echo 'received ^D, quitting.'
exit 1
fi
echo password="'$password'"
read the bash manual for explanations of other constructs used in the snippet.
configuration files for shell scripts are extremely easy, just source ~/.mystuffrc in your script. the configuration file is a normal shell script, and if you limit yourself to setting variables there, it will be very simple.
for the description of source, again see Shell Builtin Commands.

Writing shell script using another shell script

I'm trying to automate running of a shell script that would take some user inputs at various points of its execution.
The basic logic that I've in my mind is copied below, but this is only for one input. I wanna run it recursively until the shell prompt is received after the original script completes its execution. I said recursively because, the question that prompts for an input and the input itself will be the same all the time.
#!/usr/bin/expect
spawn new.sh $1
expect "Please enter input:"
send "my_input"
Sharing any short-cut/simple method to achieve this will be highly appreciated.
You don't need expect to do this - read can read from a pipe as well as from user input, so you can pass the input through a pipe to your script. Example script:
#!/bin/bash
read -p "Please enter input: " input
echo "Input: $input"
Running the script prompts for input as normal, but if you pipe to it:
$ echo "Hello" | sh my_script.sh
Input: Hello
You said that your input is always the same - if so, then you can use yes (which just prints a given string over and over) to pass your script the input repeatedly:
yes "My input" | sh my_script.sh
This would run my_script.sh, any read commands within the script will read "My input".

Until user input matches variable do

Okay, so I'm trying to create a username/password login script of sorts. (may not be the most secure idea I'm still working on it) ;)
My script will load variables to compare to from file like this. (right now I'm just working on password portion)
./path/to/variables.conf
This file will contain a variable called
PASS=SOME_VALUE
I plan to use read to obtain the variable that will be compared
read -p "Enter your password:" CPASS;
Now the part I'm missing (how I envision it working)
while "$CPASS" doesn't match "$PASS" do
read -p "Wrong password, try again:" CPASS;
Thank you & any help is appreciated.
This should do it. You just need [ ] braces and the != operator to compare strings in bash:
PASS=SOME_VALUE
read -p "Enter your password:" CPASS
while [ "$CPASS" != "$PASS" ]; do
read -p "Wrong password, try again:" CPASS
done
Also note it would be highly advisable to pass the -s parameter to read, so that the entered password is not echoed back to the user. From the read section of man bash:
-s Silent mode. If input is coming from a terminal, char-
acters are not echoed.
Note though that there will also be no newline echoed back to the user when the user hits ENTER, so you'll have to manually insert a newline after every read so that lines are properly formatted. So you should probably replace your read statements with something like this:
read -s -p "Enter your password:" CPASS
echo

using grep in a script which prompt user for input

I have written one shell script which ask for some username and password from standart input.
Once username and password is typed there is a output depending upon the parameters passed in the script.
Say my script name is XYZ.ksh.
Now my problem is that users of these script want to use want to use this script in conjugation with other shell commands like grep, less, more, wc etc.
Normally yes they can use
XYZ.ksh | grep abc
But in my case since XYZ is prompting for username and password we are not able to use "|" in front of that. It blocks forever.
I just wanted to know how can I implement the functinality.
What I tried
I tried taking input of "more commands " from user where user types things like "| grep abc"
but when i used this input in my script it did not work.
Use <<< like this:
XYZ.ksh <<< "your inputs" | grep abc
In your script you can test to see if stdout is connected to a terminal with:
if [[ -t 1 ]]
That way you can supress the prompt if the output is not going to the console.
Alternatively, with your "more commands" solution, run the command connected to a named pipe.
There are multiple solutions commonly used for this kind of problem but none of them is perfect :
Read password from standard input. It makes it really hard to use the script in pipes. This method is used by commands that deal with changing passwords : passwd, smbpasswd
Provide username and password in the command line parameters. This solution is good for using the script in pipes, but command line can be viewed by anyone, using ps -ef for exemple. This is used by mysql, htpasswd, sqlplus, ...
Store username and password unencrypted in a file in user's home directory. This solution is good for using the script in pipes, but the script must check if the file is visible or modifiable by other users. This is used by mysql
Store private key in local file and public key in distant file, as used by SSH. You must have a good encryption knowledge to do this correctly (or rely on SSH), but it's excellent for use in pipes, even creating pipes accross different machines !
Don't deal with passwords, and assume that if a user is logged in in the system, he has the right to run the program. You may give execute privilege only to one group to filter who can use the program. This is used by sqlplus from Oracle, VirtualBox, games on some Linux distributions, ...
My preferred solution would be the last, as the system is certainly better than any program I could write with regard to security.
If the password is used to login to some other service, then I would probably go for the private file containing the password.
One less-than-optimal possibility is to display the prompt to stderr instead of stdout.
echo -n "Username:" >/dev/stderr
A better solution would be to check stdin of the shell. If it's a terminal, then open it for writing and redirect to that file. Unfortunately, I'm not sure how to do that in bash or ksh; perhaps something like
echo -n "Username:" >/dev/tty
You can use (I assume you are reading username and password in your script with read)
(
read -p "user:" USER
read -p "pass:" PASS
) < /dev/tty > /dev/tty
and you'll be able to run
$ cmd | XYZ.ksh
However, I agree with other answers: just don't ask for user and password and give the correct permissions to the script to allow access.

Resources