Posted on August 14, 2007 in Python by adamNo Comments »

One of the most powerful aspects of Jython is that you have native java objects and native python objects playing together in the same script. It also is one of the more confusing parts when you start trying to access python one in a java manner, or vice versa.

The application that I am scripting up with Selenium (via Jython) is for car dealerships. A new feature is that you can bundle a number of dealers as a ‘group’ to apply policies in a more convenient manner. Due to the nature of how the app is built, you cannot delete a group but can only mark it as inactive. This leads to the usual dirty data problem of automation. How can I make a group, if it is already created?.

The answer is of course to just be sneaky and nuke it from the database when the application isn’t looking. This code snippet make use of the connection I created here to first retrieve some information from a table, then use it to remove some information from a different one — all using prepared statements to ensure we are not susceptable to sql injection (not that this case is ripe for abuse, but it’s good to get in the habit of doing things securely).

def removeDealerGroup(self, dgid):
    # get the dealer group oid
    try:
        pstmt = self.connection.prepareStatement("select oid from group where group_id = ?")
        pstmt.setString(1, dgid)
        rset = pstmt.executeQuery()
        rset.next()
        oid = rset.getInt("group_oid")
    except java.sql.SQLException, e:
        if e.getMessage().find("Exhausted Resultset") != -1:
            return "Dealer Group %s does not exist" % dgid

    # get rid of the dealer group and associations
    msg = ""
    try:
        try:
            # remove the dealer association
            pstmt = self.connection.prepareStatement("delete from bank_group_assoc where oid = ?")
            pstmt.setInt(1, oid)
            rset = pstmt.executeQuery()
        except java.sql.SQLException, e:
            msg = "Could not remove dealer association"
            raise java.sql.SQLException, e
    except java.sql.SQLException, e:
        self.connection.rollback()
        #print e.getMessage()
        return msg
Posted on August 10, 2007 in Python by adamNo Comments »

While fighting to get my classpath correct in Jython, I decided I needed to see what it was. Inspired by this post, here is how you display the classpath in Jython.

import java.lang
import java.net.URL;
import java.net.URLClassLoader;
        
sysClassLoader = java.lang.ClassLoader.getSystemClassLoader()
urls = sysClassLoader.getURLs();
for url in urls:
    print url.getFile()
Posted on August 9, 2007 in Python, Quality by adamNo Comments »

Whenever automating web tests, you need to verify not only that the correct objects are appearing in the browser, but that the correct content is being retrieved from the database. This is not that easy when writing Selenium scripts in Selenese (the HTML table based language). It is however easy when writing Selenium RC scripts in whatever language you happen to be using, in my case it is Jython.

Inspired by this post, here is how you can access Oracle from within Jython. If you need to get different information, then you just add another method.

from oracle.jdbc.driver import OracleDriver
from java.sql import DriverManager

class oracle(object):
    def __init__(self, un, pw, sid, host, port):
        driver = OracleDriver()
        DriverManager.registerDriver(driver)
        connection_string = "jdbc:oracle:thin:@%s:%s:%s" % (host, port, sid)
        self.connection = DriverManager.getConnection(connection_string, un, pw)

    def getPermissionCode(self, uid):
        stmt = self.connection.createStatement()
        rset = stmt.executeQuery("select a bunch of stuff that isn't relevant for the example")
        permissions = []
        while (rset.next()):
            permissions.append(rset.getString("ROLE_ID"))
        stmt.close()
        return permissions

if __name__ == "__main__":
    db = oracle("user", "password", "sid", "host", "1521")
    codes = db.getPermissionCode("ADAM-JNH-CA-FS-0005")
    print codes
Posted on July 31, 2007 in Python, Quality by adam3 Comments »

One tool we used to win the CAST2007 testing competition (before we were disqualified…) was log-watch by James Bach. Log-watch is a perl script which watches a log file for instances of a string, or regex and when it encounters it plays a sound allowing you to actively, yet passively monitor a logfile. It does however have two hits against is. First, it’s in perl <grin> and second it is windows only. 3 hours and a couple false starts later I can now announce pylog-watch.

Pylog-watch is a straight port of the original log-watch script to python and while the audio works only on windows at the moment, there is hooks for audio on linux, freebsd and solaris — I just don’t have access to any of those machines right now so didn’t finish them.

Just as the original does not require you to install perl to run it, I’ve made a standalone windows executable using py2exe (which is remarkably easy to use). You can get the zip from over here.

For the more programmatically inclined, you can grab the script out of svn here or view it below the cut.
(more…)

Posted on July 18, 2007 in Python by adamNo Comments »

I was once told that when learning another (non-programming) language that you cannot say that you are fluent in it until you stop converting what you are hearing / what to say to / from your native tongue. I think the same applies to programming languages; you do not know it until you can use it to solve any problem. Of course, if the only tool you have is a hammer…

