Execute Javascript in PHP using v8js on Ubuntu 18.04

Let’s say you want to log into a webpage using PHP.

You post the login credentials to the login form, and expect to get a cookie back.

But you get this back instead:

<html><title>You are being redirected…</title>
<noscript>Javascript is required. Please enable javascript before you are allowed to see this page.</noscript>
<script>var s={},u,c,U,r,i,l=0,a,e=eval,w=String.fromCharCode,sucuri_cloudproxy_js=,S=‘az0nNXZYOScuc3Vic3RyKDMsIDEpICsiOSIgKyAiMHN1Y3VyIi5jaGFyQXQoMCkrJ1lhJy5zbGljZSgxLDIpKydhWzEnLmNoYXJBdCgyKSsiMHN1Ii5zbGljZSgwLDEpICsgJ2YnICsgICI2c2VjIi5zdWJzdHIoMCwxKSArICI1Ii5zbGljZSgwLDEpICsgJzInICsgICdhWjQnLmNoYXJBdCgyKSsnYycgKyAgICcnICsnJysiNCIgKyAiN3N1Ii5zbGljZSgwLDEpICsgIiIgKyIwc3UiLnNsaWNlKDAsMSkgKyAiIiArJ3RAOCcuY2hhckF0KDIpKyIyIi5zbGljZSgwLDEpICsgImNzdWN1ciIuY2hhckF0KDApKyd0NGYnLmNoYXJBdCgyKSsnMScgKyAgJ2InICsgICJiIiArICdsPzgnLmNoYXJBdCgyKSsnM2InLnNsaWNlKDEsMikrJ1RsWmInLnN1YnN0cigzLCAxKSArJ0E2Jy5zbGljZSgxLDIpKyJmbiIuY2hhckF0KDApICsgIiIgKyJhc3VjdXIiLmNoYXJBdCgwKSsgJycgKyJhc3VjdXIiLmNoYXJBdCgwKSsiOHciLmNoYXJBdCgwKSArICczYk8zJy5zdWJzdHIoMywgMSkgKyIiICsiYmkiLmNoYXJBdCgwKSArICcnO2RvY3VtZW50LmNvb2tpZT0ncycrJ3UnKydjJysnJysndXN1Y3VyJy5jaGFyQXQoMCkrICdyJysnJysnc3VjdWknLmNoYXJBdCg0KSsgJ3NfJy5jaGFyQXQoMSkrJ2NzJy5jaGFyQXQoMCkrJ3N1Y3VybCcuY2hhckF0KDUpICsgJ28nKyd1JysnZCcrJycrJ3BzdWN1cicuY2hhckF0KDApKyAncnN1Y3VyaScuY2hhckF0KDApICsgJ29zdScuY2hhckF0KDApICsnc3VjdXgnLmNoYXJBdCg0KSsgJ3lzdScuY2hhckF0KDApICsnXycrJycrJ3VzdWN1cmknLmNoYXJBdCgwKSArICd1JysnJysnaXMnLmNoYXJBdCgwKSsnZCcrJ19zdWN1cmknLmNoYXJBdCgwKSArICdzdWEnLmNoYXJBdCgyKSsnOXMnLmNoYXJBdCgwKSsnc3VjdWEnLmNoYXJBdCg0KSsgJ3NiJy5jaGFyQXQoMSkrJzgnLmNoYXJBdCgwKSsnc3VjdXI3Jy5jaGFyQXQoNSkgKyAnYicrJycrJ3N1YScuY2hhckF0KDIpKydmJysnJysiPSIgKyBrICsgJztwYXRoPS87bWF4LWFnZT04NjQwMCc7IGxvY2F0aW9uLnJlbG9hZCgpOw==’;L=S.length;U=0;r=;var A=‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’;for(u=0;u<64;u++){s[A.charAt(u)]=u;}for(i=0;i<L;i++){c=s[S.charAt(i)];U=(U<<6)+c;l+=6;while(l>=8){((a=(U>>>(l-=8))&0xff)||(i<(L2)))&&(r+=w(a));}}e(r);</script></html>
view raw need-js.html hosted with ❤ by GitHub

Hmm. Well, the message says we need to enable Javascript. So let’s do what it says!

Following the instructions here, we can install the V8 Javascript engine, and v8js, a PHP interface to V8.

Then we extract the text between the <script/&#x3E tags, and feed it to V8.

By callling V8Js::executeString, we can run the Javascript we got back, then print whatever cookie it’s eventually generating. All we need to do is stub out `document` and `location.reload()`. We can find this either by running the code and watching the error messages, or base64-decoding the above string to get an idea of what it does.

An example PHP script might look like this:

