Difference between revisions of "HTTP Post request to a PHP server"

From Second Life Wiki
Jump to navigation Jump to search
m (language tags to <source>)
 
(17 intermediate revisions by 7 users not shown)
Line 1: Line 1:
<div class="boilerplate metadata" id="prod" style="margin: 0 5%; padding: 0 7px 7px 7px; background: #EDF1F1; border: 1px solid #999999; text-align: left;">
{{LSL Header|ml=*}}
The accuracy of this article has been called into question. This can be discussed in the [[{{TALKPAGENAME}}|talk page]].


'''Dispute:''' With the capture of a single message an attacker only needs at most 24 hours to systematically determine the secret MD5 nonce used to authenticate all messages without requiring any interaction with the source or target of the message.
== How to use ==
</div>
Second life allows scripts to make requests to a web site.


== Introduction ==
The command lets you send Post data to PHP.
The format of the HTTP Post is however a bit tricky.


LSL now offer the ability to request HTTP page from any website.
This library lets you call a PHP page and post as many variables in your call as you want.


On top of that I introduce a little checksum/password system to limit potential abuse.


You can use different methods to access your webserver.
== How to use ==
The most obvious is GET, the get method allows any number of parameters.


The syntax is :
'''The second life script'''


http://www.yourwebsite.com/pay.php?user=Corto+Maltese&amount=100
In the beginning of your script you must copy the xrequest function
and also choose a SECRET_NUMBER and a SECRET_STRING.
In SL you should also make sure that the script is not visible to other people than yourself (this is the default access right).


In the example above the page pay.php is requested with 2 parameters param1 and param2.
<source lang="lsl2">
The issue with GET is that if someone manage to sniff or guess your webpage, he could potentially take any webbrowser and type :
integer SECRET_NUMBER=123456789;
string SECRET_STRING="abcdefghi";
key http_request_id;
xrequest(string url, list l)
{
    integer i;
    string body;
    integer len=llGetListLength(l) & 0xFFFE; // make it even
    for (i=0;i<len;i+=2)
    {
        string varname=llList2String(l,i);
        string varvalue=llList2String(l,i + 1);
        if (i>0) body+="&";
        body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
    }
    string hash=llMD5String(body+llEscapeURL(SECRET_STRING),SECRET_NUMBER);
    http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
}
</source>


http://www.yourwebsite.com/pay.php?param1=Joe+Blog&amount=1000000
To make a call to the function you have to provide 2 parameters:


And your web server will have little idea that this request is bogus.
For example:


xrequest("http://www.yourserver.com/your_page.php",["parameter1",123,"parameter2","parameter2 value"]);


This is where my library comes into action.
The first parameter is the address of the webpage which will process your request. I assume, you own a website which supports PHP (about any version).


The LSL library takes every character in your HTTP request and compute a security HashCode.
The second parameter is a list containing the parameters you want to pass to the page.
The library will then add this extra security hash parameter to your request like that:
They will be sent to the page as if they had been type in a WebForm.
The list can be empty [] or contain any number of 'variable name','variable value' pairs.


http://www.yourwebsite.com/pay.php?user=Corto+Maltese&amount=100&hash=edabcc1792b33e7d6055cc4c8e69912c
'''The PHP Page'''


When the server receive the request, it will be able to check that the hash provided is correct.
The php page must contains the function below, if you're a PHP wiz, you also include it inside another file.
If the request was tempered, the hash will not be correct, the server will therefore ignore the request and not allow Job Blog to pretend he has paid L$ 1,000,000.


Also the library uses a POST method, the POST method is not very different from GET but allow slightly more input parameters than GET, The POST method is also a bit more secure as the parameters do not appears in the cache statistics or similar tools.
Note that the page must be modified to contain your own SECRET_NUMBER.
Your page will then use the function checkHash() to make sure the correct password was used.
If the password is wrong, the page won't run any further.


== Syntax ==
If the password is right you can then read the content of the parameters using a simple $_POST["parameter_name"]


The main LSL function is called xrequest
<source lang="php">
 
<?php
  xrequest(string Url, List Parameters)
  // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
 
   function llEscapeURL($s)
Url :
  is the address of your webpage. for example "http://www.yoursite.com/sl.php"
 
Parameters :
  is a list of string, the list must be set in pairs using this format:
  [variable_name_1, variable_value_1, variable_name_2, variable_value_2, ...]
 
 
In the example below the script request a page using the parameters a=1, b=2 and c=3.
<code>
   default
   {
   {
      touch_start(integer total_number)
    $s=str_replace(
       {
       array(" ","+","-",".","_"),
          xrequest("http://www.yoursite.com/sl.php",["a","1","b","2","c","3"]);
      array("%20","%20","%2D","%2E","%5F"),
      }
       urlencode($s));
     
    return $s;
      http_response(key request_id, integer status, list metadata, string body)
   }   
       {
          if (request_id == http_request_id)
          {
              llSetText(body, <0,0,1>, 1);
          }
      }
     
   }
</code>
 
Here is the code of the xrequest function.
Note that you should change the SECRET_NUMBER to any number of your choice but preferably something rather large and random up to 2,000,000,000.
 
