/    Sign up×
Community /Pin to ProfileBookmark

PHP Securing Files

I should know how to come up with this solution but I’m having a bit of brain freeze or something tonight.

I’m trying to secure the font files that I’ll be using so I won’t allow people to download them when they view my css. I figured I’d use a php script to serve the font files (stored below the web root) to my CSS file, but how do I do it?

My CSS would be:

[code]
@font-face {
font-family: ‘TradeGothic BoldCond Twenty’;
src: local(‘TradeGothic BoldCond Twenty’),
url(‘http://example.com/fonts/myscript.php?somekey’),
etc etc etc
}
[/code]

and use a php script to basically do this:

[code=php]
header(‘Content-Type: font/opentype’);
echo file_get_contents(“/path/to/font.ttf”);
[/code]

But I need a way of securing it so people can’t just type in [url]http://example.com/fonts/myscript.php?somekey[/url] and get the font file.

I am pretty sure that there’s not a single superglobal in $_SERVER that I can rely on, like HTTP_REFERER, but I’m at a total loss of how to do it, at least to the best of my ability.

to post a comment
PHP

9 Comments(s)

Copy linkTweet thisAlerts:
@NogDogMar 03.2011 — Not 100% sure this would work, but it's probably what I would try:

main page:
[code=php]
<?php
session_start();
$token = uniqid();
$_SESSION['token'] = $token;
setcookie('token', $token, 0);
[/code]

file-server:
[code=php]
<?php
session_start();
if(!isset($_COOKIE['token']) or !isset($_SESSION['token']) or
$_COOKIE['token'] != $_SESSION['token']) {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
exit;
}
// so that copying from the HTML source won't work
setcookie('token', '', 1);
unset($_SESSION['token']);
// rest of script...
?>
[/code]
Copy linkTweet thisAlerts:
@aj_nscauthorMar 03.2011 — Thanks NogDog, very interesting indeed.

EDIT: Had an .htaccess thought, wasn't relevant.

So, if the browser can read the font, is there any type of sniffing tool that can capture the request from the web page and download the font?
Copy linkTweet thisAlerts:
@NogDogMar 03.2011 — Thanks NogDog, very interesting indeed.

EDIT: Had an .htaccess thought, wasn't relevant.

So, if the browser can read the font, is there any type of sniffing tool that can capture the request from the web page and download the font?[/QUOTE]


If you are going to send a file to a client, there is ultimately no way to stop somebody determined enough and knowledgeable enough from capturing it. The best you can hope is to make it difficult enough to stop the less determined/less knowledgeable people. At some point the file will be on the user's computer, so if they know where to look for it, they can copy/move it from that cache location to somewhere more permanent. A little clever use of cURL in a PHP script could capture it, too.
Copy linkTweet thisAlerts:
@eval_BadCode_Mar 03.2011 — Yes there is absolutely no way to prevent me from getting that font.

It will be visible in about:cache (the browser's cache), or I could simply reconstruct it from creating logs with my card in promiscuous mode and reconstructing the file from packet(s).

You'd be really hard pressed to find someone saying obscurity is security, but after about 5-15 minutes it would no longer be worth the effort to get that font. You can do what NogDog said; make it so unfun that no one wants to bother.
Copy linkTweet thisAlerts:
@aj_nscauthorMar 03.2011 — Thanks folks for the replies. So whats the point of foundries like typekit or fontdeck? Is it just that they take care of all legal/licensing issues for you so that's why it's worth about a buck a month for a font?
Copy linkTweet thisAlerts:
@aj_nscauthorMar 03.2011 — NogDog, you're idea (almost) works brilliantly. The problem I'm having is that @font-face usually looks like this:

<i>
</i>@font-face {
font-family: 'TradeGothic BoldCond Twenty';
src: url(fonts.php?eot=0);
src: local('TradeGothic BoldCond Twenty'),
url(fonts.php?woff=0) format('woff'),
url(fonts.php?ttf=0) format('opentype'),
url(fonts.php?svg=0) format('svg');
font-weight: normal;
font-style: normal;
}


I'm using my script, fonts.php and using the query string to determine which font to send to the browser. The issue is that the wonderful snippet you wrote cancels the cookie and session token after the first request to fonts.php - but I still need to make 3 more requests (which always get 404'ed).

Any ideas on how to workaround this issue?

Thanks buckets for your help so far!
Copy linkTweet thisAlerts:
@NogDogMar 03.2011 — My first thought was to add a url query string variable to the last one, and only delete the session/variable tokens if that $_GET element is present. However, I'm not sure there's any guarantee that the client will request them in the order in which they appear in the style block. So what I'm thinking now is to set a separate session variable for each font type, then delete that session variable as it's processed.

[code=php]
<?php
session_start();
$token = uniqid();
$_SESSION['token'] = array(
'eot' => $token,
'woff' => $token,
'ttf' => $token,
'svg' => $token
);
setcookie('token', $token, 0);
[/code]

[code=php]
<?php
session_start();
$types = array('eot', 'woff', 'ttf', 'svg');
$fontType = false;
foreach($types as $type) {
if(isset($_GET[$type])) {
$fontType = $type;
break;
}
}
if($fontType == false
or !isset($_COOKIE['token'])
or !isset($_SESSION['token'])
or $_COOKIE['token'] != $_SESSION['token'][$fontType])
{
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
exit;
}
// so that copying from the HTML source won't work
unset($_SESSION['token'][$type]);
// rest of script...
?>
[/code]
Copy linkTweet thisAlerts:
@aj_nscauthorMar 03.2011 — Hahaha! Now you're talking! Thanks for letting me borrow your brain.
Copy linkTweet thisAlerts:
@aj_nscauthorMar 03.2011 — [B]EDIT: NM - I fixed this mess somehow.....I'll leave the original question below but it's already fixed (I hope)[/B]

After being so great with your help, I hate to bother you, but I'm having a funny issue now.

This is at the top of all the pages on my site:
[code=php]
session_start();
$token = uniqid();
setcookie('fToken', $token, time()+90);//expire thirty seconds after page load
$_SESSION['fToken'] = array(
'tgbct' => array(
'eot' => $token,
'woff' => $token,
'ttf' => $token,
'svg' => $token
)
);
[/code]


Very similar to the code you used, except I wanted to take one small step ahead and create an array in case I wanted to use more than one font. tgbct is the name of my font, and each of the extensions are in it with the ingenious solution you came up with.

Here's my font serving script:

[code=php]
<?php

session_start();
if(!isset($_SERVER['HTTP_REFERER'])) {
print_r($_SESSION);
echo "<br/>n";
echo "<br/>n";
echo "<br/>n";
print_r($_COOKIE);
exit;
}

//$fontName and $fontType have been tested and set to tgbct and the file extension so this is not a problem

if(!$fontName or !isset($_COOKIE['fToken']) or !isset($_SESSION['fToken'][$fontName][$fontType]) or $_COOKIE['fToken'] != $_SESSION['fToken'][$fontName][$fontType]) {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
exit;
}

unset($_SESSION['fToken'][$fontName][$fontType]); //can no longer be requested

//serve the font below here
?>
[/code]


I used the HTTP_REFERER header for debugging so when I access the script directly it will show me the cookie and session variables set.

When I visit my site it downloads the fonts and unsets the session vars so when I visit the script page it shows me that those session vars for the downloaded fonts have been unset.

HOWEVER (big however), when I refresh the script page, it regenerates the session and cookie and a font can be downloaded directly.

Here's the page and the script:

http://jaksweb.server309.com/xit/

http://jaksweb.server309.com/xit/css/fonts.php?tgbct=ttf

The test for this is basically the following:

Visit the homepage then visit the script page (you'll see that two of the four entries in the session array 'tgbct' are missing). But when you REFRESH the script page, they're all back there again.

I hope you can take a look and I sincerely appreciate your help this far.
×

Success!

Help @aj_nsc spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 4.29,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...