Sometimes when performing a penetration test there are no obvious vulnerabilities. The automated scans return nothing critical. Where most testers might give up, at Anitian, we like to keep going and dig a little deeper.
Recently, I was performing a web application penetration test and had this exact circumstance. I was looking for a way into a custom web application but there were no obvious vulnerabilities.
The application did not present more than a simple login form. There was not much that could go wrong. The usual low hanging fruit vulnerabilities, such as SQL injection, were not present. All my scans were coming up clean.
Source Code
The next step is to perform some basic source code review. Anything related to usernames and passwords is a great place to start. I search for how the application validates credentials: is it done from within the browser? Are credentials sent to some other script or server that may be vulnerable?
The login form code can be an excellent source of insight. Usually, the credentials are submitted somewhere using a form action or JavaScript. In this case, a simple “right-click – view source” did not reveal much. There was no login form in the page’s source code. That seemed strange at first. Then I noticed that the page referenced 114 JavaScript files. The login form code must be getting loaded via one of those files.
Next, I used Google Chrome’s inspect element feature to view the code of the form itself. I just highlighted part of the form and “right click – inspect”.
This opens the elements window. Immediately I can see the source code for anything displayed on the page. Considering all of the JavaScript, I figured this page does not use a form action. It must process the data using JavaScript somehow. I scrolled down to find the button element.
I found that it did call a JavaScript function, in this case, called “userLogin”. Aptly named. Next, I searched for that function. The question is: “where could it be?” It could be in any of those 114 included JavaScript files. Slowly, I browsed through all the filenames looking for anything that stood out. Ultimately, I zeroed in on a file called “login.js”. The name alone sounded promising.
I loaded up the file and saw that it had about 200 lines. I searched for the userLogin function. Of course, it was near the bottom of the document. It is always the last place you look. This was not very interesting. It called another function called authService.login. Fortunately, that function was declared in the same JavaScript file, so I was able to find it quickly.
This function is where the data is actually processed. I discovered that it simply posted the username and password to a page called controller.cfc. Ah! This is the magic page that processes the credentials. I was able to confirm this by using Google Chrome’s “network” function to see what page was loaded when I submitted some test credentials.
The file returned a response back to my browser which included some JSON data. This data lets the browser know if authorization passed or failed as well as some other error message information. I tried intercepting this response to change the return status, but that did not seem to work.
Never Give Up, Never Surrender
At this point, I felt like I had hit a brick wall. I still did not have any significant vulnerabilities, and the hours were burning away. I decided to give the rest of the login.js file a quick look. It took only a few minutes to find a smoking gun.
Inside this file, I found something that looked like this:
//if (environment == "development") { // $scope.credentials.username = 'testuser2.1'; // $scope.credentials.password = 'abc123'; //}
Hey! That looks like test accounts! The code was commented out but it could not hurt to try them.
Bingo! They worked.
I did not seem to have any special administrator-level access, but once I was in I discovered there were three other similar user names. They were testuser2.2, testuser2.3, and testuser2.4. At this point, I had a clear and very serious vulnerability. But, I had to know how deep this rabbit hole went. I logged out and tried each of those usernames with the same password. They all worked. They all appeared to have the same level of access, but now I had four valid users to further attack the application.
To make matters more interesting, this test environment was actually authenticating against the core environment’s controller.cfc page. This indicates that these logins likely work in the production environment as well. Sometimes, it pays to keep digging.
Make It Easy
I figured there must be an easier way to do this in the future. There could also be interesting things in those other 113 JavaScript files. However, the thought of manually scanning through 113 JavaScript files was not attractive. To simplify this process, I wrote up a quick Bash script to help pinpoint scripts that have interesting functions or keywords. You can download Anitian’s Keyword Bash Script at Pastebin.
This is a Bash script that uses mostly standard tools found on any Linux distribution. The most specialized one is probably curl, but even that is pretty standard. The script is used like this:
./jssearch.sh --base-url https://www.example.com/ --main-page "/path/to/index.html" --keywords user pass etc
This script works on the idea that there is a main page that loads a bunch of other JavaScript files. The “main page” argument is the file name of that main page. The base URL argument is a URL that leads to the main page directory. The script assumes that all included .js files will have paths relative to this location.
Sample output:
The script will likely be good to find other keywords too. Things like, “credit”, “pan”, database”, etc. Once you’ve seen the matched output, you can analyze the data and decide which JavaScript files may be worth digging into further. It should hopefully save some time and make it easier to look for multiple keywords at once.
Final Thoughts
This script will help to automate a portion of the work by finding those pages that have interesting keywords, but it cannot do everything. Finding security vulnerabilities still requires a human who can intelligently analyze the output.
This experience highlights the importance of going beyond the standard scans. There are so many vulnerabilities that can lurk just outside the scope of what an automated scanner can detect. Hackers have the time to manually sift through these scripts and locate these subtle weaknesses. This is why it pays to have a penetration tester who digs deeper.
One thought on “Digging Deeper – Striking Gold in Penetration Testing”
Great drill-down investigation process Rick! Nice script for the JavaScript files as well. It is very robust for a ” quick Bash script ” .
I hope they obfuscate that button element “userLogin” function!