X-CASH-official / xcash-dpops

πŸ—³ Delegated-Proof-of-Private-Stake: First DPoS implementation on a Monero-based coin

Home Page:https://xcash.foundation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Application layer DDoS attack

picatextra opened this issue Β· comments

πŸ› BUG REPORT

By sending a GET request to xcash-dpops , i am able to make the system busy for 2 seconds on a high end VPS.
I am also able to kill xcash-dpops after sending enough request to make the server memory full, and trigger the OOM Killer.

Expected Behavior
Delegate servers should handle this kind of attacks

Current Behavior
socket_thread() make it possible to receive up to 50mo of string data

if (receive_data(client_socket,buffer,MAXIMUM_BUFFER_SIZE,1,SEND_OR_RECEIVE_SOCKET_DATA_TIMEOUT_SETTINGS) < 2)

string_replace() is making a lot of operation on this 50mo string : malloc + memcpy + strstr
char* string_replace(const char *str, const char *sub, const char *rep)

memory leak in receive_data()
str1 = string_replace(message,SOCKET_END_STRING,"");

Possible Solution
Release memory afer calling string_replace()
Make a more optimized code to remove the SOCKET_END_STRING , so the server call handle big data faster.

Steps to Reproduce (for bugs)

  1. Make a GET request to the server's 18283 port ,
  2. Set a user-agent
  3. Set a header with a big string ending with |END|
  4. Send the request many times to make the server memory full
    5 OR send the request from many clients to make a DDOS

Javascript example :

superagent.get('http://delegate.xxx:18283/shareddelegateswebsitegetstatistics')
        .set('User-Agent', 'test')
        .set('joke', '?'.repeat(50000000)+'|END|')
        .catch(reason=>console.log(reason));

Context

Your Environment

@zachhildreth , after some tests i found that string_replace is not so slow.
But a 50mo incoming data is read in 260 parts by recvfrom() .
One solution is receive_data() could exit the loop if the buffer starts with GET / or POST or ...
That would make this DDOS attack less easy.

Thanks @picatextra for looking into this and the string replace idea as well
I will post on here probably in a few days a few different fixes to the code for #16 and #17 as they seem related to a certain extent at least for the solutions.

Hi @picatextra I will post the write up for the bug bounty after I talk to the team, but did want to post an explanation for the fixes

The explanation of the anti DDOS system can be read in this commit message
b72f807

This fix is for issue #16 and #17

Hi @zachhildreth , i don't see an improve for the timeout ddos.

Hi @picatextra for issue #17 it seemed to me your were describing a slowloris style attack

The fixes for this were to limit the IP address to only 20 connections at a time, and to increase the maximum file descriptors the program could use in the systemd service file to boost the server availability.

I did not fully understand the proposed solution for the recvfrom part, because

The socket is a non blocking socket

It calls recvfrom, it will return -1 and errno set to EAGAIN or EWOULDBLOCK if the connection is still sending data, but its not there yet. It will only return -1 if the data could not be read or the client closes the connection, not if it does not have the |END| string in it

It then checks if there was data, grab it, otherwise reloop. If it does have the |END| then its the final data and finish.

Since there is no guarantee with TCP that the data will all come in one packet, There is no way to know when in the timeout a client will send the |END| string, or they may not send it at all. If they dont send it all, there is not a way I see to check this ahead of time, as this is what the timeout is for to limit it to a reasonably amount of time.

Ok i get it, so may be just check if the last char of the buffer is \0 ?

I dont think that would work either, due to the fact that the buffer that pulls the data from the is zero set, so the last byte is always going to contain the null termination string. Thats why its checks if the first byte is not a 0 to see if it received data as I thought this would be quicker than a strlen

Hi @picatextra after discussing with the team, the price agreed upon is 200USD for issue #16 and issue #17 combined

please post a XCASH address

Thanks!

XCA1ka4bXH1bnvdT8vti1S12PfyH8fJ5XDUXyNRusyMRTBfFCawywJyCV5vvG38h71GAv77WotbmwbmbJen5bQpC7GeVx8gSws

Bounty Paid βœ…


Date: 2020-08-05
Amount (USD): $200
Amount (XCASH): 12232415.91 XCASH
Spot Price: 0.00001635 USD/XCASH
XCASH Address: XCA1ka4bXH1bnvdT8vti1S12PfyH8fJ5XDUXyNRusyMRTBfFCawywJyCV5vvG38h71GAv77WotbmwbmbJen5bQpC7GeVx8gSws
Tx Hash: 4204754cc08e3c140a733da8770d79b283d0f2d59938882451e2cb48e7a50d6a
Link: https://explorer.x-cash.org/Transaction?data=4204754cc08e3c140a733da8770d79b283d0f2d59938882451e2cb48e7a50d6a"