<?php declare(strict_types=1);
// this comes directly from <script></script> tags on page fetch.
$js = “var s={},u,c,U,r,i,l=0,a,e=eval,w=String.fromCharCode,sucuri_cloudproxy_js=”,S=’az0nNXZYOScuc3Vic3RyKDMsIDEpICsiOSIgKyAiMHN1Y3VyIi5jaGFyQXQoMCkrJ1lhJy5zbGljZSgxLDIpKydhWzEnLmNoYXJBdCgyKSsiMHN1Ii5zbGljZSgwLDEpICsgJ2YnICsgICI2c2VjIi5zdWJzdHIoMCwxKSArICI1Ii5zbGljZSgwLDEpICsgJzInICsgICdhWjQnLmNoYXJBdCgyKSsnYycgKyAgICcnICsnJysiNCIgKyAiN3N1Ii5zbGljZSgwLDEpICsgIiIgKyIwc3UiLnNsaWNlKDAsMSkgKyAiIiArJ3RAOCcuY2hhckF0KDIpKyIyIi5zbGljZSgwLDEpICsgImNzdWN1ciIuY2hhckF0KDApKyd0NGYnLmNoYXJBdCgyKSsnMScgKyAgJ2InICsgICJiIiArICdsPzgnLmNoYXJBdCgyKSsnM2InLnNsaWNlKDEsMikrJ1RsWmInLnN1YnN0cigzLCAxKSArJ0E2Jy5zbGljZSgxLDIpKyJmbiIuY2hhckF0KDApICsgIiIgKyJhc3VjdXIiLmNoYXJBdCgwKSsgJycgKyJhc3VjdXIiLmNoYXJBdCgwKSsiOHciLmNoYXJBdCgwKSArICczYk8zJy5zdWJzdHIoMywgMSkgKyIiICsiYmkiLmNoYXJBdCgwKSArICcnO2RvY3VtZW50LmNvb2tpZT0ncycrJ3UnKydjJysnJysndXN1Y3VyJy5jaGFyQXQoMCkrICdyJysnJysnc3VjdWknLmNoYXJBdCg0KSsgJ3NfJy5jaGFyQXQoMSkrJ2NzJy5jaGFyQXQoMCkrJ3N1Y3VybCcuY2hhckF0KDUpICsgJ28nKyd1JysnZCcrJycrJ3BzdWN1cicuY2hhckF0KDApKyAncnN1Y3VyaScuY2hhckF0KDApICsgJ29zdScuY2hhckF0KDApICsnc3VjdXgnLmNoYXJBdCg0KSsgJ3lzdScuY2hhckF0KDApICsnXycrJycrJ3VzdWN1cmknLmNoYXJBdCgwKSArICd1JysnJysnaXMnLmNoYXJBdCgwKSsnZCcrJ19zdWN1cmknLmNoYXJBdCgwKSArICdzdWEnLmNoYXJBdCgyKSsnOXMnLmNoYXJBdCgwKSsnc3VjdWEnLmNoYXJBdCg0KSsgJ3NiJy5jaGFyQXQoMSkrJzgnLmNoYXJBdCgwKSsnc3VjdXI3Jy5jaGFyQXQoNSkgKyAnYicrJycrJ3N1YScuY2hhckF0KDIpKydmJysnJysiPSIgKyBrICsgJztwYXRoPS87bWF4LWFnZT04NjQwMCc7IGxvY2F0aW9uLnJlbG9hZCgpOw==’;L=S.length;U=0;r=”;var A=’ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\/’;for(u=0;u<64;u++){s[A.charAt(u)]=u;}for(i=0;i<L;i++){c=s[S.charAt(i)];U=(U<<6)+c;l+=6;while(l>=8){((a=(U>>>(l-=8))&0xff)||(i<(L-2)))&&(r+=w(a));}}e(r);”;
// need to stub out document for .cookie write, and location for .reload.
// thats it! document.cookie will print/return when we execute.
$script = <<<EOL
var document = {}, location = { reload: function(){} };
{$js}
document.cookie;
EOL;
try {
$v8 = new V8Js();
$cookie = $v8->executeString($script);
// do something with $cookie
echo $cookie;
}
catch (V8JsException $ex) {
// testing, maybe throw? tbd.
echo “JS EXCEPTION!!\n\n”;
echo $ex->getJsTrace().“\n\n”.$ex->getJsSourceLine();
}

view raw v8js-test.php hosted with ❤ by GitHub

On running the example script, you would see an output like this:

sucuri_cloudproxy_uuid_a9ab87baf=990a10f6524c47082cf1bb8bb6faa83b;path=/;max-age=86400

And that’s it! By passing this cookie, we will be considered logged-in.