bpatrik / pigallery2

A fast directory-first photo gallery website, with rich UI, optimized for running on low resource servers (especially on raspberry pi)
http://bpatrik.github.io/pigallery2/
MIT License
1.76k stars 202 forks source link

Security issue: Protect against mallicious requests. #214

Open bpatrik opened 3 years ago

bpatrik commented 3 years ago

This is not an app related issue, but rather a setup issue.

I have noticed that my server gets requests from unexpected IPs requesting wordpress related sites. Example:

"GET /solr/admin/info/system?wt=json HTTP/1.1"
"GET /?XDEBUG_SESSION_START=phpstorm HTTP/1.1" 
"GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"
"GET /api/jsonws/invoke HTTP/1.1"
"GET /console/ HTTP/1.1"
"POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1" 
"POST /Autodiscover/Autodiscover.xml HTTP/1.1"
"GET /index.php?s=/Index/\x5Cthink\x5Capp/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=HelloThinkPHP21 HTTP/1.1" 
"GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"
"GET /wp-content/plugins/wp-file-manager/readme.txt HTTP/1.1" 
"GET /Autodiscover/Autodiscover.xml HTTP/1.1" 
"GET /solr/admin/info/system?wt=json HTTP/1.1"

I have also noticed unsuccessful login ssh attempts.

Symptom of the issue:

Error shown in the pigallery2 logs:

12/27/2020, 5:11:17 AM[WARN] Handled error:
ErrorDTO {
  code: 10,
  message: 'Unknown server side error',
  details: ForbiddenError: invalid csrf token
      at csrf (/app/node_modules/csurf/index.js:112:19)
      at result (/app/node_modules/express-unless/index.js:49:5)
      at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
      at trim_prefix (/app/node_modules/express/lib/router/index.js:317:13)
      at /app/node_modules/express/lib/router/index.js:284:7
      at Function.process_params (/app/node_modules/express/lib/router/index.js:335:12)
      at next (/app/node_modules/express/lib/router/index.js:275:10)
      at cookieParser (/app/node_modules/cookie-parser/index.js:57:14)
      at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
      at trim_prefix (/app/node_modules/express/lib/router/index.js:317:13) {
    code: 'EBADCSRFTOKEN'
  },
  detailsStr: 'ForbiddenError: invalid csrf token'
}

The UI shows:

Unknown server error
{ "message": "invalid csrf token", "code": "EBADCSRFTOKEN" }
astyonax commented 3 years ago

Hi, how do you get/enable those logs?

For ssh, have you considered fail2ban (https://github.com/fail2ban/fail2ban) ?

bpatrik commented 3 years ago

The first log was only nginx log that I use as a reverse proxy. The second log are the pigallery default logs. You can also log everything within the app, if you set the Log-level to 'silly' or 'debug'

I think my issue may come from two sources. I'm using 1) duckdns.org 2) freenom.com Both is a bit fishy. I also saw failed attempts to log into my ssh. (even tho, I moved it from the default 22 port)

I looked into it that time. I also came across the fail2ban, but haven't added yet.

bpatrik commented 3 years ago

I'm giving a try to this: https://github.com/trick77/ipset-blacklist

It looks promising

bpatrik commented 3 years ago

Did not resolve everything, but helped.

Trying to fix it with some nginx restriction: Relevant part:


    # Only allow GET for root (/). see https://github.com/bpatrik/pigallery2/issues/214
    location = / {
      limit_except GET {
        deny  all;
      }
      proxy_pass http://pigallery2:80; # forwarding to the other container, named 'pigallery2'
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
    }

    location / {
      proxy_pass http://pigallery2:80; # forwarding to the other container, named 'pigallery2'
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
    }
SlavikCA commented 3 years ago

As it's already mentioned

This is not an app related

So, speaking of implementing setup security measures,

1) rate limiting on the login endpoints. So, preventing brute-forcing 2) block requests to potentially sensitive endpoints, such ".git" or config folders 3) block IP of scanners. For example, if the request is for known WordPress endpoint - block the IP 4) Disable nginx server_tokens 5) Prevent Buffer Overflow by lowering buffer sizes

astyonax commented 3 years ago

I tried enabling fail2ban to filter the failed logins but the I didn't manage to parse the log, however, since I run pigallery2 behind a reverse proxy (traefik) I enabled the default botsearch filter and jail that matches well known paths (worpress&co) and excessive 404 requests. For nginx the filter is here: /etc/fail2ban/filter.d/nginx-botsearch.conf .

bpatrik commented 3 years ago

@SlavikCA you are absolutely right with fail2ban, I was just lazy to set it up sofar.

Although I think the app could do better job with the nginx setup.

The docker container does not contain any unnecessary files and the node only servers files within the dist folder.

If you have any simple addons for the general nginx.conf that would be appreciated: https://github.com/bpatrik/pigallery2/blob/master/docker/docker-compose/default/nginx.conf

I will also update the location once I tested the change only instance. This https://github.com/bpatrik/pigallery2/issues/214#issuecomment-843574296 does not work.

The app only has GET for root / and some files on the root and within the /assets folder. And has GET, POST, PUT, OPTION, for /api/*. So I'm trying something l to better match this.