Credit card security
Results 1 to 7 of 7

Thread: Credit card security

  1. #1
    Senior Member
    Join Date
    Apr 2002
    Posts
    324

    Credit card security

    Brazil 2 - England 1

    Oh well. I'll try cheering myself up with a tutorial...

    Outline

    In this tutorial I am going to cover two types of credit card validation. The first type of validation is a LUHN check. The second validation method that I cover examines the use of a cards.ini text file for credit card type validation.

    LUHN checking

    Most credit card numbers (including Visa and Mastercard) conform to the LUHN checksum algorithm. You can calculate the last digit of a card number, by examining all the preceeding digits. You cannot tell from this if the card is stolen, but it can be used to check if the user has made a mistake when entering a card number.

    In this article I am publishing both my ASP and PHP LUHN checking functions.

    Card Type validation

    The second type of validation is checking that the selected card type is correct. Each card type - Visa, mastercard etc - has a given length and prefix. For exampe Visa cards have a prefix of 4 and a length of either 13 or 16 characters. Because of this you can validate that the card type that has been selected by the user is accurate.

    This part of the code is only provided in ASP - Sorry

    A explaination of the LUHN algorithm

    The following steps are involved in this calculation:

    Step 1: Double the value of alternate digits beginning with the first
    right-hand digit (low order).

    Step 2: Add the individual digits comprising the products obtained in
    step 1 to each of the unaffected digits in the original number.

    Step 3: Subtract the total obtained in step 2 from the next higher
    number ending in 0 [this in the equivalent of calculating the
    "tens complement" of the low order digit (unit digit) of the total].
    If the total obtained in step 2 is a number ending in zero
    (30, 40 etc.), the check digit is 0.

    Example:

    Account number without check digit: 4992 73 9871

    4 9 9 2 7 3 9 8 7 1
    x2 x2 x2 x2 x2
    ----------------------------
    18 4 6 16 2

    4 + 1 + 8 + 9 + 4 + 7 + 6 + 9 + 1 + 6 + 7 + 2 = 64

    70 - 64 = 6

    Account number with check digit 4992 73 9871 6

    From: http://staff.semel.fi/~kribe/document/luhn.htm
    LUHN Check - ASP version

    Example Usage

    CardIsValid = true
    if card.luhncheck(p_CardNo) = true then
    debug "luhn ok"
    else
    debug "luhn failed"
    CardIsValid = false
    end if
    The ASP Code!

    Code:
    'ASP ISO 7812:1987(E) LUHN Checker
    	'This function was written by Simon Barnett. (si@ntsa.org.uk)
    	'Use and distribution of this software is covered
    	'by open source licence (http://www.opensource.org/osd.html).
    	'Please include these comments in any distribution.  
    
    Function LuhnCheck(p_cardno)
    
       session("debug") = "false"
       
       if isnumber(p_cardno) = false then
       	luhncheck = false
       else
       	if len(p_cardno) = 0 then
       		luhncheck = false
       	else
       		
       		tot = 0
       		chk = right(p_cardno,1)
       		p_cardno = left(p_cardno,len(p_cardno)-1)
       
       		for n = len(p_cardno) to 1 step - 2
       			x = cint(mid(p_cardno,n,1))  * 2
       			if len(x) > 1 then
       				tot = tot + cint(mid(x,1,1))
       				'debug mid(x,1,1)
       				tot = tot + cint(mid(x,2,1))
       				'debug mid(x,2,1)
       			else
       				tot = tot + cint(mid(x,1,1))
       				'debug mid(x,1,1)
       			end if		
       		next
       
       		for n = len(p_cardno)-1 to 1 step - 2
       			tot = tot + cint(mid(p_cardno,n,1))
       			'debug mid(p_cardno,n,1)
       		next
       
       		'debug tot
       
       		checkdigit = cint(cstr(cint(left(cstr(tot),1))+1) & "0") - tot
       
       		debug "Checkdigit should be "&checkdigit
       		debug "Actual Check Digit "&chk
       
       		if int(chk) = int(checkdigit) then
       			luhncheck = true
       		else
       			luhncheck = false
       		end if
       
       	end if
       end if
    
    End Function
    LUHN Check - PHP version

    Example Usage

    // <EXAMPLE USAGE>

    if(ValidCard($credit_card)) // Pass credit card details without spaces.
    {
    echo "Valid Card";
    }
    else
    {
    echo "Invalid Card";
    }
    The PHP Code!

    Code:
    <?php
    
    function ValidCard($credit_card) 
    /*	PHP ISO 7812:1987(E) LUHN Checker
    	This function was written by Simon Barnett. (si@ntsa.org.uk)
    	Use and distribution of this software is covered
    	by open source licence (http://www.opensource.org/osd.html).
    	Please include these comments in any distribution.  
    */
    
    { 
    	$checksum = substr ($credit_card, -1);    // returns checksum
    	$restnum = substr($credit_card, 0, strlen($credit_card)-1); 
                    // returns rest of credit card number
    
    	$calcvals = "";
    
    	for ($i = strlen($restnum)+1; $i >= 0; $i=$i-2) {	
    		$calcvals = $calcvals . strval(intval(substr($restnum,$i,1))*2);
    	}
    
    	for ($i = strlen($restnum) -2; $i >= 0; $i=$i-2) {	
    		$calcvals = $calcvals . strval(intval(substr($restnum,$i,1))*1);
    	} 
    
    	$calcvals = substr($calcvals,1);
    	$count = 0;
    
    	for ($i = 0; $i <= strlen($calcvals); $i++) {
    		$count = $count + intval(substr($calcvals,$i,1));
    	}
    
    	if(intval(substr(strval((10*(intval(substr(strval($count),0,1))+1)-$count)),-1))==$checksum)
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    } 
    
    ?>
    Checking the type of card (ASP)

    I didn't want to hard code the card type information for obvious reasons, not least amongst which is the fact that I'm using code similar to this over a large number of sites, each with their own list of accepted cards. So I stored all the information about the fornat of each of the different credit card companies in an ini file. This ini file is shown below.

    The cards.ini file

    [Visa]
    prefix=4
    length=13,16

    [Mastercard]
    prefix=51,52,53,54,55
    length=16

    [American Express]
    prefix=34,37
    length=15

    [Dinners Club]
    prefix=300,301,302,303,304,305,36,38
    length=14

    [JCB]
    prefix=3
    length=16

    [Discover]
    prefix=6011
    length=16
    Displaying the list of accepted cards

    The CardList routine below reads the cards.ini file given above and displays each of the credit card types in a drop down combo box. The returned 'CardType' variable is used validating the card type in the FormatCheck Function.

    Code:
    Sub CardList()
    
       cards = split(getcards(),",")
       
       response.write " <select name='CardType' size='1'>"
       response.write "     <option selected value=''>&lt;-Please Select-&gt;</option>"
       
       n = 0
       on error resume next
       while err.number = 0 
       	response.write "     <option value='"& cards (n) &"'>"& cards (n) &"</option>"
       	n = n + 1
       wend
       
       response.write "   </select>"
    
    End Sub
    
    Function GetCards()
    
       Dim fso, MyFile
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set MyFile = fso.OpenTextFile(replace(request("inipath"),"*","\"), ForReading)
       
       getcards = ""
       while not myfile.atendofstream
       	l = MyFile.ReadLine
       	if left(l,1) = "[" then
       		if getcards = "" then
       			getcards = mid(l,2,len(l)-2)
       		else
       			getcards = getcards & ","  & mid(l,2,len(l)-2)
       		end if
       	end if
       wend
    
    End Function
    Validating the selected card type

    Example Usage

    CardIsValid = true
    if card.formatcheck(p_CardNo,p_CardType) = true then
    debug "Format ok"
    else
    debug "Format failed"
    CardIsValid = false
    end if
    The Code!

    Code:
    Function FormatCheck(p_CardNo, p_CardType)
    
       Dim fso, MyFile
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set MyFile = fso.OpenTextFile(replace(request("inipath"),"*","\"), ForReading)
       
       f=0
       debug "Opening Cards.ini file..."
       while not myfile.atendofstream
       	l = MyFile.ReadLine
       	if left(l,1) = "[" then
       		if mid(l,2,len(l)-2) = p_cardtype then
       			f = 1
       			debug "found " & mid(l,2,len(l)-2)
       			prefix = split(trim(replace(MyFile.ReadLine,"prefix=","")),",")
       			length = split(trim(replace(MyFile.ReadLine,"length=","")),",")
       		end if
       	end if
       wend
       
       myfile.close
       
       if f = 0 then 
       	formatcheck = false
       else
       	prefixok = false
       	n = 0
       	on error resume next
       	while err.number = 0
       		debug "Check Prefix:" & prefix(n)
       		if left(p_cardno,len(prefix(n))) = prefix(n) then
       			debug left(p_cardno,len(prefix(n))) &"="& prefix(n)
       			if err.number = 0 then
       				prefixok = true
       			end if
       		end if
       		n = n +1
       	wend
       
       	lengthok = false
       	n = 0
       	on error resume next
       	while err.number = 0
       		debug "check len: " &  int(length(n))-1
       		
       		if len(p_cardno) = int(length(n))-1 then
       			if err.number = 0 then
       				debug len(p_cardno) &"="& int(length(n))-1
       				lengthok = true
       			end if
       		end if
       		n = n +1
       	wend
       
       	if lengthok = true and prefixok = true then
       		formatcheck = true
       	else
       		formatcheck = false
       	end if
       
       end if
    
    End Function
    If you liked this tutorial check out these others by ntsa :
    Dumping SQL data to a text file
    Hunting down skript kiddies
    Search Engine submission 'exploit'
    Forced shutdown of a remote nt/2k server
    Securing an installation of IIS 4. (No, seriously)
    Remote DSN Connections, using WinAPIs and the registry
    Scripting Internet Connections Under Window$
    \"I may not agree with what you say, but I will defend to the death your right to say it.\"
    Sir Winston Churchill.
    Share on Google+

  2. #2
    Senior Member
    Join Date
    Apr 2002
    Posts
    324

    Download the code!

    This is the article and code zipped for your ofline pleasure. The zip contains.
    1...Credit card security.htm (The above doc)
    2...CreditCardCls.inc (the ASP class the above routines are from)
    3...cc.php (the PHP LUHN checking algorithm)
    4...cards.ini (the ini file for card types show in the article above)
    \"I may not agree with what you say, but I will defend to the death your right to say it.\"
    Sir Winston Churchill.
    Share on Google+

  3. #3
    Banned
    Join Date
    Nov 2001
    Posts
    188
    you have too many good tutorials. i would give you greenies but it wont let me.

    so i am guessing that if you use this alogorthm to generate a number it could possibly be a valid number.

    Thats pretty nuts seeing that someone actually cracked credit card numbers
    Share on Google+

  4. #4
    Senior Member
    Join Date
    Apr 2002
    Posts
    324
    Yep - you could write this the other way to generate a list of valid credit card numbers, so these checks described here can't be the /only/ checks you make. But they're useful routines none the less for form validation. For example I reccomend that my customers check the name / postcode / address against the electoral register (which is availible on CD) and then PDQ the card itself prior to despatching any goods.

    Just to speculate... if you were to write it the other way you would be better to list all of the valid numbers starting from the number of a real credit card. Such a piece of code would look like this:

    Code:
    range =1
    for x = 1 to cardlen -1
       range = range * 10
    next
    
    for n = realcardnum to realcardnum + range
       if LuhnCheck(p_cardno) = true then
          echo n
       end if
    next n
    That way you'd be much more likley to hit number that won't be rejected as an invalid card.

    As I say...just speculation .
    \"I may not agree with what you say, but I will defend to the death your right to say it.\"
    Sir Winston Churchill.
    Share on Google+

  5. #5
    Senior Member
    Join Date
    Nov 2001
    Posts
    1,255
    Nice tut NTSA. You write very nice code.

    It should be noted that generating credit card numbers will not let you buy things anywhere, and that this algorithm is publicly available. As anyone with a CC # knows, you must know the expiration date of the card in order to purchase something, this is an often overlooked detail when people say "a cracker broke into our database and stole all the credit card numbers". It's not just the numbers, it's the Expiry date, and the owner, etc..

    Most CC validation services nowadays also require you to enter your phone number and address. For instance, I ordered some BOFH stuff from the Register a few weeks ago, and it required not only my credit card number and expiry date, but also my Address and phone number.
    Chris Shepherd
    The Nelson-Shepherd cutoff: The point at which you realise someone is an idiot while trying to help them.
    \"Well as far as the spelling, I speak fluently both your native languages. Do you even can try spell mine ?\" -- Failed Insult
    Is your whole family retarded, or did they just catch it from you?
    Share on Google+

  6. #6
    Senior Member
    Join Date
    Apr 2002
    Posts
    324
    I don't believe it! Someone gave me reds for this!
    germany won,**** pom!!!!!!!!!!!! - contact user about this assignment
    Well, thank you for the inciteful and literate comments - NOT.

    I will not lower myself to your level by responding with any similar racial or cultural slur, because such is not in my nature, but I would go so far as to say that you, sir, are an arse.
    \"I may not agree with what you say, but I will defend to the death your right to say it.\"
    Sir Winston Churchill.
    Share on Google+

  7. #7
    Senior Member
    Join Date
    Apr 2002
    Posts
    324
    Originally posted here by chsh
    Nice tut NTSA. You write very nice code.
    Thanks
    \"I may not agree with what you say, but I will defend to the death your right to say it.\"
    Sir Winston Churchill.
    Share on Google+

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

 Security News

     Patches

       Security Trends

         How-To

           Buying Guides