## 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
else:
sumall = 0
for i in range(0,len(cl)):
d = cl[i]
if ( ( i % 2) == 0 ):
sumall = sumall + int(d)
else:
tba = str(2 * int(d))
if ( len(tba)== 2 ):
sumall = sumall + int(tba)
sumall = sumall + int(tba)
else:
sumall = sumall + int(tba)
if ( (sumall % 10) == 0 ):
return cl + '0'
else:
luhndigit = 10 - (sumall % 10)
return cl + str(luhndigit)

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

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

Hope it helps someone

./Z