Bug 37041 - Logging into addbiblio.pl triggers a 403
Summary: Logging into addbiblio.pl triggers a 403
Status: In Discussion
Alias: None
Product: Koha
Classification: Unclassified
Component: Architecture, internals, and plumbing (show other bugs)
Version: Main
Hardware: All All
: P5 - low normal
Assignee: Marcel de Rooy
QA Contact: Testopia
URL:
Keywords:
Depends on: 24879
Blocks:
  Show dependency treegraph
 
Reported: 2024-06-06 01:09 UTC by David Cook
Modified: 2024-11-15 13:29 UTC (History)
6 users (show)

See Also:
Change sponsored?: ---
Patch complexity: ---
Documentation contact:
Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function:


Attachments
Bug 37041: Store session_id in userenv (3.47 KB, patch)
2024-09-24 13:25 UTC, Jonathan Druart
Details | Diff | Splinter Review
Bug 37041: Use session_id from userenv instead of cookie for value_builder (8.55 KB, patch)
2024-09-24 13:25 UTC, Jonathan Druart
Details | Diff | Splinter Review
Bug 37041: Add C4::Auth::check_value_builder_caller (2.55 KB, patch)
2024-10-11 09:59 UTC, Marcel de Rooy
Details | Diff | Splinter Review
Bug 37041: Use check_value_builder_caller in value builder plugins (3.47 KB, patch)
2024-10-11 09:59 UTC, Marcel de Rooy
Details | Diff | Splinter Review
Bug 37041: Add C4::Auth::check_value_builder_caller (2.59 KB, patch)
2024-10-11 14:02 UTC, Marcel de Rooy
Details | Diff | Splinter Review
Bug 37041: Use check_value_builder_caller in two value builder plugins (3.57 KB, patch)
2024-10-11 14:02 UTC, Marcel de Rooy
Details | Diff | Splinter Review
Bug 37041: Adjust remaining MARC21 value builder plugins (16.32 KB, patch)
2024-10-11 14:02 UTC, Marcel de Rooy
Details | Diff | Splinter Review

Note You need to log in before you can comment on or make changes to this bug.
Description David Cook 2024-06-06 01:09:08 UTC
As Michal Kula noted on Mattermost, trying to log into http://localhost:8081/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=9908 in main will yield a bizarre HTTP response that includes headers for a 403 response and a 200 response...

This is partially due to bug 37040, but it's mostly due to a bug in addbiblio.pl where the form builder is generating a 403 that gets printed before the 200 response somehow...
Comment 1 David Cook 2024-06-06 01:17:25 UTC
If I capture STDOUT around a subsection of build_tabs(), I get 10 of these messages in STDOUT:

[2024/06/06 01:12:47] [WARN] Status: 403 Forbidden
Content-Type: text/plain; charset=ISO-8859-1

Status: 403 Forbidden
Content-Type: text/plain; charset=ISO-8859-1

--

I suspect is has something to do with these warnings:

[2024/06/06 00:08:33] [WARN] ERROR: Plugin marc21_orgcode.pl: ARRAY(0x561ffb8bfa98) at /kohadevbox/koha/Koha/UI/Form/Builder/Biblio.pm line 222.
[2024/06/06 00:08:33] [WARN] ERROR: Plugin marc21_field_005.pl: ARRAY(0x561ffb8cdb60) at /kohadevbox/koha/Koha/UI/Form/Builder/Biblio.pm line 222.
Comment 2 David Cook 2024-06-06 01:30:27 UTC
Looks like a regression caused by bug 24879 

