Bizarre Bash

main img

init

Hi Y’ALL, this blog post covers the analysis of weird things in bash that is posted on twitter by Alex Chapman. The image below shows the tweet. By creating files with weird names that have a newline in the filename and creating a tar archive on these files and then executing using ./ (bash method) will be executed as a shell script. The irony here is bash will execute any files that have newlin characters in the starting bytes and we will see it in a while.

tweet

Normal Flow

First of all, lets us try taring normal files instead of files with weird names.

cmd img

we use touch to create new empty files such as file1 and file2. we archive the files in tar format. To note, tar is not used for compression until it is used with gzip which will end in .tar.gz. And then, chmod is used to give execution permission and then we execute it by using ./. Bash tells us a sweet message ‘exec file format error’. Of course, we know that tar files are not executables. But bash rules the execution because it is the one that forks and exec the file and creates a child process(new process) and so bash will be the parent. Since bash is the parent of the commands that are run in a bash terminal, we can use strace to see the workflow on how bash executes ./runme.

Now we will get the PID of the bash terminal from ps aux and then use strace to trace syscalls made by the process

strace img
strace-1 img

Now we will run the tar file and analyze strace output. I have cut-shorted the strace output such that it contains only important information. As we see from the above image, it clones to create a new child process and executes the file runme by calling the exec syscall and it fails. The reason it fails is that the file should be of ELF format to get executed. The error message is returned from the bash, write syscall is called and finally, it prints the error. Now it is all good, but we will try now the weird workflow.

Weird Flow

Okay, now we insert newline characters in starting bytes of the runme file. We just see hexdump and modify the starting bytes to include a newline using radare2.

weird flow img

As we see from the above image it ran as a shell script. we will see the strace output to understand it better.

weird strace output

From the strace output, we can deduce that the bash will create a child process and executes runme using execve syscall, it failed as it is not a ELF format file. But since there is a newline, bash tries to execute it as a shell script. It tries to access /usr/bin/bash and it searches the file file1 (first file’s filename in runme tar). since it can’t find the file1 bin, it shows the message command not found. If we give a valid command as a filename with a newline in it, then it will be executed as a shell script.

exit

Now we will add a valid command with a newline in the filename and execute it. To include a newline in the filename, we use the bash newline feature that is $’\n’. When bash sees this $’\n’ it will be replaced by the newline. You can try it using echo $'\n'.

final img

In tar, filenames of the file included will be in the starting bytes and if we have a newline in starting bytes, bash will execute its magic by executing the tar file as a shell script and it is not only the tar file can execute, any file can be executed if it contains newline in starting bytes. From the above image, the newline is added in the filename by using $’\n’ and when tared, the filenames will be in the starting bytes 690a(0a is the newline) and finally, bash thinks that it is a shell script and executes. Another way of telling the bash to execute as a shell script is by having the text #!/usr/bin/bash in the starting line, this way of telling the bash to execute is a normal way but newline character was new to me, If it was new to you, share this to others.

Will see ya in the next blog until then happy learning!!.bizz