Author

Topic: Security Standards For Payment Processing? (Read 227 times)

member
Activity: 322
Merit: 20
Donating 10% to charity
January 23, 2019, 12:01:14 PM
#4
On the subject of withdrawals. Don't allow instant withdrawal. Schedule it for once per day.

In addition, do auditing of withdrawals. So, if you have an exchange, for example, is the withdrawing user withdrawing more than they should be able to going by the sum of their deposit amount and total p/l? If so, block it.

edit: Altcoins are always being updated by their creators; be vigilant about updating for hardforks, or you will end up with users depositing and trading deprecated coins.

And, of course, never store private keys on a server connected to the internet.

This is in fact really important considering security above anything else.

But now we need to ask ourselves, security and a good degree of anonymity? Or security without the last one? Because being able to check who each person is ends up being really important from a security point of view but could be too much hassle if security is not so important so depends here.

Also it's worth nothing that people buys IDs and Passport pictures online, i personally saw and they are not even paying that much and some people is more than willing to give those away carelessly creating another security issue, which makes me doubt about how effective this way of identification is. It's just another idea anyways with pros and cons.
full member
Activity: 351
Merit: 134
January 23, 2019, 03:43:26 AM
#3
On the subject of withdrawals. Don't allow instant withdrawal. Schedule it for once per day.

In addition, do auditing of withdrawals. So, if you have an exchange, for example, is the withdrawing user withdrawing more than they should be able to going by the sum of their deposit amount and total p/l? If so, block it.

edit: Altcoins are always being updated by their creators; be vigilant about updating for hardforks, or you will end up with users depositing and trading deprecated coins.

And, of course, never store private keys on a server connected to the internet.
member
Activity: 111
Merit: 15
Eat, sleep, code, repeat.
January 22, 2019, 10:29:14 PM
#2
It's worth mentioning that tracking addresses is a lot harder than one might suspect.

Let's go with these assumptions:
* Deposit addresses are UNIQUE (generated by server)
* Withdrawal addresses are NOT UNIQUE (generated by untrusted parties)

What's the rational for not forcing non-uniqueness on the withdrawal addresses?
* If all withdrawal addresses are forced to be unique, I could submit any withdrawal address and if it bounces, I know it's in the database. => Leaks database information.

Okay so we don't force uniqueness. What are the pitfalls?
* Tracking addresses becomes complex, our database now has to allow for multiple records of the same withdraw address. We build a primary key { user, withdraw_address } for each record.
=> deduct the balance before the withdrawal goes into the queue, and make sure that it targets the right user.

What if an attacker attempts to use a deposit address as a withdrawal address?
* This is a more interesting scenario, especially if you combine both deposit and withdrawal addresses in the same table.

Let's take this simple table as our initial state.
AliceDEPOSITA


Mallory uses the deposit address of Alice as a withdrawal address.
AliceDEPOSITA
MalloryWITHDRAWA

Alice does a new deposit and the payment handler has a flaw, it assumes the deposit addresses are unique (not true in a combined table!).
Code:
SELECT user FROM table WHERE (address = A)
That could result in Mallory being selected as the receiver of the deposited funds by Alice. Simply by failing to verify that the type of the address was indeed a deposit address rather than a withdrawal address.
The correct way of getting the right user for the deposit address would be:
Code:
SELECT user FROM table WHERE (address = A AND type= DEPOSIT)

In a combined table (storing both deposit and withdrawal addresses), the primary key is { user, type, address }.
Long story short, do not store deposit addresses and withdrawal addresses in the same table in your database.
The uniqueness deposit vs withdraw addresses does not hold, and they deserve their own tables. A single missing type check in a query can spell disaster.
member
Activity: 111
Merit: 15
Eat, sleep, code, repeat.
January 18, 2019, 04:48:09 PM
#1
Hi,

I'm theorizing what the ideal patterns are for developing applications that deal with centralized payment processing.
I've come up with the following list, please let me know if there is more to add or if you think something is wrong.
There have been many hacks, which is often the fault of monolith systems without proper isolation and authentication.

I haven't looked into topics such as cold storage, anomaly detection, rate limiting and would love to hear ideas.

1. Use microservice pattern
Following the microservice pattern is a must. Payment processors must force interaction through an API. The sensitive payment processing code must have its own database with limited privileges (eg. INSERT, UPDATE, SELECT).
Ask yourself whether deletes are necessary, I recommend not giving it that ability such that there is an audit trail after an incident.
  • Forces you to think about authentication.
  • Isolation of the sensitive code and credentials from the main application.
  • Reduces the attack surface.


2. Split the cryptocurrencies into their own microservices and containers
A malicious insertion into the source of one cryptocurrency, should not affect any other cryptocurrency.
  • Containers/virtualization is your friend, isolate as much as possible.
  • Docker is your friend but be distrustful of container images created by other people. Use private repositories.
  • Bind containers that execute sensitive cryptographic operations to a single dedicated core, use CPU affinity.
  • Each cryptocurrency should have its own database, but the API for interaction should be identical.

3. Process payments from a queue, not on-demand
  • Users shouldn't be able to trigger an asynchronous withdrawal, the corresponding cryptocurrency microservice should maintain a queue which is processed every X amount of time.
  • Use mutex locking to prevent ANY possibility of concurrent processing of payments, if a processing request accidentally wants to process the queue, it must happen in sync.
  • Spamming transaction attacks may trigger payment processing requests that overlap and can therefore cause undefined behavior if no mutex locking is provided.
  • As a general rule: deposits should be processed before withdrawals (to prevent a withdrawal from using coins of an unconfirmed deposit.
  • Always use UTXOs  (txid + vout) and their amount to track payments (rpc command listunspent). Txid's on their own mean nothing.
  • Always check whether a UTXO is already present in the database.
  • Register deposit transactions eagerly and mark them as "unconfirmed", then periodically monitor the transactions for confirmations, and only when confirmed, update the balance of the user. (rpc fields 'safe' and 'solvable')
  • The balance of a user requesting a withdrawal should subtract the balance eagerly and verify that the remaining balance is a positive amount, only then push the withdrawal on the queue of "to be processed".
  • Evict the withdrawal from the queue before actually executing the transaction. A failed withdrawal should not stay in the queue as it may repeat itself and drain all the funds.
  • Think about corner cases where a withdrawal is made to an address within the system and would also have to account for a deposit!
  • Rollback at any error on a transaction. Make sure that the eviction from the "to process" queue (both deposit and withdrawal) is not rollbacked though.

4. Authentication for microservice X should not be valid for microservice Y
Make clever use of authentication. I recommend using OpenID Connect JWT tokens that a cryptographically signed by the authentication microservice.
JWTs should:
  • Be fully verified before even inspecting them.
  • Only be valid for this particular service, tokens generated for other microservices should not provide access.
  • Only be valid for a single request and provide replay protection.
An example of very simple replay protection would be to have an API function that generates a random 'challenge' on a cryptocurrency microservice, stores it locally and also returns it to the user.
Then the user turns to the authentication microservice and ask its to include the hash(challenge + API function + API request) in the creation of the JWT token specific for the cryptocurrency microservice.


5. Optimize for security not for performance
  • Realistically, how many transactions does your company expect to process?
  • If you're using SQL, make sure to always used prepared statements and transactions where necessary.
  • If you're using SQL, make sure to test every endpoint for SQL injections. Doing this retroactively is often PITA to do manually. There are automated tools that can also crawl the website for you.


0. Obvious notes
  • HTTPS everywhere...
Jump to: