Skip navigation

The jsp backdoor I mentioned in the last post inspired me to do a little playing around with php backdoors. PHP backdoors range from incredibly simple to extremely elaborate, and can either be independent .php scripts uploaded to a vulnerable server, or inserted directly into a page. The interfaces for some of these shells are quite distinctive, and I thought, surely some of these shells have to have been indexed by search spiders?

Google provides a search API, but it is fairly limited in the number of searches you can perform per day. It only returns a couple results at a time, meaning you have to perform several requests to get a decent number of results per search. The API is also deprecated, so they reserve the right to turn it off at any time.

The shell I’m focusing on for now is the WSO Shell (Web Shell by Orb). Like many shells, it includes a set of server stats along with the command line. A google search for the string of terms “uname user php hdd cwd WSO” currently returns about 12,700 results. The results from the first page are divided into two groups:

  • People asking for help with their compromised servers
  • Websites with the shell interface bang in the middle (bingo!)

I whipped up a pretty shaky python script to do the heavy lifting:

#!/usr/bin/env python

import sys
import httplib
import json


WSOShell = '/search?btnG=1&pws=0&q=uname%20user%20php%20hdd%20cwd%20WSO'

def usage():
	print "Usage:"
	print "./ [mode]"
	print "Modes: --easy, --hard"

def get_json_results(start):
	conn = httplib.HTTPConnection('')
	response = conn.getresponse()
	json_data = json.load(response)
	results = json_data['responseData']['results']
	for i in range(len(results)):
		print "| " + results[i]['titleNoFormatting']
		print "| - " + results[i]['unescapedUrl']

	if(len(sys.argv) > 1):
		if sys.argv[1] == '--easy':
			print "Scraping small result set from json api."
			print "| Results --------------------------------------"
			for i in range(10):
			print "|-----------------------------------------------"
		elif sys.argv[1] == '--hard':
			print "Scraping bigger result set from search."
				#Room for expansion here
except IOError, e: 
	if hasattr(e, 'code'): # HTTPError 
		print 'http error code: ', e.code 
	elif hasattr(e, 'reason'): # URLError 
		print "can't connect, reason: ", e.reason 

… and along comes the stream of nicely formatted results.

Extensions to make:

  • Bypass limits/risks of API by making a scraper for regular google search results
  • Add more search strings for other types of shell
  • Tunnel requests through assorted proxies to avoid IPs getting blocked for too many searches
  • Store results in database for easy storage
  • Disclaimer: I didn’t go on any of these sites. Verification of the shell’s presence was performed by checking the preview screenshot Google supplies with the search results. The most responsible use of the information presented here would be to warn website owners that their machines have been compromised.


One Trackback/Pingback

  1. […] bitsmash Digital notepad for technical adventures. Skip to content ← Finding Compromised Hosts with the Google Search API […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: