Javascript, Python and PHP: Simple security and encryption measures

1. Introduction:

The year 2011 emphasized once more the importance of data security even for systems that would previously have been dismissed as too low-profile to warrant decent security measures by site-administrators. This post will demonstrate how quickly the bar in web-security can be raised, for low to medium key applications.

One security risk is posed by Cookies. These are essentially text-files serving as a semicolon ';' separated key-value store, along with an expiration date and domain of validity. Yet cookies get physically lost along with the loss of ubiquitous mobile devices such as a USB keys with a portable browser, external harddisks, laptops and mobile phones. More commonly cookies are stolen via Browser attacks, cross-scripting domain attacks and other  man in the middle attacks.

Most web sites use cookies as the only identifiers for user sessions, because other methods of identifying web users have limitations and vulnerabilities. If a web site uses cookies as session identifiers, attackers can impersonate users’ requests by stealing a full set of victims’ cookies. From the web server's point of view, a request from an attacker has the same authentication as the victim’s requests; thus the request is performed on behalf of the victim’s session. Source: Wikipedia

If the Cookie contains user account data, this data is directly recoverable from the Cookie, and the concerned account can be easily accessed. Users generally tend to reuse passwords, which in connection to search engines allow backtracking and accessing the user's account on various web-sites, and quickly gather a comprehensive picture of the user. This can become a prior key-step setting in motion more nefarious identity theft schemes.

The issue of security is mended through the use of Session-Id's to some extend. These are user-identifiers, passed in the url each time the user's web Browser request a web-resource, and the Id's half a short half-life in the order of typically minutes after which the session-Id becomes invalid. Session-Id's can increase the amount of data transmitted between the Client and a Server in comparison to Cookies. This may negatively impact rapid application development (RAD).  Notwithstanding the issue of web-security through the use of  Cookies or Session-Id's, neither solution fundamentally answers how to handle the transmission of sensitive user data in the first place.

2. Security Measures:

The following security measures should be heeded when sensitive user data is concerned, even for mere test-websites:
  1. Encrypted database: Securing the data of a database can be easily facilitated through the use of a seamlessly encrypted file-system or options which the DataBase Management System (DBMS) offers. Database encryption algorithms may perform slower than transparent secure file-systems.
  2. Secure Computer accounts: Administrators should never leave password-free accounts and guest accounts remaining on productive systems. Another no-go: root accounts with 'standard' passwords
  3. No raw passwords: Password must not be stored in its text-format, includes encodings such as base64. The latter encoding with an alphabet of 64 characters, generally ensures character compatibility with the limited symbol table assigned to URI's.
    NOTE: Base64 encoding converts every 3 bytes into 4 bytes. During decoding these 32bits (4 bytes) are converted back to 3 bytes. If less than 3 bytes were remaining in the input, the output will be padded with '=' to a total end-chunk of 4 bytes. Base64 decoders should throw an exception if the input string is not a multiple of 4 bytes, meaning that the length of any base64 decodable string must be divisible by 4. Thus the length of a string and last characters can often hint at base64 encoding!
  4. No raw data: Only Hashes of passwords obtained via strong-hashfunctions should be stored in a Cookie or SessionId. The user-hash is then compared to a target-hash in the database. The database may only store the user-password's hash directly and doesn't retrieve the actual password in order to performs the hashing in the script. Computing the hash in the database is more secure, but still a slight security risk, incuring unnecessary computations.

    The hash is then retrieved and compared against the hash sent from the client, which is transmitted by HTTP-Headers, for instance due to a Cookie or a Session-URI.

    Computing or updating the current hash to another hashing algorithm, can be directly performed in SQL (See MySQL's DES_ENCRYPT / DES_DECRYPT):
  5. Another strong hash with an dissimilar hashing algorithm is generated from the naked-password as in 3) and stored analogously in the Database as hash_B. Instead of the naked-password this second hash is to be used, as a bona-fide password. In this scenario the actual user-password will only be used (e.g. transmitted and loaded in the working memory of the server) in special cases.
    The bona fide password never leaves the domain of the server. Indeed,  in this scenario the database acts as a trusted-third party or middle-man endorsed with establishing the authenticity of the user hash. If valid,  the hash-password is transmitted to the server-side-script or any server process, which encrypts (HTTP-GET) or decrypts (HTTP-POST) client side-data stored in Session's or Cookies
    Note: I generally serialize the entire set of hand-picked, user variables, which is important to be stored on the client, and the rest of user-state variables, such as given states of the user-interface view, which is to be restored upon revisit, is stored an serialized in a database. Whilst there are caveats against this practice, doing so simplifies programming logic, and is often more secure owing to well-developed Serializer interfaces in the major server-scripting languages, rendering these interfaces likely less prone to code injection than own implementations.

Recommended read: Hash functions: Theory, attacks, and applications 

3. Modulo Encryption:

Following is one of the simplest encoding functions:
To each character of the data to be encrypted, the character of a key is added. To reverse the process, to each character of the encrypted data the character of the key is subtracted:

In this example the decimal presentation of one user-data byte of the user-data-sequence (8bit) is 200. The corresponding character outside of the printable ASCII symbols.
Encryption:
>>> (200 + 300) % 256
244
Decryption
>>> (244 - 300) % 256
200

decrypted data
encrypted data
key-hash-data

3.1 Python Implementation: The following example implements the code-logic in Python:


However the usage of Python's v3 base64 encoder, and handling of binary data changed significantly.
Some help came from here:

http://docs.python.org/release/3.0.1/whatsnew/3.0.html
Perhaps this library may help: ....it did not.

Some further research provided me with the answer. Courtesy of the site: diveintopython3.org

And here is the link between strings and bytes: bytes objects have a decode() method that takes a character encoding and returns a string, and strings have an encode() method that takes a character encoding and returns a bytes object. In the previous example, the decoding was relatively straightforward — converting a sequence of bytes in the ASCII encoding into a string of characters. But the same process works with any encoding that supports the characters of the string — even legacy (non-Unicode) encodings.

#Voila,  it works:




3.2 Javascript implementation: To do the same in javascript just write:







t = "testme"
"testme"
k = "keyme"
"keyme"
for(i=0, data=''; i<t.length; i++){ data += String.fromCharCode( (t[i].charCodeAt() + k[i%k.length].charCodeAt()) % 256)}
"ßÊìáÒÐ"
t="testme|testme"
"testme|testme"
for(i=0, data=''; i<t.length; i++){ data += String.fromCharCode( (t[i].charCodeAt() + k[i%k.length].charCodeAt()) % 256)}
"ßÊìáÒÐáíÒØßÒÞ"


Fig 1. Shown on the right is Chrome's web inspector (js), on the left Pyedit (python). The encrypted data matches.

and finally to base64 encode


btoa(data)
"38rs4dLQ4e3S2N/S3g=="


and to base64 decode:

atob("38rs4dLQ4e3S2N/S3g==")
"ßÊìáÒÐáíÒØßÒÞ"
//here is what happens when "..".length %4 != 0

atob("38rs4dLQ4e3S2N/S3g==" + '!')


DOMException




PS: Any reversible bit-operation that is fast, suffices for encoding and decoding. I will show in the future  how to efficiently hack the presented algorithm.

LihatTutupKomentar