A bit of background before we get to code. I have a 14 yr old daughter who at the best of times is negligent of her homework and who is, shall we say, less than street smart. Yesterday she got her nana’s old computer for her room which is a scenario which could compound the two previous problems so we wanted to be able to control when the machine was live onto the internet. I thought about teaching my wife how to log into the router and control the access lists, but that would involve lots of steps she would have to remember so I figured I would have to automate it.

My first crack at it was to use Selenium but it got foiled by the username/password window which basic auth presents. And the old school trick of putting the credentials in the url doesn’t work at all in IE (on purpose) and in Firefox it still pops up the box, just with the values prepopulated. So that wasn’t going to work.

Reaching into the toolbox I pulled out Python. I had tried a number of months ago to this task using python but overengineered it using the httplib module and abandoned it. Sure, I could cart around a session, but for this task it was overkill. Since all I needed to do was POST a specifically constructed request to the router to control whether the filter is on or off it was 10 minutes of coding to whip together something that almost works and the rest of the hour to debug it (I wasn’t setting the authentication realm properly and there was a status code that apparently means something which I wasn’t setting correctly either).

Before using the script there is some setup work on the router that needs to be done. First, you need to create the filter that you want to be controlling. Second, you need to associate the filter to the machine you are trying to blackhole. I did this via the nic’s mac address so I could still have the machine use dhcp. And third, tweak the script to suit your environment. Specifically the router_host and encoded_password variables and the f_name and f_id keys in options. encoded_password is just a base64 representation of the router’s password if anyone (such as Meagan) is snooping for the password to gain access to the router they won’t see it. Note: this doesn’t work in a household of programmers.

import urllib2, sys, base64, urllib

router_host = "192.168.5.1"
security_page = "http://%s/apply.cgi" % router_host
encoded_password = "cnViYXJi"

options = {"submit_button": "Filters",
           "change_action": "",
           "submit_type": "save",
           "action": "Apply",
           "blocked_service": "",
           "filter_web": "",
           "filter_policy": "",
           "f_status": "2", # 0 for disable, 1 or 2 for enable
           "f_id": "3", # filter id
           "f_status1": "enable",
           "f_name": "Meagan", # filter name
           "f_status2": "deny",
           "day_all": "1",
           "time_all": "1",
           "allday": "",
           "blocked_service0": "None",
           "blocked_service1": "None",
           "host0": "",
           "host1": "",
           "host2": "",
           "host3": "",
           "url0": "",
           "url1": "",
           "url2": "",
           "url3": "",
           "url4": "",
           "url5": ""}

if sys.argv[1] == "on":
    options["f_status1"] = "enable"
else:
    options["f_status1"] = "disable"
    options["f_status"] = "0"

auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password("downstairs", router_host, "", base64.decodestring(encoded_password))
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)

try:
    f = urllib2.urlopen(security_page, urllib.urlencode(options))
    if f.read().find("Settings are successful.") == -1:
        print "Settings were not successful"
    else:
        print "Settings were successful"
except urllib2.HTTPError, e:
    print e.msg

In addition to the script, there are 2 batch scripts which are used to actually control this as the behavior is determined by a parameter and I wanted this to work by just clicking a single icon on the desktop. Here is the one for turning off the filter.

c:\python25\python.exe router.py off

One side benefit of this solution is that I could quite easily turn on DDNS and remote management of the router and I would be able to control her access from work if necessary by only having to change a single variable.

Posted on June 20, 2007 in Python, Quality by adamNo Comments »

This was supposed to be a followup to my original post on Making Selenium scripts generic and about how the actual results deviated from the plan. On re-reading it, it looks like I was pretty good at thinking out the problem and coming up with a viable solution.

The only differences between the plan, and the results are

  1. Framework launches the script through the -htmlSuite flag to the selenium server
  2. The login script looks like
    <tr>
    	<td>storeCurrentTestQueryArg</td>
    	<td>userName</td>
    	<td>u</td>
    </tr>
    <tr>
    	<td>type</td>
    	<td>Login.Token1</td>
    	<td>${u}</td>
    </tr>

Of course, the implementation was not so straight forward. Between having to figure out maven and dusting off my javascript skillz it was a good 3 or 4 days of work. The end result however does pretty much what it was supposed to do, and has been submitted as a patch to Selenium-Core (which is required by Selenium-RC).

Posted on May 23, 2007 in Python, Quality by adamNo Comments »

