Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add xmlrpc.php to http-bf-wordpress_bf #863

Open
adam-ah opened this issue Oct 27, 2023 · 12 comments
Open

[FEATURE] Add xmlrpc.php to http-bf-wordpress_bf #863

adam-ah opened this issue Oct 27, 2023 · 12 comments
Labels
question Further information is requested

Comments

@adam-ah
Copy link

adam-ah commented Oct 27, 2023

What would you like to be added?

/kind enhancement

What

WP brute force often comes as repeated 200 requests to xmlrpc.php. The current http-bf-wordpress_bf does not catch this.

Sample log (this repeated 20 times before WordFence blocked it)

36.134.168.163 - - [28/Oct/2023:01:07:57 +1100] "POST //xmlrpc.php HTTP/1.1" 200 401 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36"

Sample explanation

line: 36.134.168.163 - - [28/Oct/2023:01:08:01 +1100] "POST //xmlrpc.php HTTP/1.1" 200 401 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36"
        ├ s00-raw
        |       ├ 🟢 crowdsecurity/non-syslog (+5 ~8)
        |               ├ update evt.ExpectMode : %!s(int=0) -> 1
        |               ├ update evt.Stage :  -> s01-parse
        |               ├ update evt.Line.Raw :  -> 36.134.168.163 - - [28/Oct/2023:01:08:01 +1100] "POST //xmlrpc.php HTTP/1.1" 200 401 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36"
        |               ├ update evt.Line.Src :  -> /tmp/access_log
        |               ├ update evt.Line.Time : 0001-01-01 00:00:00 +0000 UTC -> 2023-10-27 20:00:01.871814211 +0000 UTC
        |               ├ create evt.Line.Labels.type : apache2
        |               ├ update evt.Line.Process : %!s(bool=false) -> true
        |               ├ update evt.Line.Module :  -> file
        |               ├ create evt.Parsed.message : 36.134.168.163 - - [28/Oct/2023:01:08:01 +1100] "POST //xmlrpc.php HTTP/1.1" 200 401 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36"
        |               ├ create evt.Parsed.program : apache2
        |               ├ update evt.Time : 0001-01-01 00:00:00 +0000 UTC -> 2023-10-27 20:00:01.871832908 +0000 UTC
        |               ├ create evt.Meta.datasource_path : /tmp/access_log
        |               ├ create evt.Meta.datasource_type : file
        |       └ 🔴 crowdsecurity/syslog-logs
        ├ s01-parse
        |       └ 🟢 crowdsecurity/apache2-logs (+21 ~2)
        |               └ update evt.Stage : s01-parse -> s02-enrich
        |               └ create evt.Parsed.clientip : 36.134.168.163
        |               └ create evt.Parsed.httpversion : 1.1
        |               └ create evt.Parsed.rawrequest :
        |               └ create evt.Parsed.response : 200
        |               └ create evt.Parsed.timestamp : 28/Oct/2023:01:08:01 +1100
        |               └ create evt.Parsed.verb : POST
        |               └ create evt.Parsed.bytes : 401
        |               └ create evt.Parsed.ident : -
        |               └ create evt.Parsed.target_fqdn :
        |               └ create evt.Parsed.port :
        |               └ create evt.Parsed.referrer : -
        |               └ create evt.Parsed.request : //xmlrpc.php
        |               └ create evt.Parsed.auth : -
        |               └ create evt.Parsed.http_user_agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36
        |               └ update evt.StrTime :  -> 28/Oct/2023:01:08:01 +1100
        |               └ create evt.Meta.http_user_agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36
        |               └ create evt.Meta.log_type : http_access-log
        |               └ create evt.Meta.source_ip : 36.134.168.163
        |               └ create evt.Meta.http_path : //xmlrpc.php
        |               └ create evt.Meta.http_status : 200
        |               └ create evt.Meta.http_verb : POST
        |               └ create evt.Meta.service : http
        ├ s02-enrich
        |       ├ 🟢 crowdsecurity/dateparse-enrich (+2 ~2)
        |               ├ create evt.Enriched.MarshaledTime : 2023-10-28T01:08:01+11:00
        |               ├ update evt.Time : 2023-10-27 20:00:01.871832908 +0000 UTC -> 2023-10-28 01:08:01 +1100 AEDT
        |               ├ update evt.MarshaledTime :  -> 2023-10-28T01:08:01+11:00
        |               ├ create evt.Meta.timestamp : 2023-10-28T01:08:01+11:00
        |       ├ 🟢 crowdsecurity/geoip-enrich (+13)
        |               ├ create evt.Enriched.ASNNumber : 9808
        |               ├ create evt.Enriched.IsInEU : false
        |               ├ create evt.Enriched.ASNOrg : China Mobile Communications Group Co., Ltd.
        |               ├ create evt.Enriched.ASNumber : 9808
        |               ├ create evt.Enriched.IsoCode : CN
        |               ├ create evt.Enriched.Latitude : 23.118100
        |               ├ create evt.Enriched.Longitude : 113.253900
        |               ├ create evt.Enriched.SourceRange : 36.134.128.0/18
        |               ├ create evt.Meta.ASNNumber : 9808
        |               ├ create evt.Meta.IsoCode : CN
        |               ├ create evt.Meta.SourceRange : 36.134.128.0/18
        |               ├ create evt.Meta.ASNOrg : China Mobile Communications Group Co., Ltd.
        |               ├ create evt.Meta.IsInEU : false
        |       ├ 🟢 crowdsecurity/http-logs (+7)
        |               ├ create evt.Parsed.file_ext : .php
        |               ├ create evt.Parsed.file_name : xmlrpc.php
        |               ├ create evt.Parsed.file_dir : //
        |               ├ create evt.Parsed.file_frag : xmlrpc
        |               ├ create evt.Parsed.static_ressource : false
        |               ├ create evt.Parsed.impact_completion : true
        |               ├ create evt.Meta.http_args_len : 0
        |       └ 🟢 crowdsecurity/whitelists (unchanged)
        ├-------- parser success 🟢
        ├ Scenarios

