moleculerjs / moleculerjs/database

Race condition attack

Open
#27 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
33
Forks
15
Avg merge
15m
Merged PRs (30d)
1

Description

There is such a problem as the race condition attack.

This problem is famous when using the ORM pattern as Active Record and Data Mapper.
We get a record for changes and change it outside the transaction, which means that we can execute precisely the same query in parallel.

https://github.com/moleculerjs/database/blob/3729bf9c06d1d06d2781abf2f7f7ddf0c435594a/src/methods.js#L592-L595

https://github.com/moleculerjs/database/blob/3729bf9c06d1d06d2781abf2f7f7ddf0c435594a/src/methods.js#L618

Consider a simple attack in transferring $5 from Alice to Bob:

Get balance Alice -> $5 -> transfer to Bob -$5 -> get balance Bob -> $0 -> received from Alice +$5

And now, if two queries were running at the same time:

Query 1: Get balance Alice -> $5 (race condition!) -> transfer to Bob -$5 -> get balance Bob -> $0 -> received from Alice +$5

Query 2: Get balance Alice -> $5 (race condition!) -> transfer to Bob -$5 -> get balance Bob -> $5 -> recieved from Alice +$5

Bob has a balance of $10, and Alice has $5.

It is elementary to check this behaviour by calling the Promise.all() method, we generate ten requests and, depending on the network, and the processing speed of the database, from 2 to 10 requests will pass simultaneously.

In SQL, the first statement must be with SELECT FOR UPDATE to block against concurrent updates, or both wrapped in a SERIALIZABLE transaction isolation level.

How can we protect ourselves now?

We must wrap the updateEntity method in a transaction with isolation level SERIALIZABLE.
Or use moleculer-channels to update items in strong FIFO in Kafka.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/methods.js at the referenced lines around updateEntity and review how concurrent updates are handled. Reproduce the behavior with parallel Promise.all requests and inspect the database adapter's transaction support. Done means concurrent balance updates cannot produce the demonstrated inconsistent result, using the transaction or locking behavior supported by the project.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, sql
Domain
backend, databases
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.