In some qa organizations, the tester’s role is to not only discover bugs, but to track down their cause. In agile teams, testers are often also responsible for static or whitebox tests. In both these scenarios, being able to reverse engineer the product is a useful skill to have. It is also one that not many people have anymore as schools teach computers at a higher and higher level of abstraction these days. In this video, Alex Sotirov, a vulnerability engineer at Determina who found the first publically disclosed remote exploit in Windows Vista discusses how he reverse engineers Microsoft’s monthly patches and shows a demo of the exploit.

  • Metasploit – an exploit framework written in Ruby
  • IDA Pro – another reverse engineering tool
  • BinDiff – a plugin for IDA Pro which does what the name implies; diffs binaries
  • PAIMAI – a scriptable (in Python) debugger
  • Buffer overruns – The use the /GS flag on Microsoft compilers can greatly reduce your exposure to these kinds of errors by inserting code to check for overruns and hijacking of the return address (see for more information). However, the compiler uses a heuristic when putting in the cookies and remember that heuristics are by definition failable. In this case the original heuristic was if there was an array, then cookie is. The ANI bug however dealth with a fixed length structure. The heuristic has since been updated to include this scenario
  • ASLR (Address Space Layout Redundency) – Putting the same stuff in the same spot in memory every time is a baaaaaaad idea
  • Heap Spraying is responsible for most of the browser exploits in the last while, and is fighteningly reliable an attack vector
  • DEP (Data Execution Protection) – mark certain pages of memory as read-only. Of course, IE (even in Vista) does not run in DEP enabled mode by default
  • Even with IE running in ‘protected’ mode, things are not so good. Protected mode prevents the attacker from modifying the system’s files, but it can still read them. It can also install things into running proccesses (like a key logger into IE)
  • Even if you have ASLR and DEP implemented, you can still shoot yourself in the root. Windows has 8 bits of entroby for the ASLR algorithm, so it only takes 256 guesses to find the thing in memory you want to stomp on, and in the case of the ANI bug, there was exception handling in place which made it easier.
  • Always check the rest of your code for similar problem patterns. The ANI bug was fixed in 1 place, but was still an issue in 2 others with the exact same signature
  • “C++ is wrong in almost all but a limited set of circumstances” – instead use a higher level language and encapulate the performance critical parts in a small library that is called from that higher language
  • At the end there is a chart which shows which of the protection methods he described are implemented in which OS. Vista, Linux and OpenBSD are all green. Amazingly, Mac OS X is all red. Well, DEP is green, but only on Intel chips.

Direct link here

Posted on May 4, 2007 in Python, Quality by adamNo Comments »

I think that a test script framework should be entirely self contained (or at worst, as self contained as possible). In the case of Selenium RC scripts, this means that the server should be startable automatically if it is not present. Similarily, if you did start the server, it should be shut down. Heres the code which does just that.

But before I show the code, a note about the directory structure to allow things to make more sense.

  • Everything in my framework is relative to whatever directory is indicated by test_root
  • There are a bunch of unlisted dirs in the jre, but consider that dir the top level of it
  • Dirs in platform are what is returned by sys.platform, and hold any platform specific modules / libraries
test_root
|- some other stuff
|- platform
|  `- win32
|    `- jre1.5.0_11
|- server
|  ` selenium-server.jar
`- even more stuff

Starting

import socket, os
# check that the server is running
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    s.connect(("localhost", 4444))
    started = "FALSE"
except socket.error:
    s_path = os.path.join(test_root, "platform", sys.platform, "jre1.5.0_11", "bin", "java.exe")
    s_args = '-jar "%s%sserver%sselenium-server.jar"' % (test_root, os.sep, os.sep)
    if sys.platform == "win32":
        s_pid = os.system('start "Selenium RC Server" "%s" %s' % (s_path, s_args))
    else:
        print "Ummm, don't have to do any other platforms right now"
    started = "TRUE"

Stopping

# kill the selenium server if we were the one who started it
if started == "TRUE":
    if sys.platform == "win32":
        import wmi
        c = wmi.WMI()
        for p in c.Win32_Process(Description="java.exe"):
            if p.ExecutablePath == s_path:
                p.Terminate()
    else:
        print "Read the message above, we only do windows right now"
Posted on April 30, 2007 in Python, Quality by adamNo Comments »

These days I spend too much of my time recertifying bugs than actual value generating testing or hacking stuff up in python. Last week however I had a brief reprieve from that to produce a data generator for a new feature. This particular feature is about adding a new layer of authentication to the product; not only do you have to provide the correct credentials, but you have to be coming from a known IP Address. The ‘expected’ maximum ip list size is thought to be around 150, so I tested with 255 (a full /24 address block) which I used Excel to generate. (Note to testers, learn to love the ‘fill handle’ in Excel). There was however some concern about the implementation and data independence so in order to trigger multiple lists being inserted at the same time wanted a big list.

A really big list.

Unfortunately, the fill handle does not know the semantics of an ip address so it will merrily generate 10.10.10.256, 10.10.10.257, etc. Two and a half hours later, I whipped together this little bit of python which will generate as many lists as you want, up to the max allowable ip address (255.255.255.255).
(more…)

« Previous Page