Why

WP will assess login requests sent to xmlrpc.php and return 200. WordFence will eventually block the user but that is much more compute-intensive task. Without WordFence this would not get blocked, letting bruteforce attacks through.

How

Simply add checking for xmlrpc.php in http-bf-wordpress_bf.yaml:

6c6
< filter: "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name in ['wp-login.php', 'xmlrpc.php'] && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '200'"
---
> filter: "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name == 'wp-login.php' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '200'"

Sample after the change

The parsing is as-expected after the change:

line: 36.134.168.163 - - [28/Oct/2023:01:08:00 +1100] "POST //xmlrpc.php HTTP/1.1" 200 401 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0 Safari/537.36"
        ├ s00-raw
        |       ├ 🟢 crowdsecurity/non-syslog (+5 ~8)
        |       └ 🔴 crowdsecurity/syslog-logs
        ├ s01-parse
        |       └ 🟢 crowdsecurity/apache2-logs (+21 ~2)
        ├ s02-enrich
        |       ├ 🟢 crowdsecurity/dateparse-enrich (+2 ~2)
        |       ├ 🟢 crowdsecurity/geoip-enrich (+13)
        |       ├ 🟢 crowdsecurity/http-logs (+7)
        |       └ 🟢 crowdsecurity/whitelists (unchanged)
        ├-------- parser success 🟢
        ├ Scenarios
                └ 🟢 crowdsecurity/http-bf-wordpress_bf

Why is this needed?

xmlrpc.php brute force attacks are not captured correctly

@github-actions
Copy link

@adam-ah: Thanks for opening an issue, it is currently awaiting triage.

In the meantime, you can:

  1. Check Crowdsec Documentation to see if your issue can be self resolved.
  2. You can also join our Discord.
  3. Check Releases to make sure your agent is on the latest version.
Details

I am a bot created to help the crowdsecurity developers manage community feedback and contributions. You can check out my manifest file to understand my behavior and what I can do. If you want to use this for your project, you can check out the BirthdayResearch/oss-governance-bot repository.

@github-actions
Copy link

@adam-ah: There are no 'kind' label on this issue. You need a 'kind' label to start the triage process.

  • /kind feature
  • /kind enhancement
  • /kind bug
  • /kind packaging
Details

I am a bot created to help the crowdsecurity developers manage community feedback and contributions. You can check out my manifest file to understand my behavior and what I can do. If you want to use this for your project, you can check out the BirthdayResearch/oss-governance-bot repository.

@LaurenceJJones
Copy link
Contributor

Transferring parser/scenario request to the hub repository

@LaurenceJJones LaurenceJJones transferred this issue from crowdsecurity/crowdsec Oct 27, 2023
@LaurenceJJones
Copy link
Contributor

Hey 👋🏻

I don't use word press personally but if repeated calls to xmlrpc in short duration is not normal behavior then you can open a pull request on this repository with your changes you purposed

@adam-ah
Copy link
Author

adam-ah commented Oct 27, 2023

thanks for moving the ticket to the right repo, @LaurenceJJones I'll keep that in mind for future reference

@GNU-Plus-Windows-User
Copy link
Contributor

this sounds like a bad idea, especially when you take into consideration 3rd party plugins that use the xmlrpc API endpoint heavily.

@LaurenceJJones LaurenceJJones added the question Further information is requested label Oct 28, 2023
@adam-ah
Copy link
Author

adam-ah commented Oct 28, 2023

@GNU-Plus-Windows-User your point of view is inaccurate for the following reasons:

  • no legit plugins should hammer the xmlrpc.php endpoint (see capacity and leakspeed parameters in Crowdsec)
  • if anyone hammers xmlrpc.php it's either DDoS or password bruteforce
  • none of the stock standard popular WP plugins use xmlrpc.php (I have over a dozen plugins installed, only hackers call the xmlrpc.php endpoint)
  • without using a 3rd party plugin (e.g., WordFence), crowdsec's http-bf-wordpress_bf plugin fails to block bruteforce attacks
  • several security guides recommending downright disabling xmlrpc.php 1 2
  • users without deep technical knowledge incorrectly believe http-bf-wordpress_bf protecting them from bruteforce attacks

