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.
Related
I would like to make a PHP website, where employees can log in/out themselves and these logs will count as a time when they started and ended their working day. I would like to allow them to do that only on their work computer and not for example on their phone while they are still on the way, but they want to avoid "being late".
So I'm struggling with a few ideas, but any of them seems to be the right solution.
Allow using the website only for specific IP addresses. But then I realized that in our place IP address is dynamic and changing it for static costs too much in our area.
Check user location. But then I saw that when I'm checking my public IP address, the location is completely wrong! Our building isn't even close to the loaded area.
Using a COOKIE/token on a work computer. But it's very easy to set the same cookie on your own device and I'm not the only IT employee here.
Checking MAC address. As I read here it's possible only in specific cases.
Block access for mobiles. But detecting a mobile is based on browser and if the user click "Request Desktop Site" scripts will say that's a computer.
Is there another method, which I can use to achieve my goal? Am I missing something?
May I bind my app for example with some other technologies that will allow me to do that? Or maybe I should try a combination of all of them?
I couldn't find any script, which would take care of that. In the worst case it doesn't have to be "perfectly secure", but I would like to be it at least hard, annoying, or time-consuming to try to "cheat" in this system.
I would run your app in the office LAN. Nobody will be able to access it from outside except if they can do remote desktop to the office computer or if they have VPN. But if you are in the IT team you may could fix IP ranges for the office computers so that you could exclude the VPN.
In terms of security, in any case it may be better having it running in your LAN. I'm sure you've got a server somewhere and if it's not the case then you could use a NAS (Synology offers NGINX, Apache, PHP and much more) or a little Rasperry Pie or something similar.
If you haven't got a fixed IP, you could also use DynDNS and have it mapped to a sub-domain such as company-name.dyndns.org and then on your PHP app you could have a cron job that gets the IP address from the domain name and updates it every minutes (I'm sure it's quickly run). It could then store it inside a config file, this way:
<?php
define('ALLOWED_IP_FILE', 'allowed-ips.inc.php');
$ALLOWED_DOMAINS = [
'your-company.dyndns.org',
'you-at-home.dyndns.org',
];
$allowed_ips = [];
foreach ($ALLOWED_DOMAINS as $allowed_domain) {
$ip = gethostbyname($allowed_domain);
if ($ip !== $allowed_domain) {
// Store with the IP in the key and value for ease when checking the IP validity.
$allowed_ips[$ip] = $ip;
} else {
fprintf(STDERR, "ERROR: Could not find the IP of $allowed_domain!\n");
}
}
$allowed_ips_export = var_export($allowed_ips, true);
$config_file_content = <<<END_OF_CONFIG
<?php
// Don't edit! This config file is generated by cron-ip-address.php.
\$ALLOWED_IPS = $allowed_ips_export;
END_OF_CONFIG;
if (file_put_contents(ALLOWED_IP_FILE, $config_file_content) === false) {
fprintf(STDERR, 'ERROR: Could not write config file ' . ALLOWED_IP_FILE . "\n");
}
This generates a config file to include in your app. Example of content generated if you run the script I wrote above:
<?php
// Don't edit! This config file is generated by cron-ip-address.php.
$ALLOWED_IPS = array (
'142.250.203.99' => '142.250.203.99',
'23.201.250.169' => '23.201.250.169',
);
Now, in your app, just include it and test the presence of the IP in the $ALLOWED_IPS array:
<?php
include ALLOWED_IP_FILE; // If this is declared in a common config file.
// include 'allowed-ips.inc.php'; // If you haven't got a common config file.
if (!isset($ALLOWED_IPS[$_SERVER['REMOTE_ADDR']])) {
http_response_code(403);
die('Sorry, you cannot access it from here.');
}
Ideally, if what you actually want to track is when employees are in the workplace and logged on / for how long, it would be probably better to just track local machine-logins via a domain controller - a method reachable from the internet is suboptimal exactly for the reasons you mentioned.
If you have an intranet which users cannot tunnel into but can access from their work machines, I'd say hosting your login-page only inside that intranet is the easiest way to achieve what you want with the methods you suggest.
Alternatively, if employee work-machines use windows under a domain controller - you can restrict access to Windows certificate-storage, then install/push a certificate and require that to be present via your server-configuration. In that case, it doesn't matter if the website is accessible from the internet. I'm sure there are similar solutions if work-machines are not on Windows.
This admittely old question gives some pointers in the right direction on how to require client certificates from a Webserver (IIS in that case).
I need your advice. I made API in php to communicate with my android application and mySQL database. Now I wanna put this api on free online hosting with free database, the problem is that when i make query for that API I'm receiving my json data with junk from hosting like HTML tags and commercial text "[hosting name] free hosting". When my app receives this data, it shuts down. Everything works fine on local wamp server but at online hosting my app is crashing
I have 3 questions for you
Is it normal on free hosting or maybe my API is wrong designed?
If I put my php files on paid serwer will I avoid this additional stuff added by hosting company?.
Check out part of my sample user registration php code
$new_sql_select_query = "select * from userinfo where userName like '$userName' and userEmail like '$userEmail';";
$sql_all_data = mysqli_query($con, $new_sql_select_query);
$userDataJson = array();
while ($row = mysqli_fetch_array($sql_all_data)) {
$userDataJson["userId"] = $row["userId"];
$userDataJson["userName"] = $row["userName"];
$userDataJson["userEmail"] = $row["userEmail"];
$userDataJson["accountBalance"] = $row["accountBalance"];
}
$responseJson["success"] = 1;
$responseJson["message"] = "User correctly added to base!";
array_push($responseJson["user"], $userDataJson);
echo json_encode($responseJson);
I have an idea but I do not know how to do it correctly. I am generating a new json data file by code below
$myjson = json_encode($responseJson);
file_put_contents('myfile.json', $myjson);
but here is another problem, my app need to be somehow redirected to this new file because right now my app is connecting directly to a specific php file in this case CreateNewUserDB.php so how should I do it?. Should I return link to this generated json file to my app and then make another connection but this time to this "myfile.json" file?. Waiting for answers.
Regards
The reason that your app might be crashing is that when you do send response to your app on localhost, then only json data is sent. But as you said on the free hosting, you got some html. When your java code tried to make a json object out of it, it must have thrown an exception and hence the error.
There are plenty of free hosting, that are good and don't do these type of advertisements. https://www.biz.nf/ is one of them. I used it in my early years. Also paid hosting will not give you problems like these
This is an old thread, but I had a similar problem recently.
I uploaded my php json api in my shared hosting and solved the problem setting the right format by adding the header for json in the php file:
header('Content-Type: application/json');
I encourage you to work with Firebase, it will handle all the background staff for you, and it gives you access to the database also, besides that, it's very fast comparing to regular databases.
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;
?>
what is the best way to tell my server side script that the submitted form or data is coming from a trusted source or from my website?
Am already performing alot of server side data scrutinize, and think i can improve this more with the client side too
AM a php/mysql developer
To find out the IP of the user who posted the data use:
$ip = $_SERVER['REMOTE_ADDR'];
echo "<b>IP Address= $ip</b>";
According to the IP you can decide whether the user is trusted or not. (for instance if you'd like to trust only a special range of IP-addresses)
Whenever I read posted variables in PHP I use to filter them like that:
function check_string($string) {
// allowed chars: a-z,A-Z,0-9,-,_
if((preg_match('/^[a-zA-Z0-9\-\_]+$/',$string)))
return true;
return false;
}
It would filter all chars which are not a-z, A-Z, 0-9,- or _ and enhances the sites security a little bit. If you've access to your webserver:
Disable server banners (which display OS and apache version for instance), if you have access to the webservers configuration. This information can be very useful for hackers, and you want to disable everything which could help them in any way ;)
Prevent directory listing (for instance with .htaccess files). A simple example would be:
Options All -Indexes
Run the webserver with a limited user account (best would be to chroot the user as well)
Use mysql_real_escape_string in mysql queries and use htmlentities in html posts.
Example:
Wrong:
<?php
if($_SERVER['REQUEST_METHOD'] == "post"){
echo $_POST['hai'];
}
?>
right:
<?php
if($_SERVER['REQUEST_METHOD'] == "post"){
echo htmlentities($_POST['hai']);
}
?>
$_POST can also be $_GET
wrong:
<?php
$query = "SELECT * FROM table WHERE msg = '". $_GET['hai'] ."'";
?>
right:
<?php
$query = "SELECT * FROM table WHERE msg = '". mysql_real_escape_string($_GET['hai']) ."'";
?>
And don't forget to use htmlentities when you get things out of the mysql table...
Greetings
I've always used a class that handled such issues, it would handle both server/client side and ensure that any input was made from the server itself. It would then validate and ensure it is not given special characters.
http://validformbuilder.org/
Let me know if that helps, it helped me a while ago. :)
I think the best option would be adding a digital signature to requests, even a simple one.
For example your site or the trusted source add the SHA checksum of the request computing it after the addition of a secret "salt" (that is not sent). The server gets the data, adds the same salt and computes the SHA signature, if the SHA matches then the source knew the secret and you can trust the content.
I guess your question implies CSRF... Just generate and add a validation token.
Many frameworks can manage these for you.
Guys, thanks for your help i appreciate it all. Generally i was talking about client side security ie making sure data coming from the client is from original source.
Generally SSL might just have been the answer, after a lot of browsing i found two sites that solves this issue to an extent: aSSL ,and Jquery implementation
This way my data is secured up to a level say 90%
what do you think?
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).