Note that I'm not planning on working on this one.
Comment 3 Marcel de Rooy 2024-08-12 08:05:58 UTC
(In reply to David Cook from comment #1)

> I suspect is has something to do with these warnings:
> 
> [2024/06/06 00:08:33] [WARN] ERROR: Plugin marc21_orgcode.pl:
> ARRAY(0x561ffb8bfa98) at /kohadevbox/koha/Koha/UI/Form/Builder/Biblio.pm
> line 222.
> [2024/06/06 00:08:33] [WARN] ERROR: Plugin marc21_field_005.pl:
> ARRAY(0x561ffb8cdb60) at /kohadevbox/koha/Koha/UI/Form/Builder/Biblio.pm
> line 222.

Seeing those too. Will have a look.
Comment 4 Marcel de Rooy 2024-08-12 09:37:49 UTC
The arrays mentioned just contain:
$VAR2 = [
          'EXIT
',
          0
        ];

This is just caused by the new CGI on bug 24879. Easier to replace that by blocking direct access to valuebuilder scripts. See my comment there.
Comment 5 Marcel de Rooy 2024-08-12 09:49:44 UTC
(In reply to Marcel de Rooy from comment #4)
> The arrays mentioned just contain:
> $VAR2 = [
>           'EXIT
> ',
>           0
>         ];
> 
> This is just caused by the new CGI on bug 24879. Easier to replace that by
> blocking direct access to valuebuilder scripts. See my comment there.

To clarify: The new CGI makes that the wrong session ID is checked and that the builder scripts bail out with 403.
Comment 6 Katrin Fischer 2024-08-12 13:12:39 UTC
For my understanding of the urgency of this: if you log in from another page or the normal "main" login page this problem doesn't occur?
Comment 7 Marcel de Rooy 2024-08-12 13:17:47 UTC
(In reply to Katrin Fischer from comment #6)
> For my understanding of the urgency of this: if you log in from another page
> or the normal "main" login page this problem doesn't occur?

Yeah thats true. So the impact is small. But our catalogers are constantly on those pages and when their session times out, they come across it.
Comment 8 Katrin Fischer 2024-08-12 13:19:23 UTC
I think in this case we might keep this one open for the next regular maintenance release - still high priority to fix, but I don't want to interrupt release process.
Comment 9 Jonathan Druart 2024-08-14 14:30:32 UTC
There is something fundamentally wrong in the way we handle the session id. Which leads to this kind of problems.

Should we consider setting the session id in the L1 (actually in the userenv) so that we could have access to the current session id. So if a new one has been generated and is different than the one in the cookie of the request we can access it easily?

We would have then:
  check_cookie_auth( C4::context->{userenv}->{session_id}, $required_flags );
and not relying on CGI.

Another way would be to trick CGI and replace HTTP_COOKIE env var. But this seems very hacky and certainly not something recommended.
Comment 10 Marcel de Rooy 2024-08-14 14:37:56 UTC
(In reply to Jonathan Druart from comment #9)
> There is something fundamentally wrong in the way we handle the session id.
> Which leads to this kind of problems.
> 
> Should we consider setting the session id in the L1 (actually in the
> userenv) so that we could have access to the current session id. So if a new
> one has been generated and is different than the one in the cookie of the
> request we can access it easily?
> 
> We would have then:
>   check_cookie_auth( C4::context->{userenv}->{session_id}, $required_flags );
> and not relying on CGI.
> 
> Another way would be to trick CGI and replace HTTP_COOKIE env var. But this
> seems very hacky and certainly not something recommended.

Looks easier to remove the newly added CGI in the value_builder scripts and block access in another way (RewriteRule or just move the files?).
The original design should not have used scripts here ..
The tric with passing another session id feels hacky too?
Comment 11 Jonathan Druart 2024-08-14 15:19:01 UTC
(In reply to Marcel de Rooy from comment #10)
> (In reply to Jonathan Druart from comment #9)
> > There is something fundamentally wrong in the way we handle the session id.
> > Which leads to this kind of problems.
> > 
> > Should we consider setting the session id in the L1 (actually in the
> > userenv) so that we could have access to the current session id. So if a new
> > one has been generated and is different than the one in the cookie of the
> > request we can access it easily?
> > 
> > We would have then:
> >   check_cookie_auth( C4::context->{userenv}->{session_id}, $required_flags );
> > and not relying on CGI.
> > 
> > Another way would be to trick CGI and replace HTTP_COOKIE env var. But this
> > seems very hacky and certainly not something recommended.
> 
> Looks easier to remove the newly added CGI in the value_builder scripts and
> block access in another way (RewriteRule or just move the files?).

Easier maybe but then we have something specific in the apache config we could avoid. I am asking if there is something "better", not "easier" ;)

> The original design should not have used scripts here ..

Yes, but too late.

> The tric with passing another session id feels hacky too?

It is not another session id, it is actually the *current* session id!
Comment 12 David Cook 2024-08-15 00:19:19 UTC
(In reply to Jonathan Druart from comment #9)
> Should we consider setting the session id in the L1 (actually in the
> userenv) so that we could have access to the current session id. So if a new
> one has been generated and is different than the one in the cookie of the
> request we can access it easily?

I'm not aware of the exact code problem, but this sounds all right to me. If it were a MVC like Catalyst/Mojo, we'd have something like $c->user or $c->session, so C4::Context->userenv is probably our next best thing (for now)?

One day we'll move away from CGI scripts (even ones wrapped with Plack::App::CGIBin)...
Comment 13 Jonathan Druart 2024-09-24 13:25:19 UTC
Created attachment 171931 [details] [review]
Bug 37041: Store session_id in userenv
Comment 14 Jonathan Druart 2024-09-24 13:25:22 UTC
Created attachment 171932 [details] [review]
Bug 37041: Use session_id from userenv instead of cookie for value_builder
Comment 15 Jonathan Druart 2024-09-24 13:26:30 UTC
Only to share what I had in mind. It fixes the problem it seems, but can eventually introduce new ones...

Now the session's id is stored in userenv, so we don't want to leak it! It seems safe however.
Comment 16 Marcel de Rooy 2024-10-11 06:50:44 UTC
(In reply to Jonathan Druart from comment #15)
> Only to share what I had in mind. It fixes the problem it seems, but can
> eventually introduce new ones...
> 
> Now the session's id is stored in userenv, so we don't want to leak it! It
> seems safe however.

Yeah, interesting. But in terms of security perhaps not the way we want to go..
Comment 17 Marcel de Rooy 2024-10-11 07:22:41 UTC
Will try to submit another proposal.
Comment 18 Marcel de Rooy 2024-10-11 09:59:46 UTC
Created attachment 172685 [details] [review]
Bug 37041: Add C4::Auth::check_value_builder_caller

Test plan:
Run t/db_dependent/FrameworkPlugin.t
Run xt/find-missing-auth_checks.t

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Comment 19 Marcel de Rooy 2024-10-11 09:59:49 UTC
Created attachment 172686 [details] [review]
Bug 37041: Use check_value_builder_caller in value builder plugins

Test plan:
Verify if item editor and tools/batchmod work as expected.
Directly hit a value builder plugin like:
    https://YOUR_STAFF_SERVER/cgi-bin/koha/cataloguing/value_builder/barcode.pl
Verify that you get a 403 page regardless of being logged in or not.
Run t/db_dependent/FrameworkPlugin.t
Run xt/find-missing-auth_checks.t

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Comment 20 Marcel de Rooy 2024-10-11 10:01:15 UTC
Counter proposal.
Not finished yet, but to give an idea. Check caller stack. Optional exit via new Auth subroutine. Remove check_cookie_auth from value builder plugins. Adjust missing checks script.
Comment 21 Marcel de Rooy 2024-10-11 14:02:45 UTC
Created attachment 172694 [details] [review]
Bug 37041: Add C4::Auth::check_value_builder_caller

Test plan:
Run t/db_dependent/FrameworkPlugin.t
Run xt/find-missing-auth_checks.t

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Comment 22 Marcel de Rooy 2024-10-11 14:02:47 UTC
Created attachment 172695 [details] [review]
Bug 37041: Use check_value_builder_caller in two value builder plugins

Test plan:
Verify if item editor and tools/batchmod work as expected.
Directly hit a value builder plugin like:
    https://YOUR_STAFF_SERVER/cgi-bin/koha/cataloguing/value_builder/barcode.pl
Verify that you get a 403 page regardless of being logged in or not.
Run t/db_dependent/FrameworkPlugin.t
Run xt/find-missing-auth_checks.t

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Comment 23 Marcel de Rooy 2024-10-11 14:02:50 UTC
Created attachment 172696 [details] [review]
Bug 37041: Adjust remaining MARC21 value builder plugins

Test plan:
Edit a biblio record and verify active plugins work as expected.
(See first test plan) Test hitting some plugins directly.
Run t/db_dependent/FrameworkPlugin.t
Run xt/find-missing-auth_checks.t
Comment 24 Marcel de Rooy 2024-10-11 14:09:28 UTC
Still needs attention at UNIMARC side
Comment 25 Jonathan Druart 2024-10-15 10:52:38 UTC
(In reply to Marcel de Rooy from comment #16)
> (In reply to Jonathan Druart from comment #15)
> > Only to share what I had in mind. It fixes the problem it seems, but can
> > eventually introduce new ones...
> > 
> > Now the session's id is stored in userenv, so we don't want to leak it! It
> > seems safe however.
> 
> Yeah, interesting. But in terms of security perhaps not the way we want to
> go..

In term of cleaning our session handling code however we need that, and it could be a good excuse to introduce it.

If we want it, then do it now. Otherwise we can go with your alternative approach.
Comment 26 Marcel de Rooy 2024-10-15 11:14:27 UTC
(In reply to Jonathan Druart from comment #25)
> (In reply to Marcel de Rooy from comment #16)
> > (In reply to Jonathan Druart from comment #15)
> > > Only to share what I had in mind. It fixes the problem it seems, but can
> > > eventually introduce new ones...
> > > 
> > > Now the session's id is stored in userenv, so we don't want to leak it! It
> > > seems safe however.
> > 
> > Yeah, interesting. But in terms of security perhaps not the way we want to
> > go..
> 
> In term of cleaning our session handling code however we need that, and it
> could be a good excuse to introduce it.
> 
> If we want it, then do it now. Otherwise we can go with your alternative
> approach.

Lets separate both developments. I think that the cookie_auth_check should not be in the value builder plugins regardless of the session id being in the context or not. Suppose that the cookie check would pass via context [user logged in with perms], than we still have an unwanted script call resulting in a 500 error. (The original design should have prevented calling those scripts..) So the session_id patches do not resolve the problem of this report.

As said before, we could also rely on Apache/nginx etc to restrict access to that folder. But the caller logic is a trivial fix in one place, not affecting the installation itself (apache file etc). So easier to backport?

Could we move your patches to a new specific report? What do you think?
Comment 27 Jonathan Druart 2024-10-15 11:50:18 UTC
(In reply to Marcel de Rooy from comment #26)
> (In reply to Jonathan Druart from comment #25)
> > (In reply to Marcel de Rooy from comment #16)
> > > (In reply to Jonathan Druart from comment #15)
> > > > Only to share what I had in mind. It fixes the problem it seems, but can
> > > > eventually introduce new ones...
> > > > 
> > > > Now the session's id is stored in userenv, so we don't want to leak it! It
> > > > seems safe however.
> > > 
> > > Yeah, interesting. But in terms of security perhaps not the way we want to
> > > go..
> > 
> > In term of cleaning our session handling code however we need that, and it
> > could be a good excuse to introduce it.
> > 
> > If we want it, then do it now. Otherwise we can go with your alternative
> > approach.
> 
> Lets separate both developments. I think that the cookie_auth_check should
> not be in the value builder plugins regardless of the session id being in
> the context or not. Suppose that the cookie check would pass via context
> [user logged in with perms], than we still have an unwanted script call
> resulting in a 500 error. (The original design should have prevented calling
> those scripts..) So the session_id patches do not resolve the problem of
> this report.

How that? It worked when I've written it.

> As said before, we could also rely on Apache/nginx etc to restrict access to
> that folder. But the caller logic is a trivial fix in one place, not
> affecting the installation itself (apache file etc). So easier to backport?

Easier but I don't think it is really nice.

> Could we move your patches to a new specific report? What do you think?

That will be yet another thing that will get lost. I am willing to abandon it. 
Obsoleting the patches now.
Comment 28 Marcel de Rooy 2024-10-15 11:55:56 UTC
(In reply to Jonathan Druart from comment #27)
> How that? It worked when I've written it.

Please explain. Those scripts return a hash with builder and launcher. No HTTP for a browser. What probably worked, was calling without being logged in.

> Easier but I don't think it is really nice.
Agreed

> That will be yet another thing that will get lost. I am willing to abandon
> it. 
> Obsoleting the patches now.

Not my intention. But lacking the time now to follow-up on them too. There was a reason to implement this approach?
Comment 29 Jonathan Druart 2024-10-15 12:34:29 UTC
With the session's id available in userenv you don't have to rely on CGI. And with CGI you get the session's id from the cookie which may be obsolete (example here if you are in the middle/after of a login operation).
I am not sure what you want me to explain as I am sure you understood all that already.

I just thought it was a good opportunity to clean up this area, as the way we handle the session's id lead us to problem like this one.

We should certainly try to reach this workflow:
- Auth from credential or CGISESSID cookie
- Set userenv
- Rely on userenv to know if the user is currently authenticated
- Add CGISESSID to the response

And the value_builder scripts here would return 403 unless C4::Auth::is_authenticated({catalogue => 1})

is_auth would just need to get the patron's id from userenv, if exists it means that the user is authenticated already.
Comment 30 Jonathan Druart 2024-10-15 12:37:16 UTC
(In reply to Jonathan Druart from comment #29)
> is_auth would just need to get the patron's id from userenv, if exists it
> means that the user is authenticated already.

Wait, isn't that true already actually?

Cannot we simply replace the check_cookie_auth call with
  C4::Auth::haspermission(C4::Context->userenv->{id}, {catalogue => 1})
here?
Comment 31 Marcel de Rooy 2024-10-15 13:37:36 UTC
(In reply to Jonathan Druart from comment #30)
> (In reply to Jonathan Druart from comment #29)
> > is_auth would just need to get the patron's id from userenv, if exists it
> > means that the user is authenticated already.
> 
> Wait, isn't that true already actually?
> 
> Cannot we simply replace the check_cookie_auth call with
>   C4::Auth::haspermission(C4::Context->userenv->{id}, {catalogue => 1})
> here?

No, if this is a direct call to a value builder, the answer should be 403 (or 400) in any case. Not depending on login or permissions.
This is what check_value_builder_caller implements too.
Comment 32 Jonathan Druart 2024-11-15 13:29:04 UTC
I think we need to restore the first version, and store the session's id in userenv