Further reading on fail2ban and xmlrpc 1 2

In your response, could you please address each of these, with a special focus about the concern regarding adding a correct brureforce filter with the appropriate leakspeed and capacity parameters, with evidence (logs) showing that indeed, it is not possible or downright harmful?

@GNU-Plus-Windows-User
Copy link
Contributor

no legit plugins should hammer the xmlrpc.php endpoint

I don't know about this, plugins like jetpack do use the xmlrpc endpoint a fair bit. I don't use jetpack anymore so this may have changed. I can test this if you like.

if anyone hammers xmlrpc.php it's either DDoS or password bruteforce

Maybe, it depends on what the xmlrpc.php is used for, and the use case, this is my main concern by expanding the scenario to cover xmlrpc.

none of the stock standard popular WP plugins use xmlrpc.php (I have over a dozen plugins installed, only hackers call the xmlrpc.php endpoint)

That doesn't mean anything, the xmlrpc api endpoint wasn't created for hackers to hack wordpress. Yes, it's a common attack vector but so is port 443, that doesn't mean you should be shutting off port 443. If you don't need it then it makes sense to disable it since that's a basic attack surface reduction technique.

without using a 3rd party plugin (e.g., WordFence), crowdsec's http-bf-wordpress_bf plugin fails to block bruteforce attacks

I understand that concern and I fully support expanding brute force protection to XMLRPC, if it doesn't cause any additional FPs which is my main concern.

several security guides recommending downright disabling

You shouldn't be blindly following the advise of security guides online, if you don't need the xmlrpc.php endpoint then it makes sense to disable it. Disabling xmlrpc is something that should be taken on a case by case basis, disabling stuff without knowing what it does is a sure fire way to break stuff. I've seen a lot of very bad takes in the wordpress community, to be fair many of these people aren't security experts.

users without deep technical knowledge incorrectly believe http-bf-wordpress_bf protecting them from bruteforce attacks

Agreed, CrowdSec should add a disclaimer for the scenario to prevent confusion.

@GNU-Plus-Windows-User
Copy link
Contributor

These logs are from using the wordpress app:

0.0.0.0 - - [30/Oct/2023:05:37:03 +1100] "POST /xmlrpc.php HTTP/2.0" 200 631 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:03 +1100] "POST /xmlrpc.php HTTP/2.0" 200 265 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:05 +1100] "POST /xmlrpc.php HTTP/2.0" 200 278 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:05 +1100] "POST /xmlrpc.php HTTP/2.0" 200 403 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 5154 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 9523 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 635 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 678 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 678 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 635 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 635 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 635 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:06 +1100] "POST /xmlrpc.php HTTP/2.0" 200 678 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:07 +1100] "POST /xmlrpc.php HTTP/2.0" 200 135 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:08 +1100] "POST /xmlrpc.php HTTP/2.0" 200 135 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:10 +1100] "POST /xmlrpc.php HTTP/2.0" 200 403 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"
0.0.0.0 - - [30/Oct/2023:05:37:10 +1100] "POST /xmlrpc.php HTTP/2.0" 200 278 "-" "Mozilla/5.0 (Linux; Android 14; Pixel 7 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 wp-android/23.4"

You'd have to have a seperate scenario with a fairly leniant leak speed and capacity, maybe 5s leak speed and a capacity of 20.
There may be some other plugins that use xmlrpc even more than the wordpress app

@LaurenceJJones
Copy link
Contributor

LaurenceJJones commented Oct 30, 2023

I also just realized, we have a separate scenario

It is NOT included by default due to reasons outlined by @GNU-Plus-Windows-User

https://app.crowdsec.net/hub/author/crowdsecurity/collections/wordpress

@adam-ah
Copy link
Author

adam-ah commented Oct 30, 2023

Great find, @LaurenceJJones

The solution could be (?) then to add it to the description of the collection to encourage installing the optional http-bf-wordpress_bf_xmlrpc as in most cases this would be needed.

I think these all come back to the high suprise factor of CrowdSec defaults - I would not expect a wordpress scenario made by CrowdSec to be not included in the WordPress collection (probably most users would not expect it, even though it is a critical scenario for most of wp users). Taking 3 days and 3 people to find this may suggest that something is not quite right...

@LaurenceJJones
Copy link
Contributor

LaurenceJJones commented Oct 30, 2023

The solution could be (?) then to add it to the description of the collection to encourage installing the optional http-bf-wordpress_bf_xmlrpc as in most cases this would be needed.

Yeah I agree, we have over 200 scenarios so adding links in the markdown is easy to aid other to find them. We are also working on a recommendation system in the hub depending on tags. So when viewing the wordpress collection it will offer other scenarios with similar tags (Excluding the ones inside the collection itself)

Edit: Plus when our WAAP (waf) comes out, we can easily generate rules based on the HTTP body itself rather than having a vague scenarios based on higher limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants