0

I have a database with just over 800 data.

product table

pid   name     p_page
1     money    money.php
2      gold    gold.php
3      .
.      .
.      .
800    .

I have 2 pages...

product_item.php

<div class="button">
<a href="<?php fetchdir($apages) ?><?php echo $row['p_page']; ?>?pid=<?php echo $row['pid']; ?>">View</a>
</div>`

when you click view the product info is pass to product.php in here i have

if (isset($_GET['pid'])) {

depending on what product the user clicked on the URL might look like something below but the 44 will change to whatever id

http://www.example.x10.mx/money.php?pid=44

the problem with this, is that money.php have a different layout to the other pages and if I change 44 to 68, the product info will show on the page but the layout will not look good.

My question what is the best way for me to stop users from being able to change the url. I want to encrypt all my pid in the url so it will look something like http://www.example.x10.mx//money.php?sel=the product name here or 4 letters or anything

I just want to take away pid from the url.

Please help me. If you dont understand my question please ask in the comment and try and say what you think you understand.

Edited to show my fetch function

$php = "php/";
$apages = "account/";
$bpages = "booking/";
$gpages = "general/";
$ppages = "product/";

// Global functions
function fetchdir($dir)     
{
   $protocol = $GLOBALS['protocol'];
    $host = $GLOBALS['host'];
    ($dir == $GLOBALS['apages'] || $dir == $GLOBALS['bpages'] || $dir == $GLOBALS['ppages'] || $dir == $GLOBALS['gpages'] ? $branch = $GLOBALS['pagebranch'] : $branch = $GLOBALS['branch']);
    echo $protocol.$host.$branch.$dir;
}

Thanks

p.s. I dont know if this can be done in .htaccess but i think it can be done in php


Some clarification:

I have a url which looks like this

www.example.com/account/product.php?pid=1

the problem with this is that someone can change 1 or any number and if they is a pid in the database with that number it will get the items information and display on the page. Which I don't want to happen because not all product are meant to be display in some pages.

In the papge which i show all my available product. I simple uses a SELECT statement and then echo what I need in some div.

In that page I have a view button.

$stmt = $conn->prepare("SELECT * FROM Product WHERE Type = 'shoes'");
$stmt->execute();
$i = 0;
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
    $id = ($row['pid']);
    $product_page ($row['dir_page']);

    <div class="button" >
        <a href = "<?php fetchdir($apages) ?><?echo $product_page?ProdID=<?php echo $id>" > View</a >
        </div >
    }

Depending on the page that information is getting sent to when you click on view I use Get method

<?php   
    if (isset($_GET['pid'])) {
    // Connect to the MySQL database  
    dbconnect(); 
    $id = preg_replace('#[^0-9]#i', '', $_GET['pid']); 

 }

If you notice in my select statement used type to show only the product which type is shoes. I have other types as well, which as their other pages. Now the problem is if i change the pid to any page that doesn't have a type of shoes or if an in the other pages and enter a pid which type is shoes or anything, the information from that page will still render. Which I don't want to happen.

My question how can i stop users from changing that pid and even if they change it. they will still be on the same page?

Gordon
  • 312,688
  • 75
  • 539
  • 559
Sarah James
  • 431
  • 5
  • 19
  • 2
    Even if you "encrypt" the pid, people can still manipulate it. There is no way to prevent people from tinkering with URLs or HTTP request for that matter. They are in control of what they send to your server. – Gordon Jul 29 '13 at 10:13
  • Sounds like a case of fixing the symptom rather than the cause. The real issue is that the page cannot display products properly. It needs to check if it can display the product and redirect to a different page or show an error if it can't – Anigel Jul 29 '13 at 10:15
  • if you don't want user your users to hack urls, then don't provide simple-easy-to-guess IDs like that. make it `id=` instead, and now they'll never be able to guess what the next id in the sequence is. – Marc B Jul 29 '13 at 18:13
  • if you have in your database a field like active/inactive you can use this field to check before your show the page. – Perry Jul 29 '13 at 18:14
  • If you rely on data sent by a client to determine "what to display", there's not really anything you *can* do to prevent them from changing said data. You can make it difficult though; don't use the `id` and instead use a friendly-url like `example.com/products/some-products-long-and-awesome-name`. You could also make it a bit more obfuscated and use session variables to hide what's displaying, but it still has to come from the user initially. – newfurniturey Jul 29 '13 at 18:14
  • @MarcB thats true but I wish phpmyadim could generate pid with a mix of numbers and letter with auto_inclement – Sarah James Jul 29 '13 at 18:15
  • phpmyadmin doesn't generate ANYTHING. it's a management tool for a mysql database. it is NOT a database itself. – Marc B Jul 29 '13 at 18:16
  • Is this a security concern, or just convenience? If security, then you should be ensuring that the active user only has access to the requested PID, even if it's different what what you offered. – Joe Jul 29 '13 at 18:17
  • @MarcB am sure you know what i mean... xx – Sarah James Jul 29 '13 at 18:17
  • @newfurniturey I did it with the name... hopefully that secure. I will add numbers and underscores. etc to the name... – Sarah James Jul 29 '13 at 18:34

4 Answers4

2

The problem isn't having the PID in the URL, it is having the template name in the URL.

Store the template name in the database (you are doing this already), and use that to determine what HTML to wrap the data in instead of putting it (money.php) in the URL.

Move your templates out of the web root (they shouldn't be hit by users directly), have a single index.php and then include() the template based on the data in the database.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • any example of this anywhere online i can read up or follow? please xx – Sarah James Jul 29 '13 at 10:19
  • `include($TEMPLATE_ROOT_DIR . $row['p_page']);` – Quentin Jul 29 '13 at 10:28
  • 'View' ??? can u show your example based on my layout please – Sarah James Jul 29 '13 at 10:34
  • No. `View` in your link. Then `include($TEMPLATE_ROOT_DIR . $row['p_page']);` in `index.php`. Determine your template in the page that shows the product information, not in the page that links to that page. – Quentin Jul 29 '13 at 10:51
  • i added `include($TEMPLATE_ROOT_DIR . $row['p_page']);` to each of the pages but I am getting an error. – Sarah James Jul 29 '13 at 11:28
  • What error? Is it complaining that `$TEMPLATE_ROOT_DIR` doesn't exist? You have to set it to where you are keeping your templates. Is it complaining that `$row['p_page']` doesn't exist? You have to query the database. – Quentin Jul 29 '13 at 11:32
  • it is complaining about `$TEMPLATE_ROOT_DIR` I have edited the question to show where the error is pointing to – Sarah James Jul 29 '13 at 11:34
0

You cannot prevent someone from changing the URL or from requesting arbitrary URLs. Your server (i.e. your app) has to decide how to respond to an invalid request. If you don't want to display certain things publicly, flag them as such in your database, test for that flag and simply refuse to output anything if that flag is hit.

Make the server respond negatively if something doesn't fit your conditions; don't expect the user to behave correctly.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • its not about not display some contents is about not display some contents in some pages that those contents shouldnt be display in – Sarah James Jul 29 '13 at 18:19
  • 2
    Well then don't display them in those pages. Establish some rule somehow to determine what can be displayed where and then write code that checks for that condition. Your program needs to be internally consistent, it's not the job of the user to make consistent requests. Put another way: if it's possible to mess up your app simply by requesting "the wrong URL", your code is simply bad. – deceze Jul 29 '13 at 18:22
0

Assuming that PID is a autoincrement value, you can still obfuscate it. Add another column in the table that contains a randomly-generated key (using uniqid or some derivative). Then use that key in your URL. You'll get something like: www.example.com/account/product.php?pid=II8GypI6H93Ij. This doesn't guarantee that someone won't find it, but it's good enough in most instances.

Joe
  • 6,767
  • 1
  • 16
  • 29
  • the only problem with this is that I need to enter those random key myself because they is no want to do this. It will only work if i was dealing with a `register form` in which i can hash it. – Sarah James Jul 29 '13 at 18:28
0

Check for allowance in the Database

Depending on your level of programming skills, in the database you could add a field or a relational table that relates the ID of the pages to allowed page templates (I'm guessing you're talking about templates.)

Then in the code you can make it so the page checks this database to see if the page contents are allowed to show. Something like:

$query1 = "SELECT * FROM Product WHERE Type = 'shoes' and allowedTemplate='1'";

This way you won't have to hardcode everything into the code itself. On the backend (if there is a CMS) then you could have checkboxes indicating the relationships to the templates and prefill them by default.

You'll need to make the site so something with that stuff though.

Your other option

You could use clean urls (which used to be better for SEO) to show real words instead of the IDs. Then you can use .htaccess tricks to convert the URIs to their ID counterparts with a dynamic RewriteMap.

AbsoluteƵERØ
  • 7,816
  • 2
  • 24
  • 35
  • I am still in high school, and we just started learning this year but I have been reading some books and watching some video and been practicing to improve but i think I will got with `` is they a way i can add $id om that button? please. – Sarah James Jul 29 '13 at 18:51
  • Yes. You could make it say `
    `.
    – AbsoluteƵERØ Jul 29 '13 at 19:34