<code>
   integer SECRET_NUMBER=123456789;
    
    
   xrequest(string url, list l)
   // this my main SL page XML-RPC page
  function checkHash()
   {
   {
      integer i;
    global $body;
      integer len=llGetListLength(l) & 0xFFFE; // makes the list count even
    $hash=$_GET["hash"];
      string body;
    $body="";
 
    $cpt=0;
    for (i=0;i<len;i+=2)
    $SECRET_NUMBER=123456789;
    {
    $SECRET_STRING="abcdefghi";
          string varname=llList2String(l,i);
 
          string varvalue=llList2String(l,i + 1);
    foreach ($_POST as $name => $value) {
          if (i>0) body+="&";
      if ($cpt++>0) $body.="&";
          body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
      if (get_magic_quotes_gpc()) {
        // $name = stripslashes($name); not a good idea though
        $value = stripslashes($value);
        $_POST[$name]=$value;
       }
       }
       string hash=llMD5String(body,SECRET_NUMBER);
       $body.=llEscapeURL($name)."=".llEscapeURL($value);
       http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
    }
    $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
    if ($hash!=$calcHash)
    {
       sleep(2); // slow down the requests
      echo "result=FAIL\nMSG=Invalid request.";  
      die;
    }
   }
   }
</code>


On the server side here is the PHP function which will allow your server to check the securty hash:
  checkHash();
  // You can use the parameters here by simply using $_POST["parameter_name"]
  echo "OK";
?>
</source>


<code>
I hope it helps.
  <?php
Don't hesitate to ask any question to Corto Maltese or improve this page.
  // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
  function llEscapeURL($s)
  {
  return str_replace(
  array("+","-",".","_"),
  array("%20","%2D","%2E","%5F"),
  urlencode($s));
  } 
 
  // this my main SL page XML-RPC page
  function checkHash()
  {
  global $body;
  $hash=$_GET["hash"];
  $body="";
  $cpt=0;
  $SECRET_NUMBER=123456789;
  foreach ($_POST as $name => $value) {
  if ($cpt++>0) $body.="&";
  $body.=llEscapeURL($name)."=".llEscapeURL($value);
  }
  $calcHash=md5($body.':'.$SECRET_NUMBER);
  if ($hash!=$calcHash)
  {
  sleep(2); // slow down the requests
  echo "result=FAIL\nMSG=Invalid hash"; + $body="";
  die;
  }
  }
 
 
  checkHash();
  // You can use the parameters here by simply using $_POST["parameter_name"]
  echo "OK";
  ?>
</code>


This library could be improved, to treat output parameter too.
It doesn't do anything in this area yet.


[[Category:LSL Library|Secure HTTP Post]]
{{LSLC|Library}}

Latest revision as of 20:27, 24 January 2015

How to use

Second life allows scripts to make requests to a web site.

The command lets you send Post data to PHP. The format of the HTTP Post is however a bit tricky.

This library lets you call a PHP page and post as many variables in your call as you want.

On top of that I introduce a little checksum/password system to limit potential abuse.

How to use

The second life script

In the beginning of your script you must copy the xrequest function and also choose a SECRET_NUMBER and a SECRET_STRING. In SL you should also make sure that the script is not visible to other people than yourself (this is the default access right).

 integer SECRET_NUMBER=123456789;
 string SECRET_STRING="abcdefghi";
 key http_request_id;
 
xrequest(string url, list l)
{
    integer i;
    string body;
    integer len=llGetListLength(l) & 0xFFFE; // make it even
    for (i=0;i<len;i+=2)
    {
        string varname=llList2String(l,i);
        string varvalue=llList2String(l,i + 1);
        if (i>0) body+="&";
        body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
    }
    string hash=llMD5String(body+llEscapeURL(SECRET_STRING),SECRET_NUMBER);
    http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
}

To make a call to the function you have to provide 2 parameters:

For example:

xrequest("http://www.yourserver.com/your_page.php",["parameter1",123,"parameter2","parameter2 value"]);

The first parameter is the address of the webpage which will process your request. I assume, you own a website which supports PHP (about any version).

The second parameter is a list containing the parameters you want to pass to the page. They will be sent to the page as if they had been type in a WebForm. The list can be empty [] or contain any number of 'variable name','variable value' pairs.

The PHP Page

The php page must contains the function below, if you're a PHP wiz, you also include it inside another file.

Note that the page must be modified to contain your own SECRET_NUMBER. Your page will then use the function checkHash() to make sure the correct password was used. If the password is wrong, the page won't run any further.

If the password is right you can then read the content of the parameters using a simple $_POST["parameter_name"]

<?php
  // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
  function llEscapeURL($s)
  {
    $s=str_replace(
      array(" ","+","-",".","_"),
      array("%20","%20","%2D","%2E","%5F"),
      urlencode($s));
    return $s;
  }   
  
  // this my main SL page XML-RPC page
  function checkHash()
  {
    global $body;
    $hash=$_GET["hash"];
    $body="";
    $cpt=0;
    $SECRET_NUMBER=123456789;
    $SECRET_STRING="abcdefghi";

    foreach ($_POST as $name => $value) {
      if ($cpt++>0) $body.="&";
      if (get_magic_quotes_gpc()) {
        // $name = stripslashes($name); not a good idea though 
        $value = stripslashes($value);
        $_POST[$name]=$value;
      }
      $body.=llEscapeURL($name)."=".llEscapeURL($value);
    }
    $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
    if ($hash!=$calcHash) 
    {
      sleep(2); // slow down the requests
      echo "result=FAIL\nMSG=Invalid request."; 
      die;
    }
  }

  checkHash();
  // You can use the parameters here by simply using $_POST["parameter_name"] 
  echo "OK";
?>

I hope it helps. Don't hesitate to ask any question to Corto Maltese or improve this page.