Livewire WithFileUpload 401 with url's not matching so failing signature check - file-upload

I have a livewire file uploader on a project. When you select a file it says The uploads failed to upload. The firefox dev toolbox says it is a 401 error. I investigated further and found via https://github.com/livewire/livewire/issues/1216 that commenting out a line in the livewire vendor src (abort_unless(request()->hasValidSignature(), 401);) actually doesn't show this message and allows the file to upload but this is obviously extremely bad practice for mulitple reasons (update of livewire will undo change, it removes csrf protection and as it's in the vendor folder it is not in my repo).
I decided instead to step into how this is working and found it is creating a malformed url. This is in the laravel framework /Illuminate/Routing/UrlGenerator: line 413 [hasCorrectSignature]
/**
* Determine if the signature from the given request matches the URL.
*
* #param \Illuminate\Http\Request $request
* #param bool $absolute
* #param array $ignoreQuery
* #return bool
*/
public function hasCorrectSignature(Request $request, $absolute = true, array $ignoreQuery = [])
{
$ignoreQuery[] = 'signature';
$url = $absolute ? $request->url() : '/'.$request->path();
$queryString = collect(explode('&', (string) $request->server->get('QUERY_STRING')))
->reject(fn ($parameter) => in_array(Str::before($parameter, '='), $ignoreQuery))
->join('&');
$original = rtrim($url.'?'.$queryString, '?');
$signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
return hash_equals($signature, (string) $request->query('signature', ''));
}
As I step over this function with Xdebug I get the following variables
$url = "https://my-project.dev/livewire/upload-file"
$queryString = "/livewire/upload-file&expires=1674038186"
$original = "https://my-project.dev/livewire/upload-file?/livewire/upload-file&expires=1674038186" <- note this is malformed right?
signature this makes is
fc95677fc265d9ad90e0ff5413eecf5cb08df82b3971b468109e1011fc323406
And lastly the signature created from the query is
6152b1a0c51c2e7532d2665bf3f2cf3a809802689185b0c5d73e2854024de124
So these do not match and thus it fails, I suspect that the signature of the correct url will match the 2nd signature (i.e. signature for https://my-project.dev/livewire/upload-file&expires=1674038186). So how do I ensure this url is correct.
I've noticed a more than likely related issue with url's when I login the app after being auto logged out so if i was on a page https://my-project.dev/foo/bar then after logging back in it is now https://my-project.dev/foo/bar?%2Ffoo%2Fbar= This has no impact on the page that is generated.
My .htaccess in the public folder is:
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L,QSA]
thanks

For anyone else that has this issue I had an overnight epithany and realised that the issue is the wildcard in the htaccess RewriteRule. Remove the ? and everything works correctly. It also fixed the odd url issue I was getting.
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L,QSA]

Related

.htaccess rewrite rules behaving in a wrong way

