htmly icon indicating copy to clipboard operation
htmly copied to clipboard

CSRF Token not correct - again

Open nightflasher opened this issue 3 years ago • 22 comments

I hosted my fpv blog on my raspberry pi, which also has pihole installed and occasionally has a q3a server running, so this cannot work properly for long.

I have an account at lima-city and copied the complete blog to their server, php7 is selected and running. I can read the blog, every single page seems fine. But when I try to login, the CSRF error is happening and I don't know why.

nightflasher avatar Jul 27 '22 08:07 nightflasher

Same issue, also on lima-city.de. I asked the provider and they say:

Instead of using the following notation as normal:

$_SESSION['csrf_token'] = sha1(microtime(true) . mt_rand(10000, 90000));

In the "system/includes/functions.php" this notation is used, which I actually haven't come across yet:

$_SESSION[config("site.url")]['csrf_token'] = sha1(microtime(true) . mt_rand(10000, 90000)); (Translated)

https://github.com/danpros/htmly/blob/master/system/includes/functions.php#L2958-L2962

unz3r0 avatar Aug 22 '22 22:08 unz3r0

I am only a lurker here, but it's hard for me to understand what you mean @unz3r0 Often CSRF errors happen because of some misconfiguration of the HTTP server (Apache/Nginx/etc) Please could you display here the raw HTML content of the login page? (you have to be unlogged) For me it's this (which is normal)

  <form method="POST" action="login">
        User <span class="required">*</span> <br>
        <input type="text" class="" name="user"/><br><br>
        Password <span class="required">*</span> <br>
        <input type="password" class="" name="password"/><br><br>
        <input type="hidden" name="csrf_token" value="34a28a5d50d04bf7b653801c6198ba169311c017">
                <input type="submit" name="submit" value="Login"/>
    </form>

Hjertesvikt avatar Aug 23 '22 07:08 Hjertesvikt

@Hjertesvikt

Here you go:

  <form method="POST" action="login">
        <label>User <span class="required">*</span></label>
        <input type="text" class="form-control " name="user" placeholder="User"/>
        <br>
        <label>Password <span class="required">*</span></label>
        <input type="password" class="form-control " name="password" placeholder="Password"/>
        <br>
        <input type="hidden" name="csrf_token" value="7226cfffb6f9f02468a7c193a7fbca0dc5040f3d">
                <input type="submit" class="btn btn-primary" name="submit" value="Login"/>
    </form> 

Maybe worth to note that I needed to change:

site.url = "https://sub.example.com:443" to site.url = "https://sub.example.com"

so that I can view it.

unz3r0 avatar Aug 23 '22 13:08 unz3r0

Maybe worth to note that I needed to change:

site.url = "https://sub.example.com:443" to site.url = "https://sub.example.com"

so that I can view it.

And now with this new settings, does it work? In past discussion, it was recommended to set correctly the site in config, to mitigate some CSRF issues

Hjertesvikt avatar Aug 23 '22 15:08 Hjertesvikt

Maybe worth to note that I needed to change: site.url = "https://sub.example.com:443" to site.url = "https://sub.example.com" so that I can view it.

And now with this new settings, does it work? In past discussion, it was recommended to set correctly the site in config, to mitigate some CSRF issues

No it didn't work. Here test it yourself: https://that.webspace.rocks/login This is anyway just for testing...

Maybe it matters:

$ firefox --version 
Mozilla Firefox 103.0.2

I am not a PHP programmer and therefore having only really basic experience with php.

Anyway, thanks for taking a look at it @Hjertesvikt ;-)

unz3r0 avatar Aug 23 '22 18:08 unz3r0

I see that URLs are still appended with :443 at the end. If you specify the protocol as HTTPS, there is no need to config the site name as "https://sub.example.com:443" Please could you change it in the config page of HTMLy?

Hjertesvikt avatar Aug 23 '22 19:08 Hjertesvikt

I see that URLs are still appended with :443 at the end. If you specify the protocol as HTTPS, there is no need to config the site name as "https://sub.example.com:443" Please could you change it in the config page of HTMLy?

I changed it @Hjertesvikt

unz3r0 avatar Aug 23 '22 19:08 unz3r0

Your HTTP server is OpenResty? Did you have a look at this page: https://github.com/shrikeh/csrf-nginx-redis-lua

Hjertesvikt avatar Aug 23 '22 19:08 Hjertesvikt

No it is Apache 2.4 on Ubuntu Bionic 18.04.6 .. however it is a webspace with ssh, but I have not access to the global configs.

What is really needed to point out what actually the problem here is. Is the apache configs or is it the htmly code? Do you have an idea how I could prove it?

unz3r0 avatar Aug 23 '22 19:08 unz3r0

No it is Apache 2.4 on Ubuntu Bionic 18.04.6 .. however it is a webspace with ssh, but I have not access to the global configs.

The web tools if Firefox tell the HTTP response is sent by an Openresty HTTP server: image

Hjertesvikt avatar Aug 23 '22 20:08 Hjertesvikt

Interesting... So it could be ngnix problem? Never noticed it. php info says it is apache 2.4 . Do you have an idea how it can be proven that it is a faulty configuration?

unz3r0 avatar Aug 23 '22 20:08 unz3r0

