Nginx Regex to check MD5 of $http_cookie name - cookies

So i map $http_cookie to check all cookies the client sends the only one i want to intercept to obtain the value of the cookie is any cookie with a MD5 HASH.
The regex to detect a MD5 hash is this
[0-9a-f]{32}
But when i add it to my map directive Nginx won't run because the regex is wrong.
This is my cookie map the issue with this is it gets all cookies i only want the ones with a MD5 sum.
map $http_cookie $session_id_value {
default '';
~^.*.+\=(?<session_value>[\w]+).*$ $session_value;
}
I try this
map $http_cookie $session_id_value {
default '';
~^.*[0-9a-f]{32}.+\=(?<session_value>[\w]+).*$ $session_value;
}
But Nginx does not like my regex. So it errors and won't run.
I test with the echo module to see the value of the cookie my regex has grabbed but currently it keeps grabbing the first random cookie not the one with a MD5 hash for a name.
echo "Session Cookie Value : $session_id_value";
echo "httpcookie : $http_cookie";

That is a syntax error. From the rewrite documentation:
If a regular expression includes the “}” or “;” characters, the whole
expressions should be enclosed in single or double quotes.
Try:
map $http_cookie $session_id_value {
default '';
"~^.*[0-9a-f]{32}.+\=(?<session_value>[\w]+).*$" $session_value;
}

Related

Extra string & pipe character in Laravel Cookies

In a Laravel 6x project I'm working on I'm setting a cookie with:
Cookie::queue('remember_me', json_encode(['uid' => $user->id, 'token' => $token]),2628000);
I'm reading the cookie and decrypting it with:
$cookies = Crypt::decrypt(Cookie::get('remember_me'),false);
This works well, except that the value of $cookies has an extra pre-pended string and a | delimiter in it:
e80cd502fec2a621b624ead8eb1cc91a2e94846b|{"uid":872,"token":"l1214065120208k"}
I can work with that obviously to get what I need but I have been unable to find anything on why that string and | are being prepended to the cookie. Any explanation or documentation link?
I did find another thread here with a similar question but no answer:
How to decrypt cookies in Laravel 8
I also found a thread suggesting that Laravel 8 adds the session_id to the cookie string. Is that what I'm seeing here?
Thanks,
Michael
This value looks to be an HMAC-SHA1 of the cookie name with v2 appended to the end.
This logic is implemented in the CookieValuePrefix class in Laravel and the code looks like so:
public static function create($cookieName, $key)
{
return hash_hmac('sha1', $cookieName.'v2', $key).'|';
}
This is used in the EncryptCookies middleware when encrypting and decrypting accordingly. The relevant source code is:
// in decrypt() function
$hasValidPrefix = strpos($value, CookieValuePrefix::create($key, $this->encrypter->getKey())) === 0;
$request->cookies->set(
$key, $hasValidPrefix ? CookieValuePrefix::remove($value) : null
);
// in encrypt() function
$this->encrypter->encrypt(
CookieValuePrefix::create($cookie->getName(), $this->encrypter->getKey()).$cookie->getValue(),
static::serialized($cookie->getName())
)
I put this logic into a CyberChef page here to test it out with some local cookies I had and verify the output matches and it did. If you go there and plug in your app key (preferable a disposable one) you should see it output the hash value you have in your question.

How to extract request parameter from $request?

I want to extract request parameter( reqId ) value from $request in http block using regex and map
Can you please help me resolving it ?
Sample URL :
test-registration.com/emp/reg?reqId=939393&usrName=Jimmy
I am not sure what would be the regular expression in this case but possible
solution would be like
http {
map $request $requestId {
"regular expression" $reqId;
}
}
If there is any other solution to resolve this issue, please let me know.
I thought I can use $arg_reqId but I am not sure whether I can use it in http block or not.
EDITED:
After extracting the id I want to apply sha-256 hashing on it and put it back to $request.
So new value of $request should be like :
test-registration.com/emp/reg?reqId=$#&$#&yewywjd3&usrName=Jimmy
Thanks
You could try this pattern: reqId=([^&]+)
Explanation:
reqId= - match reqId= literally
(...) - capturing group
[^&]+ - match one or more characters other than &
Required value wll be stored in first capturing group.
Demo
What about this map block:
http {
map $request $requestId {
"~/emp/reg\?reqId=(?<reqId>[0-9]+)" /doSomething/$reqId;
}
}

varnish split url and change url