I'm building an events website, in all my websites i do the following logic:
RewriteEngine On
Options +FollowSymLinks
RewriteBase /
RewriteRule ^new/event?(/)?$ controller.php?page_name=new-event [QSA,L]
RewriteRule ^get-event/([^/]+)?(/)?$ controller.php?page_name=get-event&event_id=$1 [QSA,L]
RewriteRule ^event/([^/]+)/([^/]+)?(/)?$ controller.php?page_name=event&event_id=$1 [QSA,L]
RewriteRule ^event-edit/([^/]+)?(/)?$ controller.php?page_name=event-edit&event_id=$1 [QSA,L]
// this below line to handle all links that do not apply to the above rules, is this wrong?
RewriteRule ^([^/]+)?(/)?$ controller.php?page_name=$1 [QSA,L]
The last line is to handle all URLs that don't have anything other than the page name, like those:
www.example.com/event-submit/
www.example.com/about/
www.example.com/contact/
Because I made a controller.php file that handles all the requests depending on the page_name value.
But this is not working with this new site, here's what i get:
when I request any URL belonging to this site, the browser just hangs and takes forever, sometimes the page loads but after like 5 minutes.
I have no idea why! (It works on all my other websites!)
Am I doing anything wrong? I have searched a lot and nothing is working.
EDIT
This is controller.php: (it just checks for page_name if it's allowed and then includes it)
<?php
session_start();
define('__SITE_ROOT__', dirname(__FILE__));
define('__HELPERS__', __SITE_ROOT__ . '/' . 'helpers');
define('__APP__', __SITE_ROOT__ . '/' . 'app');
$page_name = strip_tags($_GET['page_name']);
$allowed_pages = array(
'index',
'about',
'contact',
'new-event',
'event-edit',
'get-event',,
'404'
);
class Controller{
public $page_name = 'index';
public $allowed_names = array();
}
$controller = new Controller();
$controller->allowed_names = $allowed_pages;
$controller->page_name = $page_name;
if(in_array($controller->page_name, $controller->allowed_names))
{
$page_real_name = $controller->page_name . ".php";
}else{
$page_real_name = "404.php";
}
include(__APP__ . '/' . $page_real_name);
// this below line to handle all links that do not apply to the above rules, is this wrong?
RewriteRule ^([^/]+)?(/)?$ controller.php?page_name=$1 [QSA,L]
This rule would create a rewrite-loop (500 error), since the regex ^([^/]+)?(/)?$ would also match controller.php (the URL being written to) and you don't appear to have anything that would otherwise prevent this?
You could resolve this my adding a dot to the character class, so it won't match the dot in .php. For example:
RewriteRule ^([^/.]+)?/?$ controller.php?page_name=$1 [QSA,L]
You don't need to surround the last / in parentheses.
(I'm assuming the // comment is just in your question, since that is syntactically invalid. Comments are delimited with #.)
the browser just hangs and takes forever, sometimes the page loads but after like 5 minutes.
However, the above doesn't quite explain this behaviour, unless maybe LimitInternalRecursion is set very high in your server config?! (Default is 10)

convert dynamic to seo friendly url

I know there is plenty on this issue in SO and elsewhere, and I read it all by now, but I do not seem to get this to work despite sweating it out all day.
So, see if you guys can point me in the right direction.
I have a dynamically created url ( by customer selecting a form at index.php ) that looks like, as an instance:
http://www.example.com/marques.php?brand_id=39-Ford
I need it to show to the user and search engines as:
www.example.com/marques/Ford
I have set up .htaccess as follows:
...other .htaccess stuff..
RewriteEngine on
RewriteCond %{REQUEST_URI} ^\/marques #here, I believe, to apply this only when URI is /marques
RewriteRule /([A-Z][a-z]+$)/ marques/$1 [L] #here I meant to get 'Ford' in this instance.
I plan to have the destination file, marques.php handle the request with the given brand info.
This is not working at all. I continue to see the 'old' URL.
Of course, the next step would be to have the .htaccess redirect when the customer clicks on the 'friendly' link at the search engine ( hopefully soon ). But I need the first step to be resolved.
By the way, I checked with my provider and they confirm that mod_rewrite is enabled.
Thanks for your help.
You can use this your root .htaccess:
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/+marques\.php\?brand_id=([^\s&]+) [NC]
RewriteRule ^ /marques/%1? [R=301,L]
RewriteRule ^marques/([^/.]+)/?$ marques.php?brand_id=$1 [L,QSA,NC]
After further investigation I realized I fell for this widespread misconception that one can use mod_rewrite to create SEO friendly URL's. Unfortunately, this misconception is reinforced throughout SO as well.
After reading this article from Matthew James Taylor and this it became clear that one has to create the SEO friendly URL elsewhere, not through mod_rewrite, as was my thinking.
Mod_rewrite is ONLY part of the process.
If one has only links with anchor tags, one has to go in each page of the website and hardcode the change to the SEO friendly URL. In my case, the URL's are created dynamically.
May be there are alternative solutions, but this did the trick.
So, first I changed my form, from this:
<form action="marques.php " method="post" class="form1" >
<select class="select_home" name="brand_id" onchange="form.submit()" >
<option value= "<?php echo $row['brand_id']; ?>">"<?php echo $row['brand']; ?>"</option>
To this new set up:
<form action=" " method="post" class="form1" >
<select class="select_home" name="brand" onchange="form.submit()" >
<option value= "<?php echo $row['brand']; ?>">"<?php echo $row['brand']; ?>"</option>
What I am doing above is submitting the form to the page itself by placing action = " " and changing name and value to 'brand' ie, the name of the brand as opposed to the brand_id. This last one is meant to have the URL 'really' friendly. One can decide to have both the name and the id in the URL.
The SEO friendly URL is 'created' in the sequence. This script is placed at the very top of the same page, before anything else, otherwise 'header' will not work.
if(isset($_POST['brand'])){
$brand = $_POST['brand'];
$brand = str_replace(" ", "-", $brand);
$url = '/marques-voiture/' . $brand;
header("Location:" .$url );
exit();
}
So, in the above the SEO friendly URL is created and will show at the browser:
www.example.com/marques/Ford or www.example.com/Land-Rover
Next, now yes, with mod_rewrite tell the browser how to make sense of that URL and fetch the right script which is:
www.example.com/marques.php?brand=Ford
I made that as follows within .htaccess:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/?marques-voiture [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ([\-A-Za-z]+$) /marques.php?brand=$1 [L]
Of course it is necessary to change the destination script to receive a GET, instead of a POST which now contains the brand and not the brand_id as before.
Hope that helps.

Is it possible write a cookie with the current url using Apache

A third party application I am working with normally allows the user to bookmark pages anywhere on the site. Once logged in the user will be redirected to the original page requested. Unfortunately through a commissioned single sign on customization this functionality gets lost. That is to say if you use a bookmark to access a specific page in the product (or get an email or follow an external link), if you are not already signed in you go to a log in page and then get returned to the main application page instead of the page requested.
If I can set a cookie with the original URL requested I can then use that information through JavaScript to change the location upon landing on the home page.
Let's say the home page is /app/index.jsp - If I could get a cookie to remember any URL but this one - I could restore the functionality that the user goes to the requested page after they log in. Is this possible?
I found the solution to this myself...
Using mod_rewrite I could key on the initial request by looking for the JSESSIONID cookie. The folowing when placed within my servers virtualhost section achieved my goal.
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/app/*$
RewriteCond %{REQUEST_URI} !^/content/.*$
RewriteCond %{REQUEST_URI} !^/app/adm/.*$
RewriteCond %{REQUEST_URI} !^/app/index\.jsp$
RewriteCond %{REQUEST_URI} !^/favicon\.ico$
RewriteCond %{HTTP:Cookie} !^.*JSESSIONID=.*$
RewriteRule . - [co=appURI:%{REQUEST_URI}?%{QUERY_STRING}:.mydomain.com]
Note: I added some filters above for pages I did not want to set the cookie for. I use JavaScript to detect, unset the cookie, and redirect within the application to achieve my goal.
var appURI = getCookie("appURI");
if (typeof(appURI) != "undefined" && appURI != null && appURI != "") {
mydomain.console.log("Found URI from SSO relocating to: " + appURI);
setCookie("appURI", "", -1, "/", "mydomain.com");
document.location.href = appURI;
}
Note that "setCookie" and "mydomain.console.log" above are proprietary but simple functions that do the obvious actions based on their names.

How to redirect page with query-string to external webpage using APACHE RewriteRule

I am trying to redirect a login page to an external security service. This service, after validating the credentials, will then return user back to the originating page using the referrer url, as in the following example:
http://{IP NUMBER}/MyWiki/index.php?title=Special:UserLogin&returnto=Main_Page
or any call to a page in the site containing Special:UserLogin in the query_string needs to be redirected to:
https://login.security.server.com/test/UI/Login?service=DSSEC&goto=http://{IP NUMBER}/MyWiki/index.php/Special:UserLogin
I have been testing with RewriteCond and RewriteRule without any luck.
You want something like this?
RewriteEngine On
RewriteCond %{REQUEST_URI} Special:UserLogin [OR]
RewriteCond %{QUERY_STRING} Special:UserLogin
RewriteCond ?#%{QUERY_STRING} ([^#]+)#([^#]+)
RewriteRule ^ https://login.security.server.com/test/UI/Login?service=DSSEC&goto=http://%{SERVER_ADDR}%{REQUEST_URI}%1%2 [L,B,NE]
Ok, this is going to seem a little confusing, but here's what's going on.
Check if Special:UserLogin is in the request URI or the query string.
Create backreference matches for the ? mark, the URI and the query string (this is very important)
Redirect the request to https://login.security.server.com/test/UI/Login, but using the back references from the previous condition to build the goto= param, and using the B flag, which URL encodes the backreferences. This way, the result is an entire URL, along with query string, that's been URL encoded. (The NE flag is there to make sure the % signs themselves don't get double encoded).
With these rules, a request for:
/MyWiki/index.php?title=Special:UserLogin&returnto=Main_Page
Will get redirected to:
https://login.security.server.com/test/UI/Login?service=DSSEC&goto=http://123.45.67.89/MyWiki/index.php%3ftitle%3dSpecial%3aUserLogin%26returnto%3dMain_Page
As you can see, the query string ?title=Special:UserLogin&returnto=Main_Page gets encoded into %3ftitle%3dSpecial%3aUserLogin%26returnto%3dMain_Page, so that the login.security.server.com doesn't mistake it for its own query string. Instead, their login service will see the goto parameter as:
http://123.45.67.89/MyWiki/index.php?title=Special:UserLogin&returnto=Main_Page
entirely intact.

htaccess: Can't check dynamic file existence!

I have written a on-the-fly thumbnail creator by an htaccess file looking to see if the requested file exists and if not sending the user to a php page to create it. My htaccess file looks like this:
# Check the formatting (this works)
RewriteCond %{SCRIPT_FILENAME}%{QUERY_STRING} /([a-zA-Z0-9-]+).(jpg|gif|png)w=([0-9]+)&h=([0-9]+)(&c=(true|false))
# Only forward to thumbnail.php if file doesn't exist
#RewriteCond %{REQUEST_FILENAME} !-f #this works but not for the correct filename!
RewriteCond %1-%2-%3-%4-%6.jpg !-f # Doesn't work!!!
# If file doesn't exist, send here: (this works)
RewriteRule ^.*$ thumbnail.php?file_name=%1&type=%2&w=%3&h=%4&c=%6
My check of the file's existence does not seem to work however... the old version that uses %{REQUEST_FILENAME} works, but that is not the correct filename I need to check. I have verified that the new file %1-%2-%3-%4-%6.jpg has the correct output, but does not trigger the condition!
Based on this URL:
this-is-the-image-name.gif?w=200&h=100&c=true
The htaccess file should check if this file exists:
this-is-the-image-name-gif-200-100-true.jpg
The thumbnails and htaccess file are both in the same folder, but this folder is unknown and can't be hardcoded. Does it need the full path to check? If so, how can I get the full path but with my custom filename?
Pulling my hair out with this one... PLEASE help! Thank you.
You can use your PHP script to replace the traditional "404 Error" page :
ErrorDocument 404 thumbnail.php
Then, you can retrieve the requested URL using PHP :
$url = $_SERVER["REQUEST_URI"];
Parameters can be retrieved using the preg_match function.