Posting and executing a string as PHP? - php

I'm building an application that's self-hosted, and I'd like to have some form of licensing to minimize fraudulent downloads/distribution.
Of course, I'm well aware that being self-hosted someone could simply rip out all license features from the source-code, but the con's of using a compiler like Zend Guard or ionCube far outweigh the pro's in my opinion - nonetheless I'd like to have some basic form of license security.
What I originally had in mind to do was: user logs in with license on app -> app posts license to my server -> server sends a response via a HTTP GET request -> app evaluates response, and if license is valid sets a value in a session variable (A), if invalid returns to login screen with an error.
The problem with this is, the evaluation of response/session setting is readily available in a application file, so if the user knows a little PHP and checks in on that source code, they'll realize all they'll need to do is set a session themselves with a particular $_SESSION['_valid_license'] value, and they'll be good to go.
What I was considering doing to make it a little less easy was (if possible) to post PHP back as a response, and then have the application file execute it, for example:
My original code:
$response = $_GET['response'];
if($response == "fjdkuf9") {
start_session();
$_SESSION['_valid_license'] = "YES";
header("Location:" . $rp . "/admin/");
} else {
header("Location:" . $rp . "/login/?err=1");
}
My new concept:
$response = $_POST['response'];
str_replace("\", "", $response);
With the following being posted as response:
start_session();
\$_SESSION[\'_valid_license\'] = \"YES\";
header(\"Location:\" . \$rp . \"/admin/\");
Would that execute $response as actual PHP code after str_replace()? If possible, this would be great, as it would mean evaluation would be done on my server rather than within the self-hosted app itself.

Your second solution is just as insecure as the first. here's what I would do:
Your application POSTS to your server a serial number or some other identifying information.
Your server validates the serial number against the user's account or whatever and returns a unique response.
If that response is successful, you allow the user to continue. Obviously you'd want to implement some sort of caching mechanism here so you're not having to hit you server on every page view.
Putting the responsibility of validation on your server instead of self-hosted code is much more secure. You would need to encrypt the data that is sent BTW so that someone couldn't simply emulate the success response, but you get the idea.

Related

CronJob Friendly PHP redirect

I'm struggling with a PHP script that is activated by a Cronjob and includes a redirect.
The script finds records in my database, sends an email as appropriate and then redirects to a compiled URL so the details of the records can be imported into an external system.
The email part works fine via a Cronjob, the redirect does not, I understand that this is because Cronjobs do not operate within the browser but I'm not sure what is the best alternative method of redirecting to the URL.
Simplified code below:
<?php
// Connect to DB
require_once($_SERVER['DOCUMENT_ROOT']."/admin/inc/dbconnect.php");
// Check DB for quotes that have not been sent to this client
$query_quotes = "SELECT * FROM quotes WHERE sent_client = 0 LIMIT 1";
$view_request = mysqli_query($GLOBALS['db_connect'], $query_quotes);
// Send to external system and email customer with quote
while ($quotes = mysqli_fetch_array($view_request)){
$Body = "Email Content";
// Send email via Swift Mailer
// Send quote information to third party system via URL redirect
header('Location: http://exampleurl/?FirstName='.rawurlencode($quotes['name']).'&businessName='.rawurlencode($quotes['company_name']).'.');
}
?>
It is as you said, you are not in a web-environment, so there is no browser to act on the Location: redirect. That doens't mean you can't pass information to a webpage - you just can't redirect to it - you call to it, and get information back - the info you get back might not be much - just 'OK, I got it' may well be more than enough. It might be as simple as
$url = "http://exampleurl/?FirstName=" .
rawurlencode($quotes['name']) . '&businessName=' .
rawurlencode($quotes['company_name'])
$response = file_get_contents($url);
And the response might be as simple as 200 OK (though if there is no response apart from just 'OK', officially according to the HTTP specs, you'd return 204 No Content, but that is a very small thing).
Better still would be to use a proper HTTP calling function that dcan deal with potential issues like redirections and make life a little easier - something like the Guzzle library for example, but again, if file_get_contents works for you with a URL, that may be enough, at least while you are testing the basics.

Sharing access restrictions between php and javascript

The actual questions
How to "map" access restrictions so it can be used from php and javasript?
What kind of method should I use to share access restrictions / rules between php and javascript?
Explanation
I have created a RESTful backend using php which will use context-aware access control to limit data access and modification. For example, person can modify address information that belongs to him and can view (but not modify) address information of all other persons who are in the same groups. And of course, group admin can modify address details of all the persons in that group.
Now, php side is quite "simple" as that is all just a bunch of checks. Javascript side is also quite "simple" as that as well is just a bunch of checks. The real issue here is how to make those checks come from the same place?
Javascript uses checks to show/hide edit/save buttons.
PHP uses checks to make the actual changes.
and yes,
I know this would be much more simpler situation if I ran javascript (NodeJS or the like) on server, but the backend has already been made and changing ways at this point would cause major setbacks.
Maybe someone has already deviced a method to model access checks in "passive" way, then just use some sort of "compiler" to run the actual checks?
Edit:
Im case it helps to mention, the front-end (js) part is built with AngularJS...
Edit2
This is some pseudo-code to clarify what I think I am searching for, but am not at all certain that this is possible in large scale. On the plus side, all access restrictions would be in single place and easy to amend if needed. On the darkside, I would have to write AccessCheck and canAct functions in both languages, or come up with a way to JIT compile some pseudo code to javascript and php :)
AccessRestrictions = {
Address: {
View: [
OWNER, MEMBER_OF_OWNER_PRIMARY_GROUP
],
Edit: [
OWNER, ADMIN_OF_OWNER_PRIMARY_GROUP
]
}
}
AccessCheck = {
OWNER: function(Owner) {
return Session.Person.Id == Owner.Id;
},
MEMBER_OF_OWNER_PRIMARY_GROUP: function(Owner) {
return Session.Person.inGroup(Owner.PrimaryGroup)
}
}
canAct('Owner', 'Address', 'View') {
var result;
AccessRestrictions.Address.View.map(function(role) {
return AccessCheck[role](Owner);
});
}
First things first.
You can't "run JavaScript on the server" because Javascript is always run on the client, at the same way PHP is always run on the server and never on the client.
Next, here's my idea.
Define a small library of functions you need to perform the checks. This can be as simple as a single function that returns a boolean or whatever format for your permissions. Make sure that the returned value is meaningful for both PHP and Javascript (this means, return JSON strings more often than not)
In your main PHP scripts, include the library when you need to check permissions and use the function(s) you defined to determine if the user is allowed.
Your front-end is the one that requires the most updates: when you need to determine user's permission, fire an AJAX request to your server (you may need to write a new script similar to #2 to handle AJAX requests if your current script isn't flexible enough) which will simply reuse your permissions library. Since the return values are in a format that's easily readable to JavaScript, when you get the response you'll be able to check what to show to the user
There are some solutions to this problem. I assume you store session variables, like the name of the authorized user in the PHP's session. Let's assume all you need to share is the $authenticated_user variable. I assume i'ts just a string, but it can also be an array with permissions etc.
If the $authenticated_user is known before loading the AngularJS app you may prepare a small PHP file whish mimics a JS file like this:
config.js.php:
<?php
session_start();
$authenticated_user = $_SESSION['authenticated_user'];
echo "var authenticated_user = '$authenticated_user';";
?>
If you include it in the header of your application it will tell you who is logged in on the server side. The client side will just see this JS code:
var authenticated_user = 'johndoe';
You may also load this file with ajax, or even better JSONP if you wrap it in a function:
<?php
session_start();
$authenticated_user = $_SESSION['authenticated_user'];
echo <<<EOD;
function set_authenticated_user() {
window.authenticated_user = '$authenticated_user';
}
EOD;
?>

Facebook GraphAPI via another webpage php?

First: please forgive me - Im a bit of a novice as some of this...
I have a working test site which is running the php facebook SDK to perform some simple graphAPI requests successfully. Namely read a group's feed, which the user is a member of, and process this and display it back on a webpage.
This all works fine, the problem I have encountered is when trying to perform the same request via a php curl POST to another webpage (on the same domain). It seems that the SDK does not carry the expected session to another page when a post request is formed (see "AUTH ERROR2" in code)...this works fine when the following file is included via a "require_once" but not when a curl is made.
I would much rather do a "curl" as Im finding when a "require_once" is done from a page in a different directory level, Im getting php errors of the page not being found - which is expected.
I may just be tackling this problem all wrong...there may be a simpler way to make sure when files are includes, their correct directly level remains intact, or there may be a way to send over the currently authorised facebook sdk session via a curl post. All of which I have tried to no avail, and I would really appreciate any help or advise on this.
Thank you for your time.
//readGroupPosts.inc.php
function readGroupPosts($postVars)
{
//$access_token = $postVars[0];
// ^-- I'm presuming I need this? I have been experimenting appending it to
// the graphAPI request to no success...
$groupID = $postVars[1];
$limit = $postVars[2];
require_once("authFb.inc.php"); //link to the facebookSDK & other stuff
if ($user) {
try {
$groupFeed = $facebook->api("/$groupID/feed?limit=$limit"); //limit=0 returns all;
$groupFeed = $groupFeed['data']; //removes first tier of array for simpler access
$postArray;
for($i=0; $i<count($groupFeed); $i++)
{
$postArray[$i] = array($groupFeed[$i]['from']['name'], $groupFeed[$i]['message'], $groupFeed[$i]['updated_time'], count($groupFeed[$i]['likes']['data']));
}
return $postArray;
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
return "AUTH ERROR1"; //for testing..
}
}
else
{
return "AUTH ERROR2"; //no user is authenticated i.e. $user == null..
}
}
I would much rather do a "curl" as Im finding when a "require_once" is done from a page in a different directory level, Im getting php errors of the page not being found - which is expected.
I may just be tackling this problem all wrong...
Definitively.
Using cURL as a “workaround” just because you’re not able to find your way around your server’s file system is an outrageous idea. Don’t do it. Stop even thinking about it. Now.
there may be a simpler way to make sure when files are includes, their correct directly level remains intact
Yes – for example, to use absolute paths instead of relative ones. Prefixing the path with the value of $_SERVER['DOCUMENT_ROOT'] for example – that way, once you’ve given the path correctly in respect to this “base path”, it does not matter where you’re requiring the file from, because an absolute path is the same no matter from where you look at it.
(And since this is not a Facebook-related problem at all, but just concerns basics of PHP and server-side programming, I’ll edit the tags.)

PHP: help secure / filter ajax calls

I am trying to find a way to filter ajax calls in order to add a fine layer of security to my applications. Does the code bellow make any sense?
function is_ajax(){//Help Secure Ajax Calls
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest') return;
else die;//no ajax
}
My dream is only let a file inside my server (htm or php) to access another php file via ajax.
I wonder if the code bellow would not do better:
if(strpos($_SERVER['REQUEST_URI'],'http://')) die;//Help Secure From URL Include Attacks
Thanks.
Since the AJAX call is always made from the browser, the request is not coming from your own server, but the client machine. Even if you set custom headers, these can easily be manipulated on the client side.
If your goal is to only allow your own scripts to access the script containing the ajax content, I'd recommend generating a token string that is only valid for a certain requested url and a specified time.
Quick and dirty example:
Script requesting the AJAX resource:
$secret ="ABC1232";
$item = array(
"time"=>time(),
"token_id"=>"<page_url>"
);
$signed = base64_encode(hash_hmac("sha256",json_encode($item),$secret));
$item = base64_encode(json_encode($item));
$ajax_url = "myscript.php?signed=$signed&item=$item";
AJAX Resource, check the token is valid
$item = json_decode(base64_decode($_REQUEST["item"]));
$timeout = 3600;
if($item->time < (time()-$timeout)){
die("Invalid token - timeout");
}
if($item->token_id !== "<page_url>"){
die("Invalid token - page url");
}
$secret ="ABC1232";
$valid = ($_REQUEST["signed"] === base64_encode(hash_hmac("sha256",json_encode($item),$secret));
if(!$valid){
die("Invalid token");
}
Your Ajax is as secure as your application layer. Ajax is just client side code accessing server side code. There is probably no way in securing it the way you want since anyone can emulate Ajax calls from within any language by just modifying the request headers. One more thing most ajaxified frameworks do include HTTP_X_REQUESTED_WITH but it's not 100% reliable.
Just secure your server code and your good to go. If you really want to at least let your server code know that it's receiving an ajax call, use a parameter on the request.
Assume that anything that can be requested by AJAX will also be accessed directly and you will be in a much safer place. You really should consider why you would only ever want something to be accessed via AJAX in the first place. The HTTP_X_REQUESTED_WITH header is unreliable and easily spoofed so it provides no real security anyway.
I think for a little more security you could decode your secret string after you encode it. then echo than decoded string in php and then copy it.
then on the the $valid variable
$valid = (base64_decode($_REQUEST["signed"]) === "blahblahblah that you copied from php");

How would I go about writing a simple PHP bot?

How would I go about writing a simple PHP bot that could login in and recieve all the cookies sent by the server? ... and then send them back when required?
Any suggestions would be appreciated.
First of all, your question is too broad and lacking in detail to really answer effectively. That said, I'll give it a try.
Not knowing what exactly you mean by "log in", I assume you want the script to be able to post some data to another script via an HTTP request. The CURL Library is good for that. It is able to post data and handle cookies.
Edit: Got ninja'd by Zed. ;)
If for some reason you cannot use the curl extension on your server (extension not installed), you can use a class such as Snoopy which will still allow you to either use the curl binaries or use sockets to retrieve the information.
Snoopy handles cookies.
As for the writing the bot itself, it's just a question of sending the proper requests. Here is an example with Snoopy:
$snoopy = new Snoopy;
// The following needs to reflect the form configuration of the site
$login = array('usr' => 'hi', 'pwd' => 'hello');
if($snoopy->submit('http://example.com/login', $login) === false) {
// output the response code
die($snoopy->response_code . ':' . $snoopy->error);
}
//Request succeeded (doesn't mean we are logged in)
// output the results
echo $snoopy->results;
// Check the results to see if you are logged in and
// Continue using $snoopy.
// It will pass the proper cookies for the next requests.
With the help of the cURL library?

Categories