Login with PHP curl and CSRF token

2019-05-26 13:11发布

I want login from a PHP script to another website but I always get this reply:

403 Error: CSRF token mismatch

I extract the CSRF token from a hidden field on website but it seems it is wrong. This is my code:

$username = "testuser";
$password = "testpass";

$path = "c:\\test\\";
$url="http://itw.me/login";

$field='_csrf';
$html=file_get_contents( $url );

libxml_use_internal_errors( true );
$dom=new DOMDocument;
$dom->validateOnParse=false;
$dom->recover=true;
$dom->formatOutput=false;
$dom->loadHTML( $html );
libxml_clear_errors();
$xpath=new DOMXPath( $dom );
$col=$xpath->query('//input[@name="'.$field.'"]');
foreach( $col as $node ) $csrftoken=$node->getAttribute('value');
echo "-".$csrftoken."-";

$postinfo = "email=".$username."&password=".$password."&_csrf=".$csrftoken;
$cookie_file_path = $path."/cookie.txt";

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
curl_setopt($ch, CURLOPT_COOKIE, "cookiename=0");
curl_setopt($ch, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo);
curl_exec($ch);

curl_setopt($ch, CURLOPT_URL, "http://itw.me");
$html = curl_exec($ch);
print($html);
curl_close($ch);

标签: php curl csrf
3条回答
霸刀☆藐视天下
2楼-- · 2019-05-26 13:24

CSRF token genrated for every session. Read first comment ot yor question (@walkingRed comment) (comment deleted - cURL CSRF Token - this is solution). There solution of your problem.

You should start your session on the another website and after this you can get correct csrf token.

And it's important to using cookies with every request to define that your external request always in the same session.

Example:

You make first request to grab CSRF token. On the external website started new session for your request and generated csrf token.

Then you make anohter request - but without using cookies - for this reuqest started new session again, and again generated new csrf token, for this new session.

查看更多
Lonely孤独者°
3楼-- · 2019-05-26 13:26

You are making your first request with file_get_contents and your second request with cURL.

You've set up a cookie jar for the second request, but not for the first request. Consequently, each of those two requests is starting a new session.

CSRF tokens are stored in the session by the server you are making the request to, so the token you get the first request won't match the token in the session for the second request.

You need to:

  • Use cURL consistantly
  • Use the same cookie jar for both requests
查看更多
Ridiculous、
4楼-- · 2019-05-26 13:40

now it is working!

$username = "user";
$password = "pass";
$url = "http://url.com/login";
$cookie= "c:\\cookies.txt";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_errno($ch)) die(curl_error($ch));
$dom = new DomDocument();
$dom->loadHTML($response);
$tokens = $dom->getElementsByTagName("meta");
for ($i = 0; $i < $tokens->length; $i++)
{
    $meta = $tokens->item($i);
    if($meta->getAttribute('name') == 'csrf-token')
    $token = $meta->getAttribute('content');
}
$postinfo = "email=".$username."&password=".$password."&_csrf=".$token;
echo $token; //debug info
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo);
$html = curl_exec($ch);
    print($html);
if (curl_errno($ch)) print curl_error($ch);
    curl_close($ch);
查看更多
登录 后发表回答