Webverselabs ScanPortal Challenge Command Injection
Scenario :
ScanPortal is an attack surface management platform for SMBs. The developer recently hardened the nmap call after a code review flagged it. What they missed is that every submitted target is also appended verbatim to a shared scan log, and the customer-facing log search runs grep on that file with the user’s pattern dropped straight into a shell command.
Solution :
We first start by creating a new account and login in , to be able to enumerate the application further .
We are able to identify multiple endpoints, let’s go through each one of them :
/Assets :
This just gives us a list of IP addresses , hostnames , and OS for each server running.
/Vulns :
This is a list of vulnerabilities found ranked by criticality .
/Scans :
/Scan Logs :
This is the log file of all scans performed , for now we haven’t done any .
The only endpoint that looks interesting is the /scans endpoint , if we perform a scan and look at the request :
We see that it sends a POST request to the server , with the IP we specified as well as scan_type ,then it redirects us to the scan result page : the server is probably doing an nmap scan in the background and returning to us the result in a table format .
Whenever we suspect the backend may execute commands based on user input, we should test for command injection. If inputs aren’t properly sanitized, we may be able to execute arbitrary commands on the server.
I have a detailed section in my web_methdology for command injections based on the CWES path :
1
https://elmehdilaassiri.github.io/posts/web-app-pentesting-methodology/#command-injection-
Now first i injected a semi column in both parameters to see if it will break anything .
We see that if we inject the IP address field , it will just be returned to us which means it wasn’t executed by the server.
Checking the scan_type parameter returned the same thing, i tried multiple payloads :
At first i thought maybe we can break our of a “” or ‘’ , maybe injecting ${} will execute commands inside the quotes rather than returning it via an echo command or something but that didn’t work .
Finally i moved back to the Logs :
We see that we are able to search for specific logs, maybe the server is using a command in the backend this time as well to fetch for specific logs based on keywords, if we check Burp’s History :
Let’s try to use the same injection payloads from earlier on this parameter :
Good news we manage to get a different error this time :) , the server is telling us that we got an unterminated quote .
Probably we have a grep command running in the background or some other linux command :
1
grep "aaaa"";${id}
I think having 3 quotes broke it, let’ try adding a fourth one :
We no longer have the quotation problem , but we get a permission denied .
I first thought that we can only add different files to the command to trick the app into rendering the file but that didn’t work either :
Another thing we can try is once we break out of the “” , and we add our command , we comment out the rest just like we do in a normal SQLi , to make sure we don’t break the original command syntax.
This works perfectly :
Now we can easily get our flag :
Let’s also try to read the source code to see what was really going on in the backend .
The app source code is in app.py :
Perfect , we see that it was indeed using a grep command and putting everything inside a double quotes , so when we added “ we broke out of it and were able to execute our code .
That was all for this challenge , see you in the next one :)