Tuesday 20 September 2011

LUHN-10 Error Detection

Hello All,

There comes a time in a pentest that passing a simple argument to an form field just won't reach its intended sink but will be rejected by a filter of some sort along the way. This is usually the case in loosely structured data such as credit card, imei numbers etc where the luhn-10 error detection algorithm is used to discard invalid data from ever reaching the back-end. This is performed with business logic validation against accidental errors as an incentive rather than security in mind.

For an explanation of the Luhn algorithm see http://en.wikipedia.org/wiki/Luhn_algorithm plus sample implementations for a couple of different languages. It also has a python oneliner for checking the validity of a given input against Luhn algorithm, however I hate onliners.

So i devised a couple of really basic python methods that can be used to either calculate the luhn check digit or check the validity of a given string.

[sourcecode lang="python"]
def calc_luhn( cl ):
if ( cl.isdigit() is False):
print 'Invalid input (not all digits)'
return null
sumall = 0
for i in range(0,len(cl)):
d = cl[i]
if ( ( i % 2) == 0 ):
sumall = sumall + int(d)
tba = str(2 * int(d))
if ( len(tba)== 2 ):
sumall = sumall + int(tba[0])
sumall = sumall + int(tba[1])
sumall = sumall + int(tba)
if ( (sumall % 10) == 0 ):
return cl + '0'
luhndigit = 10 - (sumall % 10)
return cl + str(luhndigit)

def check_luhn( cl ):
if (cl!=calc_luhn(cl[:-1])):
return False
return True

The two functions can be used as below:
>>> # Calculate the luhn digit
>>> l = calc_luhn('35478101234567')
>>> print l
>>> # Check for luhn algorithm compliance
>>> c = check_luhn('354781012345671')
>>> print c
>>> c = check_luhn('354781012345672')
>>> print c

Hope it helps someone


No comments:

Post a Comment

Note: only a member of this blog may post a comment.