Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dockerized laravel server denies POST requests [closed]

Here is a completely reproducible docker image of a REST API Laravel server:

FROM php
RUN apt-get update
RUN apt-get install zip -y
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
RUN composer create-project laravel/laravel frontend
WORKDIR frontend
COPY web.php web.php
RUN mv web.php routes
EXPOSE 8000
CMD [ "php", "artisan", "serve", "--host", "0.0.0.0" ]

The only thing I edited was a single endpoint (web.php):

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return csrf_token();
});

Route::post('/', function (Request $request) {
    if ($request->hasFile('source'    )) { return ">> GOOD ! <<"; }
    if ($request->hasFile('input.json')) { return ">> GOOD ! <<"; }

    $x = count($_FILES);

    return "DD >> $x << DD";
});

I build and run the docker image as follows:

$ docker build --tag host.translator.php --file Dockerfile .
$ docker run -p 8008:8000 -d -t --name translator.php host.translator.php

Then just like related posts say (here, and here, and also here):

$ Set-Variable -Name X -Value (curl.exe -X GET -F "[email protected]" http://127.0.0.1:8008/)
# X holds the token:
# echo $X
# U263lUv3dz9PH7ySm3GmgUUjHjjWm78cqofODUmh

But when I try to use that token it doesn't work:

$ curl.exe --header "X-CSRFToken:$X" -X POST -F "[email protected]" http://127.0.0.1:8008/ | Select-String "<title>Page Expired"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6851    0  6609  100   242  80486   2947 --:--:-- --:--:-- --:--:-- 83548

        <title>Page Expired</title>

Any help is very much appreciated - thanks !

EDIT:

#
# used a new variable Z - just to be sure ...
#
$ Set-Variable -Name Z -Value (curl.exe -b cookiejar -X GET -F "[email protected]" http://127.0.0.1:8008/)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   282    0    40  100   242    527   3194 --:--:-- --:--:-- --:--:--  3760
$ echo $Z # this looks good, right ?
aHvU5WOaGs9qxOIzgdYb90TJUKPDgDaNhYjQNALW
#
$ type .\cookiejar # this looks ... hmmm ... good (I think ?)
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_127.0.0.1     FALSE   /       FALSE   1711103819      laravel_session eyJpdiI6IllsOW9KdlVzT1ZPcUJDOUdQRnUyZHc9PSIsInZhbHVlIjoiekpING13WFRaaDRLUHBUcVpNM0VjblBwVjlXM1VrSU1uYUF3dk43d0J6c0RvSDJ5UWZOU3lla1lKVjBNRnNVTXJOaTNMdmt3dlIvdW5HZDk1ODZUb0gxVWMySHh5cXBWeG5XbjVMQlpMQ2xoMzM0ODROQ1FGQ0NMQzFNaHNQMXMiLCJtYWMiOiI0MTg3ZTM0NTlmNWMzZGUyZDY3YzI2YWViYzc2MDZhMjAyMjA2NzE5YmRmYTRmYWRmYzQxODIzYmVlOThlZTkxIiwidGFnIjoiIn0%3D
#
# Now let's cross our fingers extra strong !
#
$ curl.exe -c cookiejar --header "X-CSRFToken:$Z" -X POST -F "[email protected]" http://127.0.0.1:8008/ | Select-String "<title>Pa
ge Expired"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6851    0  6609  100   242  85705   3138 --:--:-- --:--:-- --:--:-- 87833
242  83137   3044 --:--:-        <title>Page Expired</title>- --
:--:-- --:--:-- 85637
like image 950
OrenIshShalom Avatar asked Nov 30 '25 16:11

OrenIshShalom


1 Answers

CSRF (Cross-Site Request Forgery) is a way to protect the server from forgery.

See https://laravel.com/docs/11.x/csrf

In order to pass this validation in the normal way, you need to pass a X-CSRF-TOKEN header (not X-CSRFToken as you did it with a typo) and pass a proper CSRF token.

The mechanism for CSRF token is as follows:

  • the site allows you to run some entry points (some GET requests, for example) without passing CSRF
  • and afterwards, you need to set the header for CSRF tokens properly upon any POST requests that you might send
  • whenever a page/request is handled, the old CSRF token is invalidated and your session will get a new CSRF token which needs to be passed in the next POST instead of the previous one

So, if you are sending a POST request via CURL, then a CSRF token needs to be determined, true, but you will need to send the newest one.

You can exclude URLs from CSRF protection, but be careful, don't reduce your security standards if possible via

->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ]);
})

and then the request will be handled properly. If it's an entry point (like in posting a JWT for SSO), then it makes sense to allow that specific end point to run without CSRF, for it is authenticating the user anyway. Otherwise, you will always need to obtain the latest CSRF token and add it to the header of your requests.

like image 166
Lajos Arpad Avatar answered Dec 03 '25 07:12

Lajos Arpad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!