I'm working on a php installer for a web application / software.
The installer need a valid license ID to finish the installation (for example: "aDs34Nsi9sa").
To check if the license ID is valid i have a php script on my main domain that check my db and return 1 if the licenseID exist and is active or 0 otherwise. This file should be called like this:
https://www.domain.com/check.php?id=aDs34Nsi9sa
So i'm wondering if is correct to use file_get_contents() to check the license ID via PHP..
$check = file_get_contents("https://www.domain.com/check.php?id=$license_field");
if( $check == 1 ) {} // finish installation
else {} // print error msg
Is this way correct and secure?
Of course, you need to properly URL-encode data before injecting it into a URL. And it's up to your remote server to detect brute force attacks. Other than that:
Your check assumes that allow_url_fopen is enabled and PHP has SSL support. Make sure you explain that in the requisites and get ready for support enquiries and workaround coding.
Data sent through SSL should remain private enough.
And, well, it isn't particularly difficult to crack. Malicious users just need to impersonate the remote site.
Related
I am using Birt 4.5 and PHP/MYSQL.
I am able to run birt reports with php. I have enabled tomcat and copied 'birt-runtime-4_5_0/WebViewerExample' to tomcat/webapps and renamed it to birt.
So I can run birt viewer with php;
<?php
$fname = "report/test.rptdesign&__showtitle=false";
$dest = "http://localhost:8081/birt/frameset?__report=";
$dest .= $fname;
header("Location: $dest" );
?>
Above code is working fine. But report connectstring already saved in test.rptdesign file.
I want to remove DB login credentials from test.rptdesign file and assign it while report open with PHP.
I have tried with report parameters. But all the parameters will display on browser address-bar.
Is there any secure way to do this? This is very important when we need to change the database location. It is very hard to change the data source of each and every .rptdesign file.
Thank You,
Supun
I don't believe using report parameters to handle a database connection is the right way. In addition to the address-bar problem you mentionned, it will cause unexpected issues: for example you won't be able to use this database to feed the dataset of another report parameter.
With Tomcat the best approach is to externalize the database connection in a connection pool: easy, robust, and reports might run significantly faster.
Alternatively the datasource can be externalized in a BIRT library (.rptlibrary) and shared across all report-designs: thus only the library needs to be updated when the database location is changing.
I agree with Dominique that sending the database parameters via the query is most likely an inappropriate solution - and you've not given any explanation of whether this is a requirement of the system.
But it is quite trivial to proxy the request via PHP and decorate the URL with the required parameters, something like...
<?php
$_GET['__showtitle']=$_GET['__showtitle'] ? $_GET['__showtitle'] : 'false';
$_GET['__report']=$fname; // NB this should be NULL in your code!
$_GET['dbuser']='a_db_user';
$_GET['passwd']='s3cr3t';
$qry=http_build_query($_GET);
$url="http://localhost:8081/birt/frameset?" . $qry;
// if its simply returning HTML, then just....
$fin=fopen($url, 'r');
while ($l=fgets($fin)) {
print $l;
}
exit;
If the returned content contains relative links the you'll need to rewrite the output stream. If the content type is unusual or you want to project other headers (e.g. for caching) to the browser, then you'll need to use Curl, capture the headers and relay them.
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;
?>
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.
I need ways to securize my own php administration panel. I read here about some:
A simple authentication using apache2.conf
Using ssl to send encrypted passwords
Host the tools on a completely seperate domain
A proper robots.txt should also be used
Using chmod 777 when i want to use and do a chmod 000 when i finish
But eachone has problems.
If i want to do it with apache2.conf, i must use ssl too. Only with this is it secured?
If i upload the tools in other domain and use robots.txt to "hide" them, could someone find them?
Using chmod is like "non-professional"
What do you use to secure your administration panel?
But eachone has problems. If i want to do it with apache2.conf, i
must use ssl too. Only with this is it secured?
Sort of. If you don't use ssl, passwords are sent over the net unencrypted if someone is listening in on your communication, they will know the password. That being said, it is usually impossible for someone to listen to your communication with the server unless one of the participating parties has already been compromised or you are communicating through an unsafe medium like unencrypted public wlan.
If i upload the tools in other domain and use robots.txt to "hide"
them, could someone find them?
Yes, if they guess the URL. robots.txt just hides you from search engines, but it does not work for protecting your admin panel from unwanted access.
Using chmod is like "non-professional"
And unsafe. It means that whenever you are working on the admin panel, everyone else also can. Don't do this.
What do you use?
Access control with Apache (either through the global config or an .htaccess file) with SSL. It may be a bit painful to set up at first, but for the given problem, it really is the only choice that makes any sense.
What you could do is use a php class that requires you to log in or sign up to your Website. You can find plenty from a quick Google.
Then, you should make an API on your Website that only sends data back if you're authenticated. Here's an example that would read data from a MySQL database:
<?php
require_once $_SERVER["DOCUMENT_ROOT"] . "/includes/accounts.class.php"; //Change this to the path to your authentication script
header("Content-Type: application/json"); //Important if you're using json
$account = new Accounts(); //A fictional Accounts class is opened
$json = array();
if (!$account->authenticated or $account->rights != "administrator") { //Ask the class if the user is not an admin
$json = array(
"error" => "Not an administrator"
);
} else {
$query = mysqli_query($link, "SELECT * FROM example"); //Assuming you use mysqli and there's a table called example
if (!$query or mysqli_num_rows($query) < 1) {
$json = array(
"error" => "Query returned no results"
);
} else {
while ($row = mysqli_fetch_array($query)) { //Read the data from the table
$json[] = $row;
}
}
}
echo json_encode($json); //Send the data as a json string
Remember that the above code is only an example of how you would do this sort of script. You'll need to modify it to work with the class and database you are using.
Now you can make your own program for your own internal use that logs in to and queries data from your API. This could be a Website running on an internal server, a Windows program or a smartphone app. All it would need to do is fill in the form on the log in Webpage, then send a HTTP request to the script above and decode the json result.
Is it OK to give full authorization to any request coming from the command line?
My idea was to make this check:
if(isset($_SERVER['argc']) AND $_SERVER['argc']>=2) {
// it must be the admin, give him full authorization, no further checks needed.
} else {
// normal web request, authentication needed.
}
Does this make sense?
Anything else I should know before I start using the command line to execute my php scripts?
It's only safe if the server has only one user. Otherwise you need to either:
Check for the correct user ID in the script
Make the script only executable for that user
(This is assuming a Linux server)
The command line is not a very good place from which to control your web application: your app displays HTML output, which is not much good to a human looking at a console (not to mention the JavaScript that won't work etc).
You could arrange for different output to be generated when running from the command line, but as a practical matter: why bother with all this? Why not have the administrator be authenticated from the web just like any other user?
If you want to have a special backdoor built into your app anyway though, I would suggest something like this (which is web-based):
define('ADMIN_BACKDOOR', true); // comment out to disable
$is_admin = defined('ADMIN_BACKDOOR') && $_SERVER['REMOTE_ADDR'] == '127.0.0.1';
This is IMO next to impossible to exploit, and it allows you admin access from a natural environment (the browser).