Is there a way to split url on varnish or change url structure with it.
I know regsub or regsuball support that but they are not enough in my case.
I would like to change a url and redirect it to another domain.
For example:
http://aaa.test.com/sport/99244-article-hyun-jun-suku-kapa.html?
to redirect below address
http://m.test.com/article-hyun-jun-suku-kapa-sport-99244/
I added some lines in vcl file to do that
set req.http.xrul=regsuball(req.url,".html",""); "clear .html"
set req.http.xrul=regsub(req.http.xrul,"(\d+)","\1"); find numbers --article ID =99244
I can rid of the article ID with
set req.http.xrul=regsub(req.http.xrul,"(\d+)","");
but cannot get just only article ID
set req.http.xrul=regsub(req.http.xrul,"(\d+)","\1"); or any other method
Does varnish support split the url with "-" pattern thus I could redesign the url? Or can we get only articleID with regsub?
Is this what you want to achieve?
set req.http.X-Redirect-URL = regsuball(req.url,"^/([^/]*)/([0-9]+)-([^/]+)\.html$","http://m.test.com/\3-\1-\2");
This is working code tailored to example you provided, just one level of section placement.
If you want to support more levels of sections, you only have to adjust regexp a bit and replace / to - in second step:
set req.http.X-Redirect-URL = "http://m.test.com/" + regsuball(regsuball(req.url, "^/(.*)/([0-9]+)-([^/]+)\.html$", "\3-\1-\2"), "/", "-");
Maybe you need one more refinement. What if URL doesn't match you pattern? X-Redirect-URL will be the very same value as req.url is. You definitely don't want redirect loop, so I suggest to add mark character to the begin of X-Redirect-URL and then test for it.
Let's say:
set req.http.X-Redirect-URL = regsuball(regsuball(req.url, "^/(.*)/([0-9]+)-([^/]+)\.html$", "#\3-\1-\2"), "/", "-");
if(req.http.X-Redirect-URL ~ "^#") {
set req.http.X-Redirect-URL = regsuball(req.http.X-Redirect-URL, "#", "http://m.test.com/");
return(synth(391));
} else {
unset req.http.X-Redirect-URL;
}
and for all cases, you need in vcl_synth:
if (resp.status == 391) {
set resp.status = 301;
set resp.http.Location = req.http.X-Redirect-URL;
return (deliver);
}
Hope this helps.

Regex with XPages SSJS to replace querystring value

I have integrated oAuth2 (Facebook, LinkedIn, etc) with my XPages app to allow for authentication to easily add comments (response docs). When a user authenticates, it has to redirect to the facebook/linkedin page, then return to complete the document creation. I use the state variable to do this, and pass it in the querystring of the url. When the page reloads and sees the state variable, it calls a "beforePageLoad" event and creates the response document if the user authenticated and has the correct state document.
My problem is when there is already a state parameter in the querystring. I want to replace the value, not add it to the end. I use a solution here from stackOverflow by ellemayo called updateQueryStringParameter. When I call it from my beforePageLoads it runs, but never replaces the parameter, it only appends it to the end. I end up with ...&state=E5A&state=E5F
I have a feeling that it is in the line,
return uri.replace(re, '$1' + key + "=" + value + '$2');
I can write the code using #ReplaceSubstring(), etc, but want to know if there are problems running regex in XPages SSJS. I read on Lotus.com that
A Regular Expression can be specified as Server-side, which uses the
Java (java.util.regex) API or Client-side, which uses the browser
JavaScript Regular Expression Engine. Client-side and Server-side
Regular Expression syntax is similar, but there are differences that a
user must be aware of.
Should I avoid regex in XPages SSJS ? I have it working extensively in client and in some field validations on the XPage itself.
Here is the call to the function:
if(#Contains( qString,"state=")){
qString=updateQueryStringParameter(qString, "state", linkDoc.getNoteID() );
}else{
qString="?"+qString+"&state=" + linkDoc.getNoteID()
}
the function:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
// I also tried --> if (re.test(uri)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
It was not an XPage or Regex problem. I was using the querystring provided by Domino the excludes the "?" as part of the querystring. when I send "?" + qString to the function, it works. Regex needed to know where to start looking, thus it never found the start of the query string.

Using Servlet filter on all the pages except the index

I'm trying to use a Filter to force my users to login if they want to access some pages.
So my Filter has to redirect them to an error page in there's no session.
But I don't want this to happen when they visit index.html, because they can login in the index page.
So I need an URL Pattern that matches all the pages excluding / and index.xhtml.
How can I do that? Can I use regex in my web.xml ?
EDIT:
After reading this
I thought that I can make something like :
if (!req.getRequestURI().matches("((!?index)(.*)\\.xhtml)|((.*)\\.(png|gif|jpg|css|js(\\.xhtml)?))"))
in my doFilter() method, but it still processes everything.
I'm sure that the regex works because I've tested it online and it matches the files that doesn't need to be filtered, but the content of the if is executed even for the excluded files!
EDIT 2 :
I'm trying a new way.
I've mapped the Filter to *.xhtml in my web.xml, so I don't need to exclude css, images and javascript with the regex above.
Here's the new code (into the doFilter())
if (req.getRequestURI().contains("index")) {
chain.doFilter(request, response);
} else {
if (!userManager.isLogged()) {
request.getRequestDispatcher("error.xhtml").forward(request, response);
} else {
chain.doFilter(request, response);
}
}
but it still doesn't because it calls the chain.doFilter() (in the outer if) on every page.
How can I exclude my index page from being filtered?
The web.xml URL pattern doesn't support regex. It only supports wildcard prefix (folder) and suffix (extension) matching like /faces/* and *.xhtml.
As to your concrete problem, you've apparently the index file defined as a <welcome-file> and are opening it by /. This way the request.getRequestURI() will equal to /contextpath/, not /contextpath/index.xhtml. Debug the request.getRequestURI() to learn what the filter actually retrieved.
I suggest a rewrite:
String path = request.getRequestURI().substring(request.getContextPath().length());
if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER)) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher("/WEB-INF/error.xhtml").forward(request, response);
}
Map this filter on /*. Note that I included the ResourceHandler.RESOURCE_IDENTIFIER check so that JSF resources like <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> will also be skipped, otherwise you end up with an index page without CSS/JS/images when the user is not logged in.
Note that I assume that the FacesServlet is mapped on an URL pattern of *.xhtml. Otherwise you need to alter the /index.xhtml check on path accordingly.