Skip to content

Security Measures

p4nd4ta edited this page Feb 5, 2021 · 3 revisions

Delete your Public key if you think your pair got compromised

/Keys/Index Del Pub Key You can delete your public key from the database and regenerate a new one, it will be updated on all clients, when you rejoin the chat room. For maximum security and privacy, you can delete every message that was encrypted with that key pair. Take a look bellow, how it is done.

Delete your messages from the Database

Delete messages You can delete every message stored in the database, which was encrypted with you public key.

Disconnection Warnings

Every time a user connects to SignalR, the authorization process is based on the session cookie, kept in the browser, generated by ASP .NET Identity. Then client/server do negotiations for the communication protocol to use, (WSS, AJAX, etc...). And the connection gets established. If you loose connection for a brief second with the server, the connection gets dropped and the user gets a message from the client JS. The reconnection is simply done by refreshing the web page. Disconnected

XSS Attack Prevention

We have filtered every output from the Internet, through an HTML character escape regex-based function in the js.

function escapeHtml(unsafe) {//RegEx Check the string and returns a replaced one, with HTML Safe Characters (XSS Prevention)
    return unsafe
        .replace(/&/g, "&")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

Server-side .NET's Razor View Engine escapes any unencrypted elements by default, but since messages are decrypted on the client, we make sure that every decrypted output is filtered to prevent possible XSS attacks. So the escapeHtml() method is called both in real-time communications and database fetched messages.

MITM Attacks Prevention

All messages are encrypted client-side before they are send to the network. If somebody intercepts a message it cannot be decrypted without the appropriate private key. Also the message is digitally signed, so the contents of it cannot be forged.

More on our digital signature system

In RSA, the standard says that you need to sign the hash of the plain text message. But because of the nature of our communication scenario, the messages tend to be short and repeated/send many times in a regular chat. Also the Signature is meant to be decrypted with the public key. Which means anyone can extract the hash inside it. The purpose of signatures is to make sure the message is not tampered with/forged. So if someone know the hashed value of the message "Hello", for example, in plain text, he can load all these common message hashes from a rainbow table and crack all the hashes which he extracted using the public keys. Effectively allowing an attacker to eavesdrop the communications, without the user and system noticing. To mitigate that, our system uses SHA-256 hash function on the Base64 of the encrypted message. RSA always generates unique cipher for the same plain text value, Base64 guarantees 1:1 representation of the ciphertext, so the Base64 will always be unique. SHA-256 hash is long enough to prevent hash collisions, so the hash of the Ciphertext of the Base64 will ALWAYS be a unique value. Thus eliminating the use of hash salting, like in password secure storage. Also if a message is forged, the attacker must know the private key to sign it again. We assume that it is not possible, but if the Private Key is known, the hash cannot be reproduced even then, nor by the user.

Signature Mismatch Alert In Real-Time Message

Signature Mismatch Alert In Real-Time Message

Signature Mismatch Alert In Data Base Fetched Message

enter image description here

Message Payload Validations

A VALID message payload

The message, received by the server is a JSON array, which gets deserialized server-side and contains objects of MessageReceive class:

MessageReceive_Class_UML

Validation process

The .NET String.IsNullOrWhiteSpace(String) Method is called on every field to verify the payload, if the verification is not passed, and Exception is thrown - The message payload is invalid. Which gets logged as you can see on the picture bellow. Also the Client is notified. The messages are not sent and not saved to the Database. In normal circumstances this validation is done client-side and Exception rarely triggered on the server. Which can be an alert for MITM attacks. Invalid Payload Exception If the method returns true, the next round of Validations is done, which checks the message and signature length, if the lengths are larger that the constants in ChatHub.cs . An exception is thrown: The message payload is too big.Which gets logged on the Server as you can see on the second picture bellow. Also the Client is notified. The messages are not sent and not saved to the Database. In normal circumstances this validation is done client-side and Exception rarely triggered on the server. Which can be an alert for MITM attacks.

Client-side message length validation before send: Client-side message length validation before send Server-Side Message Length Validation, if JS gets Bypassed: Server-Side Message Length Validation, if JS gets Bypassed

About the Constants Mentioned

By default we are using 2048 bit RSA keys. I have hardcoded the JSEncrypt generator on 2048 bits. To generate a longer key, use OpenSSL. Though, there is a hardcoded constant in the backend and the frontend script, which checks the length of the message, because a 2048 bit key can encrypt only 245 chars with its modulus. So you need to change that if you are going to use longer RSA keys:

Backend: ChatHub.cs on Lines 21 and 22
const int MESSAGE_PAYLOAD_LEN = 345; //With RSA 2048 bit key, the max base64 string is of length exactly 345(+ "%" sign for whisper traffic)
const int SIGNED_MESSAGE_PAYLOAD_LEN = 344; //With RSA 2048 bit key, the max base64 string of the SHA-256 hash is exactly 344 chars long
Frontend: chat.js on Line 6
const  MESSAGE_LENGTH  =  245;  // the max RSA encryption length for 2048 bit key Modulus, if the message is longer, the library would fail

If the Payload is in the valid Length the next validation round takes place, it validates the sender and receiver User ID's. if they are Invalid an Exception is thrown: The message recipient or sender are invalid. Which gets logged as you can see on the picture bellow. Also the Client is notified. The messages are not sent and not saved to the Database. In normal circumstances this validation is done client-side and Exception rarely triggered on the server. Which can be an alert for MITM attacks.

Server-Side Exception if the JS gets Bypassed: Server-Side Exception if the JS gets Bypassed If all validation pass, the message is send to clients and transaction committed to the Database.

Message Database Encryption

As you can see, there are only encrypted messages stored in the database, because there is nothing unencrypted traveling among clients.

Message Database Encryption

Clone this wiki locally