Is the apache configs or is it the htmly code? Do you have an idea how I could prove it?

You can put some test code in HTML function get_csrf() but that will be a rabbit hole.

Normally both Apache and HTMLy works out of the box.

I guess your provider has a proxy between the HTTP clients and its infrastructure, perhaps as a HTTP load balancer or something. And its based on Openresty and it's messing with HTTP headers. That looks quite weird and improbable with a commercial provider, so I am short of suggestions, sorry.

Hjertesvikt avatar Aug 23 '22 20:08 Hjertesvikt

php info says it is apache 2.4 .

Yes it's normal, PHP runs on Apache, so it reports Apache as host.

Do you have an idea how it can be proven that it is a faulty configuration?

Unfortunately I have no idea. Your provider looks much faster than mine (OVH) I may give it a try at some time.

Hjertesvikt avatar Aug 23 '22 20:08 Hjertesvikt

Weird I hosted a test site on lima-city.de, The HTLMy function 'generates_csrf_token()' generates a different token from the one that was just sent (which anyway looks to be always the same for the same session?) csrf_token: f91c1a8869492d183903ead02908f8e9b56deece, get_csrf: 15d9f8f095ed0152deff2210c3f1bef6698b7fe1

as in system/includes/function.php:

// Check the csrf token
function is_csrf_proper($csrf_token)
{
echo  '<br>csrf_token: ' . $csrf_token . ', get_csrf: ' . get_csrf() . '<br>' ;

    if ($csrf_token == get_csrf()) {
        return true;
    }
    return false;
}

I guess that in my own code base (which is slightly different from the current HTMLy) I will make a thorough code review of the CSRF management. CSRF management is one of the most basic security requirement on Internet.

Hjertesvikt avatar Aug 24 '22 10:08 Hjertesvikt

I guess that lima-city automatic anti-spam software is overreacting:

citizens forum wrote: I would also be interested in whether you can somehow deactivate this except with exit () before the

Hjertesvikt avatar Aug 28 '22 16:08 Hjertesvikt

@Hjertesvikt Thanks. I asked the support again and the supporter said he will refer me to another one. They will contact me as soon as they known more. So I will wait a bit and report back.

unz3r0 avatar Aug 30 '22 04:08 unz3r0

lima-city staff here. @Hjertesvikt @unz3r0 @nightflasher

The solution is simple: the PHP default for session.auto_start is off by default (and we don't change that). htmly simply never starts a session (by calling session_start()) before checking the CSRF token, so the $_SESSION array is empty.

Maybe your (LAMP/XAMP) environments are configured differently, but that is the PHP production default.

The suggested fix is that htmly calls session_start() before checking the CSRF token.

Workaround: add a .user.ini with session.auto_start = On

phillipp avatar Sep 01 '22 14:09 phillipp

Thanks Phillipp to take the time to provide this information! I really appreciate, I may switch to lima-city when my current VPS subscription will be over!

I am only a HTMLy user, so I may tell things that are incorrect or imprecise, @danspros is the author of HTMLy.

HTMLy exists since 9 years and nobody complained about problems with CSRF. Session management comes from an older project: https://github.com/noodlehaus/dispatch

When index.php is called at the root by the HTTP server, index.php calls system/htmly.php. htmly.php includes (at installation) session.php which can be found in system/includes session.php calls session_start(); So it happens very early, well before the login page is presented to the user.

On my blog, I use HTMLy since 2 years on a VPS from OVH with Debian and Apache and never had any problem. PHP info() indicates that on my VPS session.auto_start is Off.

Yet a var_dump() of $_SESSION on my VPS when not being logged shows that $_SESSION array is not empty. image So the session is indeed started before the login page is sent to the browser.

Hjertesvikt avatar Sep 01 '22 18:09 Hjertesvikt

I managed to get HTMLy working on lima-city.de.

My previous attempts where by uploading my code on the host by FTP. It didn't work because of "too many redirections", but I did not try further.

Now I used the installer with the official version of HTMLy, as probably @unz3r0 @nightflasher did. I wonder if the installation on lima-city might be broken (not because of HTMLy), for example when I installed HTMLy I received the message "too many redirections".

As you said Phillipp, I had to add session_start() in htmly.php to make it work. Yet it makes no sense, HTMLy does not need that.

Hjertesvikt avatar Sep 02 '22 12:09 Hjertesvikt

session_start();

taufik-nurrohman avatar Sep 02 '22 12:09 taufik-nurrohman

Yes you are right, I will edit my text above :-)

Hjertesvikt avatar Sep 02 '22 12:09 Hjertesvikt

I think I understand better what's happening when the host is lima-city.de

Lima-city.de does not use $_COOKIE['PHPSESSID'] as in the case on Apache HTTP servers. This is easy to show, just call phpinfo(). image (I guess Lima-city uses a NGINX server as load balancer in front of Apache HTTP servers or something similar)

Yet HTMLy uses PHPSESSID, for example in session.php: image When I replaced this with a test on $_SESSION, HTMLy works better as I can now authenticate as an 'admin' user. image

Don't try https://csrf.4lima.de/News/ I use it as a test system as I am doing a major rewrite of HTMLy for my own blog: https://padiracinnovation.org/News/

JPLeRouzic avatar Sep 25 '22 14:09 JPLeRouzic