Karl Karl - 5 months ago 8
Linux Question

Updating environment variables in bash

I have one long running script which does some work with AWS.

I have another script which put environment variables for AWS authentication but that is only valid for 15 mins.

Now i can't chnage the long running script so is there any way that i can have cron job or anything else which can update the environment variables in the shell where long script is running

Answer

Elaborating the comment:

Assumptions

  • The long running script cannot be modified.
  • The long running script will call an executable file that can be modified (for the sake of the example, lets assume that the executable file is /usr/local/bin/callable).
  • You've permissions to rename /usr/local/bin/callable and create a new file under that file path and name.
  • Either the long running script is running as root, or the /usr/local/bin/callable must be able to perform privilege escalation with the setuid bit set.
  • You'll need gdb installed.
  • You'll need to have gcc installed if the long running script isn't running as root.

Risks

  • If this is a critical system and security is a moderate to major concern, do not use any of the following procedures.
  • Although unlikely to happen, but attaching to a running process and injecting calls to it may cause unexpected or undefined behaviours. If this is a critical system doing some critical procedures, do not use any of the following procedures.
  • Generally, all these procedures are a bad idea, but they represent one possible solution. But...
  • Use at your own risk.

Procedures (for long running script running as root)

bash# mv /usr/local/bin/callable /usr/local/bin/callable.orig
bash# cat /usr/local/bin/callable << EOF
> #!/bin/bash
>
> echo -e "attach ${PPID}\ncall setenv(\"VAR_NAME\", \"some_value\", 1)\ndetach" | /usr/bin/gdb >& /dev/null
>
> /usr/local/bin/callable.orig
>
> EOF
bash# chmod 755 /usr/local/bin/callable

Procedures (for long running script NOT running as root)

bash# mv /usr/local/bin/callable /usr/local/bin/callable.orig
bash# cat > /usr/local/bin/callable.c << EOF
> #include <stdio.h>
> #include <sys/types.h>
> #include <unistd.h>
> #include <stdlib.h>
> int main(void) {
>   char inject[128]; /* You may want to increase this size, based on your environment variables that will affect the size of the string */
>   uid_t save_uid = getuid();
>   gid_t save_gid = getgid();
>   sprintf(inject, "echo -e \"attach %u\ncall setenv(\\\"VAR_NAME\\\", \\\"some_value\\\", 1)\ndetach\" | /usr/bin/gdb >& /dev/null", getppid());
>   setreuid(0, 0);
>   setregid(0, 0);
>   system(inject);
>   setregid(save_gid, save_gid);
>   setreuid(save_uid, save_uid);
>   system("/usr/local/bin/callable.orig");
>   return 0;
> }
> EOF
bash# gcc -o /usr/local/bin/callable /usr/local/bin/callable.c
bash# rm -f /usr/local/bin/callable.c
bash# chown root:long_running_script_exclusive_group /usr/local/bin/callable
bash# chmod 4750 /usr/local/bin/callable

Bonus

  • Instead of intercepting, you can, as you stated, use a cronjob to attach to the process with gdb (this will, at least, avoid you to intecept the long running script with another script and, in the worst case, the need to create a setuid binary to do it). You will, however, need to know or fetch the PID of the long running script shell process (as it is changing for each time it is called). It is also prone to failure, due to syncing problems (the script may not be running when the crontab triggers).

References