BernieC has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to access the home page at dreamhost.com and after a bunch of trying to figure out why I can't submit its form I've discovered why: Dreamhost sends me two cookies, but LWP only "jars" one of them. My access the page codes looks like

#!/usr/bin/perl use strict; use warnings ; use LWP::UserAgent () ; use HTTP::Cookies ; use Data::Dumper ; my $ua = LWP::UserAgent->new ; $ua->agent("Mozilla/5.0") ; my $cookies = HTTP::Cookies->new(file => "$ENV{APPDATA}/cookies.txt", autosave => 1, ignore_discard => 1) ; $ua->cookie_jar($cookies) ; my $res = $ua->get("https://panel.dreamhost.com/") ; print Dumper($cookies->get_cookies("https://panel.dreamhost.com/")); exit ;

and when I run it I get

d:\Desktop\Dreamhost>testcookies $VAR1 = { 'sh' => 'uPpLKaEsFiu0wKyBBTpfzTxRjsS9eJOOXl3AK-nUNm9viXXJ0rA +-ECZrwOwf };
BUT.. when I use Web Developer to access the same page, it tells me:

Request cookies: csrf wHvDOzh6BPebWCZiSvaTTZXVa-s1avJR sh i5OG_QmjNcIDJjd8y3vFzRCiQTT4HQvvPKkFre7lbFN5ntZbu3huRUiG-841

and sure enough, when I try to submit the login form with my browser I find

POST /index.cgi HTTP/1.1 Host: panel.dreamhost.com User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20 +100101 Firefox/61.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0. +8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://panel.dreamhost.com/ Content-Type: application/x-www-form-urlencoded Content-Length: 80 Cookie: sh=i5OG_QmjNcIDJjd8y3vFzRCiQTT4HQvvPKkFre7lbFN5ntZbu3huRUiG-84 +1; csrf=6tX7UCZ-XZ1KL8Z1Q9mPmp9dBIeXXdoO DNT: 1 Connection: keep-alive Upgrade-Insecure-Requests: 1

Any insights into why UserAgent isn't grabbing the csrf cookie {and what I might do to make it happen}?

Thanks! /bernie\

Replies are listed 'Best First'.
Re: Bug in LWP? Missing cookie
by bliako (Abbot) on Aug 03, 2018 at 11:48 UTC

    I would 1) set the user-agent string in perl script to be the same as your browser's, 2) remove ignore_discard, 3) Dump all cookies irrespective of domain/url (re: get_cookies()).

    Might be irrelevant but note that LWP::UserAgent, by default, follows re-directs (e.g. 301, 302) unless you say so, for certain operations (search for max_redirect and requests_redirectable in its doc).

    Note, you have a password in your post

Re: Bug in LWP? Missing cookie
by hippo (Archbishop) on Aug 03, 2018 at 12:42 UTC
    Any insights into why UserAgent isn't grabbing the csrf cookie

    That will be because the server isn't sending it:

    $ HEAD https://panel.dreamhost.com/ 200 OK Connection: close Date: Fri, 03 Aug 2018 12:38:47 GMT Server: Apache Vary: Accept-Encoding Content-Length: 3570 Content-Type: text/html; charset=ISO-8859-1 Client-Date: Fri, 03 Aug 2018 12:38:47 GMT Client-Peer: 66.33.205.234:443 Client-Response-Num: 1 Client-SSL-Cert-Issuer: /C=US/ST=New Jersey/L=Jersey City/O=The USERTR +UST Network/CN=USERTrust RSA Domain Validation Secure Server CA Client-SSL-Cert-Subject: /OU=Domain Control Validated/OU=Provided by N +ew Dream Network, LLC/OU=DreamHost Basic Wildcard SSL/CN=*.dreamhost. +com Client-SSL-Cipher: ECDHE-RSA-AES128-GCM-SHA256 Client-SSL-Socket-Class: IO::Socket::SSL Set-Cookie: sh=uNdHXzI1jn8W6e_vwHeygjmCKkWEot6H8e-dVpMZcB60qqJallOrUn- +2KlZ3; domain=panel.dreamhost.com; path=/; expires=Mon, 31-Jul-2028 0 +5:38:47 GMT; secure; HttpOnly X-Frame-Options: DENY

      Maybe the cookie is set after logging in?

      I've now compared the POST that Firefox did with the POST that LWP did and there are no differences in the body of the message just the form fields NO difference in cookies {Dreamhost puts the csrf cookie in later... } So I checked all the headers. Every one I send FF sends. But FF sends, additionally httpVersion, host, User-Agent [FF sends "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0, I just send Mozilla/5.0'), Acccept... , Accept-Language, Accept-Encoding, Content-type, Content-Length [LWP sent 'content-length' => 0, DNT, Connection, and Upgrade-Insecure-Requests.

      Do any of those sound like show stoppers for a picky server-login-CGI? I guess it must be one of those, because the cookie and form data is the same, so it can only be the headers. {even if it were a js problem, that would show up in differences between when FF sends and what LWP sends-- it looks like their js mostly just formats boxes and stuff like that on their page} I feel like I must be missing something obvious......

        Usually, csrf stands for Csrf when doing HTTP. So likely, you will need that cookie.

        Maybe that cookie gets created by Javascript? Have you tried disabling Javascript in your browser and looked whether the site still works?

Re: Bug in LWP? Missing cookie
by BernieC (Pilgrim) on Aug 05, 2018 at 10:42 UTC

    The problem is solved and I still don't fully understand HTTP::Request::Common. I had written

    $res = $ua->request(POST "https://panel.dreamhost.com/index.cgi", @fields);

    and that was what I have been asking you folks about -- the fields were correct but it wouldn't log in. I looked more carefully at my request and theirs and mine had a content-length of zero and theirs a content-length of 76. Then I noticed that in addition to the form fields it had a "content" of all of the form fields pushed together and HTML encoded. Poring over H::R::C I noticed there is a subtle difference between passing the array of fields and passing a ref to the array of fields. So I made one, very nonintuitive to me!, change in the request:

    $res = $ua->request(POST "https://panel.dreamhost.com/index.cgi", \@fields);

    and it all magically works now! I had been exploring doing the direct POST construction because for other forms I needed to include a file-upload in the Contents. Now I guess I'll use it for everything in preference to $ua->post(). Whew! Thanks for all the patience and advice.

      I am a bit confused but also interested to see how it worked. Do you want to say that: $ua->post("https://panel.dreamhost.com/index.cgi", \@fields); does not work?

        No the other way: just putting in @fields or , as it is in the docs, name=> value, name=>value, ... didn't work. What did work is using the reference: \@fields. They both send the POST variables and values, except: the reference one also includes a 'content' string which is all the variables concatenated and html encoded. That made the difference and *everything* magically worked. I wish I could explain more about what made the difference or why it worked.

        How I found it is that I compared every byte that my browser sent with what my Perl program sent. They were {essentially} identical except that I noticed that the browser had a content-length of 76 {and the data string i mentioned above} and Perl had a content-length of 0. I pored over the docs and blundered across a mention of the content-length stuff in HTTP::Request::Common, tried it and discovered that that made Perl sent the content-string and it all worked. If someone understands this bit of the POST formatting, I'd be happy to better understand what was/is going on. But for now, all I can say is that using the reference works and using the array doesn't.