For anyone that has done a long source code audit is not about really finding the easy/low hanging fruit stuff that can be slow and sometimes a bit “frustrating”. I recently had a nice 660,000 lines of code source code audit to be done in less than 2 weeks, the language was Java, so the first thing that was to be done (they had already hit fortify and other tools with it) and were looking for a bit of more interesting stuff apparently. This raised some specific problems while working and finding the vulnerabilities and exploitability of them.
Static Source Code Audit Issues & Potential Bash Function Resolutions:
I still did my longer hanging fruit greps as I call them and because this was so huge I got hit with a few problems which I have noted below.
Potential Issues During The Beginning Of Source Code Analysis Projects:
- GIT: Code was in git, so all the files I checked out also had compiled jars, libraries, etc.
- Complex grep: A quick and dirty grep will not give you context or show you in a fast an easy way where it is.
- Messy Process: After a few hours, you tend to hate to ctrl-r finding that grep, and either redirect into files will get messy if there is no structure
So I guess everything was setup and ready for it, so after running something as easy as some greps for a bunch of functions to make sure they didn’t have anything weird going on I needed logs and a decent output from everything, so ended up creating a very simple grep:
- grep -r -b #file# #directory# | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3"\n\n"}'
Here is the result of a quick call for strcpy() on an android-sdk directory as an example.
Command: grep For strcpy
- fsckOSX:~ nahual$ grep -r -b strcpy mydroid/ | grep -v "Binary file" | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3"\n\n"}' | more
Output: strcpy Located
- Filename: mydroid/bionic/libc/Android.mk
- line: 3684
- match: string/strcpy.c \
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 0
- match: /* $OpenBSD
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 186
- match: .section .gnu.warning.strcpy
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 216
- match: .ascii "warning
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 462
- match: ENTRY(strcpy)
- Filename: mydroid/bionic/libc/bionic/realpath.c
- line: 2856
- match: (void)strcpy(resolved, ".");
- Filename: mydroid/bionic/libc/bionic/realpath.c
- line: 4146
- match: (void)strcpy(wbuf, p);
- Filename: mydroid/bionic/libc/bionic/system_properties.c
- line: 3699
- match: strcpy(name, pi->name);
- Filename: mydroid/bionic/libc/include/string.h
- line: 2244
- match: extern char* strcpy(char *, const char *);
- Filename: mydroid/bionic/libc/netbsd/nameser/ns_samedomain.c
- line: 4331
- match: strcpy(dst, src);
- ...
- fsckOSX:~ nahual$
Ahhh that is so much better! At least we have now the line of the hit, the match and the filename on a more readable output, as you can see it’s a long line and if you are hitting interesting functions such as impersonation, token generation, which are custom functions. Doing ctrl-R then ctrl-A to go to the beginning of the line and change stuff is a bit annoying to say the least so I got lazy and created this in the .bashrc file.
.bashrc Shortcut Addition Modification:
- search()
- {
- if [ -z "$1" -o -z "$2" ]; then
- echo "Missing parameters: search ";
- else
- grep -r -b "$1" "$2" | grep -v "Binary file" | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3"\n\n"}';
- fi
- }
So this basically checks that you put the pattern and directory as arguments, if you don’t might as well send you an usage if not, just run the same command as before, you could add more grep -v (as you will see in the auditjava() function I created later) to remove unwanted compile files, libraries, etc.
Resource Bash:
- fsckOSX:~ nahual$ . ./.bashrc
- fsckOSX:~ nahual$
You can just call “search” as a bash function and get the output without any ctrl- magic or moving things around.
New Shortcut Commands Making Your Life Easier:
- fsckOSX:~ nahual$ search
- Missing parameters: search
- fsckOSX:~ nahual$
The old search commands from above would now be much easier as shown below with our new bash shortcuts.
Command:
- fsckOSX:~ nahual$ search strcpy mydroid/ | more
Output:
- Filename: mydroid/bionic/libc/Android.mk
- line: 3684
- match: string/strcpy.c \
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 0
- match: /* $OpenBSD
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 186
- match: .section .gnu.warning.strcpy
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 216
- match: .ascii "warning
- Filename: mydroid/bionic/libc/arch-x86/string/strcpy.S
- line: 462
- match: ENTRY(strcpy)
- Filename: mydroid/bionic/libc/bionic/realpath.c
- line: 2856
- match: (void)strcpy(resolved, ".");
- Filename: mydroid/bionic/libc/bionic/realpath.c
- line: 4146
- match: (void)strcpy(wbuf, p);
- Filename: mydroid/bionic/libc/bionic/system_properties.c
- line: 3699
- match: strcpy(name, pi->name);
- Filename: mydroid/bionic/libc/include/string.h
- line: 2244
- match: extern char* strcpy(char *, const char *);
- Filename: mydroid/bionic/libc/netbsd/nameser/ns_samedomain.c
- line: 4331
- match: strcpy(dst, src);
And so forth, so the output obviously is the same, but it’s easily called and can be recalled faster and is honestly a cleaner output for logs, screenshots and your mind has a cleaner path of just remembering search than a huge blob of grep | grep -v | grep -v | awk
This small function is a good thing to have around the entire bash if you are going to check a lot of function calls.
Now its “Java Audit” time!!! This function will allow you to call it form whenever you are and you will get 3 logs inside a folder called security_logs created in the same directory from where it was called (Obviously).
The rc file defines a function called auditjava(), what will it do? it will look for “dangerous” functions, that are the usual culprits on the bugs :)
- system()
- `
- getRuntime(),Runtime, .exec
- preparedStatement(), executeQuery(), execute(), addBatch(), executeBatch()
- getParameter, getQueryString, getHeader, getRequestURL, getCookies, getInputStream, getReader, getMethod, getProtocol, getServerName, getRemoteUser, getUserPrincipal
It sill create 3 files within the security_logs directory:
- command_injection.log
- sql_functions.log
- user_input.log
Well I won’t keep you more, this is the rc file:
- # Java static analysis (very simple) functions
- auditjava ()
- {
- if [ -z "$1" ]; then
- echo "Missing directory to audit!"
- echo "Usage: auditjava "
- else
- if [ -d "security_logs" ]; then
- mkdir security_logs
- echo "[ + ] Directory security_logs created, all logs will go into it"
- fi
- echo "[ + ] Be warned logs WILL BE OVERWRITTEN!"
- echo -n "[ - ] Verifying for possible command injection calls ... "
- grep -r -b 'system(' $1 | grep -v "Binary file" | grep -v 'lib/ruby' | grep -v '.git' | grep -v buildfile | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3\n\n"}' > security_logs/command_injection.log
- grep -r -b '`' $1 | grep -v "Binary file" | grep -v 'lib/ruby' | grep -v '.git' | grep -v buildfile | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3\n\n"}' >> security_logs/command_injection.log
- grep -r -b 'getRuntime(\|Runtime\|.exec(' $1 | grep -v "Binary file" | grep -v 'lib/ruby' | grep -v '.git' | grep -v buildfile | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3\n\n"}' >> security_logs/command_injection.log
- echo "DONE"
- echo -n "[ - ] Verifying for SQL Java Dangerous Functions ... "
- grep -r -b 'preparedStatement(\|executeQuery(\|execute(\|addBatch(\|executeBatch(' $1 | grep -v "Binary file" | grep -v 'lib/ruby' | grep -v '.git' | grep -v buildfile | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3\n\n"}' > security_logs/sql_functions.log
- echo "DONE"
- echo -n "[ - ] Verifying for user input ... "
- grep -r -b 'getParameter\|getQueryString\|getHeader\|getRequestURL\|getCookies\|getInputStream\|getReader\|getMethod\|getProtocol\|getServerName\|getRemoteUser\|getUserPrincipal' $1 | grep -v "Binary file" | grep -v 'lib/ruby' | grep -v '.git' | grep -v buildfile | awk -F : '{print "Filename: "$1"\nline: "$2"\nmatch: "$3\n\n"}' > security_logs/user_input.log
- echo "DONE"
- fi
- }
If saved in a file called auditjava.rc for example, it can be sourced as shown below.
Source auditjava.rc In Bash Terminal:
- fsckOSX:~ nahual$ . ./auditjava.rc
- fsckOSX:~ nahual$
This allows you to be able to call and run it within the terminal whenever you need. Happy bug hunting!