When the plugin requests the browser to retrieve a resource, it can use fonctions with the 'Notify' suffix, which will instruct the browser to call the plugin-side callback function NPN_URLNotify after a stream is retrieved (either successfully or not).
When using this request method, an optional 'notify data' parameter can be passed to the NPN_GetURLNotify and NPN_PostURLNotify functions, which will be passed unchanged as an parameter to the NPN_URLNotify function. Since the request-retrieval-response process is asynchronous, this allowes the plugin to pass to itself data that is relevant to the requested resource, and helps to differentiate it from other responses.
The StreamInfo base class is a prototype for this 'notify data' used by Saphe. It has two inheritors:
- StreamInfoIP is used when requesting the user's real IP address
- StreamInfoSapheEncryptedPart is used when requesting the Saphe data from the server, and contains the user name, password and client challenge, which will allow the callback function to derive the key and login (if the server is authenticated)
Saphe data manipulation
The main functionality in the SapheData code includes the creation, encryption, decryption and parsing of the SapheData that is returned by the real server to the plugin.
This is the SapheData format:
--- Start of header ---
- magic value [4 bytes] // the 4-char string 'SAPH'
- status code [1 bytes] // can be 'X' (SapheData), 'Y' (invalid user) or 'Z' (blocked user)
--- Start of SapheData part ---
- encrypted buffer size [4 bytes, little endian]
- server challenge [16 bytes]
- initialization vector (IV) [16 bytes]
- plain hmac [20 bytes]
- Encrypted buffer:
- source ip [4 bytes, little endian]
- requested url size [2 bytes, little endian]
- requested url [requested url size]
- authentication url size [2 bytes, little endian]
- authentication url [authentication url size]
- phishing report url size [2 bytes, little endian] // optional - size can be 0
- phishing report url [phishing report url size]
There are two functions for the server side code:
- CalculateEncryptedPartSize - calculates the size (in bytes) of the buffer required to contain the SapheData part (not including the 5-byte header). There is a basic constant size, which is added to the combined lengthes of the three given URLs. This function should be called in order to allocate an output buffer for CreateEncryptedPart
- CreateEncryptedPart - creates the actual SapheData part. The process is as follows:
- Derive the AES encryption key using the password, client challenge and server challenge
- Copy the server challenge and IV to their places in the output buffer
- Create the encrypted part of the SapheData and write its size at the beginning of the output buffer
- Calculate the HMAC of the encrypted part (which is still plain at this stage) using the same AES encryption key and write it to the output buffer
- Encrypt the encrypted part and copy it to the output buffer
The client side code (the plugin) uses the following function:
- DecryptEncryptedPart - does the reverse of CreateEncryptedPart, while checking for errors at each step (either format errors or logical errors):
- Derive the AES encryption key
- Decrypt the encrypted part of the SapheData
- Calculate the HMAC of the decrypted part using the AES key and compare it to the HMAC in the SapheData buffer
- Recover the client IP and the three URLs from the decrypted data
Note that the comparison between the requested URL and the respective URL returned by the server (which is done by the plugin) is case insensitive.
- IsSecureURL - checks if the given URL starts with 'HTTPS://' (not case sensitive). This function is used to verify that the URL in the first <embed> instruction and the login URL included in the Saphe data are secure - that is, based on an SSL connection. See the solution details to refresh your memory.
- ExtractIPAddress - extracts the user's IP address from the given HTML content which was returned in a response to the request made by the plugin. The data is extracted according to the format of the specific server from which the information was requested. The following URLs were found after a brief search, and may be used (notice that they are all secure):