Score:0

How can I get valid path from argument in #!/bin/sh script?

cn flag

I have some script(copy) and want to get valid path.

#!/bin/sh
cp -R $1 $2

I tried with parameter like this

./copy.sh /home/apple /home/pie;reboot

then server was rebooted and it's not acceptable in production server.

I know linux path is composed only with [a-zA-Z0-9_-/. ]

How can I filter $1 and $2, so I can call without worry.

#!/bin/sh
$filtered_path_1=some_filter_funtion($1)
$filtered_path_2=some_filter_function($2)
cp -R $filtered_path_1 $filtered_path_2

Background

I have jenkinsfile and call sh 'sudo /home/copy.sh ${Workspace} ${targetdir}' in this jenkinsfile. Because jenkins user has no write access on ${targetdir}, I gave jenkins user root privileges only on this copy.sh script via

sudo visudo jenkins    
ALL = NOPASSWD: /home/copy.sh, 

And this jenkinsfile is in git repository. If bad guy modify this jenkinsfile with bad code like reboot and commit it, then copy script is called automatically. Because this script is called in root privilege, he can do bad things using this weakpoint. He will remove sh 'sudo /home/copy.sh ${Workspace} ${targetdir}', and will add sh 'sudo /home/copy.sh /tmp /var;reboot'.

How can I protect him?

cn flag
Paste your code into https://www.shellcheck.net for advice that will solve this problem.
Denis Turgenev avatar
cn flag
@glenn, thank you, and I think it doesn't give solution how to change $1->$safe1.
ru flag
@DenisTurgenev It has nothing to do with argument parsing to make it safe. It ahs everything to do with the shell environment you're executing in by default (i.e. bash). My answer details this in the entirety. And gives you a test script and command set that shows you this in action without exploding your system
bac0n avatar
cn flag
`./copy.sh evil.sh copy.sh` whoops
Score:2
ru flag

This has nothing to do with your script. In Bash shell, the ; is seen as the termination command for the string of commands, and then right after it is a secondary command. So in effect the way your stuff was processed as follows.

  1. Execute command before the ;:

    ./copycron.sh /home/apple /home/pie
    
  2. Execute second command after the ;:

     reboot
    

Because you were executing likely as root or superuser, it successfully rebooted.

However, if you do something more specific and execute another arbitrary command after the ; instead, you'll notice that command gets run. Your two arguments to your script will remain /home/apple and /home/pie respectively. The script never sees the ;reboot part because that's not parsed as an argument. This is a Bash limitation and not something in your script.


You can test this with the following script and then command calls:

FILE: argecho.sh

#!/bin/bash

echo "Space delimited arguments: $*"
echo ""
echo "------"
echo ""

COMMAND TO EXECUTE: ./argecho.sh foo bar baz /tmp/something.txt;echo I Did Something Else

OUTPUT:

$ ./argecho.sh foo bar baz /tmp/something.txt;echo I Did Something Else Outside The Script, see?
Space delimited arguments: foo bar baz /tmp/something.txt

------

I Did Something Else Outside The Script, see?

You'll notice the 'echo' and the other arguments in it were not included in your arguments in your script. This is Standard Bash Behavior.



Based on your edits, your concern is that someone is going to hijack your Jenkins repository commands and issue a malicious command, by changing the script from sh 'copycron "${Workspace}" "${targetdir}"' to sh copycron /home /boot;shutdown

Unfortunately for you, this has absolutley nothing you can fix, this would result in a failure of you to properly control who has access to the command repositories. Such threat actors would have a lot more access to damage your system, not just run a simple command like the aforementioned changes. They'd more likely install malware on your system, than anything, and unless you properly secure your command repositories so that nobody can just 'randomly edit them', your lack of control of the repositories is what'll screw you over.

There's no real hardening we can do here if the jenkins user has unlimited sudo privileges either. There just isn't, because this is going to rely on you properly securing your systems or building an alternative deployment mechanism that is more secure and doesn't require full sudo to work with everything.

Denis Turgenev avatar
cn flag
I have jenkinsfile and call `sh 'copycron ${Workspace} ${targetdir}'` in jenkinsfile. And this jenkinsfile is in git repository. jenkins user have root privileges only on this copycron script via `sudo visudo jenkins ALL = NOPASSWD: /home/copycron`, because jenkins has no write access to ${targetdir}, and if bad guy modify this jenkinsfile with bad code like reboot and commit it, then copycron scripts is called automatically, and because this script is called in root privilege, he can do bad things.
ru flag
This is a limitation of your call via `sh` not a limitation of everything else or even your script. The problem is `sh` executes this in a shell just the same as if I execute it in Bash. You should be putting full quotes around your arguments if you want it to 'sanitize' and not run it. I.E. `sh 'copycron "${Workspace}" "${targetdir}"'` That way it treats the ; as part of the string. Then your script will simply error out because targetdir can't be found.
Denis Turgenev avatar
cn flag
The problem is bad guy can change my fine-grained script easily. `sh 'copycron "${Workspace}" "${targetdir}"'` -> `sh copycron /home /boot;shutdown` Because jenkins file is in git repository.
ru flag
@DenisTurgenev I think i have to ask a different question: why are you concerned that 'bad guy' is involved? If the repository is properly secured, bad guy won't have access to edit script. If bad guy *gains* access to the script, you are hosed either way, there's no way to sanitize the command that you're specifying. That's a failure to control your repositories, not a Bash script issue and *not* something that you will be able to protect against if you don't secure your command repositories properly.
Denis Turgenev avatar
cn flag
By the way what do you call such bad guy in security term? :) I am not security expert and also not english expert.
Denis Turgenev avatar
cn flag
This is project developed by 50 developers and of course only these people can access by their account. For example, one developer was fired, and while he leaving company, saying 'go to hell!', and can execute this. But is this too harsh assumption? :) I like imagining extremely, so forgive me if I was too harsh.
ru flag
This is a larger discussion than comments can carry out, and would start requiring my security hat on to give you a proper explanation of the "insider threat" problem and improper user management and improper auditing on your side. If you want to have that chat, I can create a chat room for you and I to discuss this in depth, however it's a far more in depth problem than can be discussed in comments.
Denis Turgenev avatar
cn flag
thanks, I'll collect some more security issues and will contact you soon. thanks for your time and valuable help.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.