Sometimes, a DBA has to write an externally called wrapper script for various Oracle-supplied commands accepting password inputs. A prominent and simple example is SQL*plus (sqlplus).
The Problem
The process list shows all parameters of a command that’s currently executed.
wrapper1.sh
Accepts all connection infos on the command line:
#!/bin/bash cmdstring="sqlplus ${1}/${2}@${3}" echo "Executed command: $cmdstring" sleep 999
Called by:
$ ./wrapper1.sh system manager mydb Executed command: sqlplus system/manager@mydb
But now, the password is visible in the process list:
$ ps aux | grep wrapper1.sh | grep -v grep 1000 20769 0.0 0.0 13808 1444 pts/1 S+ 15:19 0:00 /bin/bash ./wrapper1.sh system manager mydb
Solution 1: Not Half Bad
Use here string syntax to get the password out of the process list cmd line.
wrapper2.sh
Uses READ to get input from stdin.
#!/bin/bash read -p "DB Password: " -s dbpassword echo cmdstring="sqlplus ${1}/${dbpassword}@${2}" echo "Executed command: $cmdstring" sleep 999
Called by: $ ./wrapper2.sh system mydb <<<'manager' Executed command: sqlplus system/manager@mydb
You can’t see the password in the process list any more, since the here string component is something your bash does for you:
$ ps aux | grep wrapper2.sh | grep -v grep 1000 21509 0.0 0.0 13808 1452 pts/1 S+ 15:25 0:00 /bin/bash ./wrapper2.sh system mydb
But here strings are represented as file descriptors, so the OS user and root still can see the password over its file handle.
The file itself was in /tmp, but is deleted for good reason. So you can’t find it there any more, but the handle is still open, and we cann see its content:
$ ls -l /proc/21509/fd/ insgesamt 0 lr-x------ 1 user user 64 Apr 30 15:31 0 -> /tmp/sh-thd-1398841958 (deleted) lrwx------ 1 user user 64 Apr 30 15:31 1 -> /dev/pts/1 lrwx------ 1 user user 64 Apr 30 15:30 2 -> /dev/pts/1 lr-x------ 1 user user 64 Apr 30 15:31 255 -> /home/user/test/wrapper2.sh
$ cat /proc/21509/fd/0 manager
Solution 2: Better, but still not perfect
Use a pipe to get rid of the here string content in the file handle
wrapper3.sh
Again, we have READ to get data into the password variable, the only difference to wrapper2 is that this one has an additional sleep in the beginning to give us time for some dirty games. 🙂
#!/bin/bash echo "sleep 60" sleep 60 echo "Sleep is over" read -p "DB Password: " -s dbpassword echo cmdstring="sqlplus ${1}/${dbpassword}@${2}" echo "Executed command: $cmdstring" sleep 999
Called by:
$ echo 'manager' | ./wrapper3.sh system mydb sleep 60 Sleep is over Executed command: sqlplus system/@mydb
Again, we have no password in the process list. the ECHO is not in the process list, since I used the bash builtin ECHO, that’s not represented individually. Should you use /bin/echo, you’d have the password in the ps list again.
$ ps aux | grep wrapper3.sh | grep -v grep 1000 25324 0.0 0.0 13808 1412 pts/1 S+ 15:56 0:00 /bin/bash ./wrapper3.sh system mydb
And when we do nothing, the fd/0 file is empty, because the script read it:
$ cat /proc/25324/fd/0 $
But when we interfere earlier, we can “steal” the password out of the file descriptor:
$ echo 'manager' | ./wrapper3.sh system mydb sleep 60
$ ps aux | grep wrapper3.sh | grep -v grep 1000 26750 0.0 0.0 13808 1412 pts/1 S+ 16:09 0:00 /bin/bash ./wrapper3.sh system mydb
The password is “in the pipe” now, the script has not READ it yet. So we can suck it out:
$ cat /proc/26750/fd/0 manager
Of course, the script can’t get the password now any more, usually the script will fail.
$ echo 'manager' | ./wrapper3.sh system mydb sleep 60 Sleep is over Executed command: sqlplus system/@mydb
But the password now is in the hands of the guy executing the CAT command.
Summary
- Easily avoid having your passwords on display in the process list, everybody with login rights on the server can read them!
- Use here string syntax or even better, piping and the READ command to get the password into the script. Only root or the same OS user executing the script can read/steal the password now.
Ok, but did you really try it?
How did you achieve actually calling the command, instead of only echoing it, and not having it on the “ps” output?