Results 1 to 36 of 36
  1. #1
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874

    Question Secure php app to download medical files?

    Hello All,
    I am writing a secure php app.
    This is what I have done:
    1) Secure login with user name and password from a mysql database through sessions.
    2) three wrong attempt I flag the account and lock it.
    3) user can change password.

    then what challange I face:
    Once the user logs in correctly, I want the user to be able to see a total of 12 files that can be downloaded. the problem is if the user gets the url of the location, then they really do not need to login and they can type the url and download it.... so the physical location has to be secure and I need php to be able to access them and get it....
    I will need to have every user to be the same way (with a folder that only their ID has access to. (very sensitive files)
    is there a way to do this? if so, is it secure? is it the most secure?
    Is using sessions in general very secure?
    thank you all for all your help.
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  2. #2
    Join Date
    Apr 2006
    Location
    Southern California
    Posts
    1,125
    2 ways I can think of. make a writable folder, copy the desire file to the folder with some funky hash name and link that to the user. You need to clean it up later once the user is done. Or store the file in a database, take a bit more works but it's more secure.
    Sarcasm, the 6th Ponyman of the Apocalypse.
    Please do not inquire about Tim, the 5th Ponyman.

  3. #3
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    the files will be downloaded\viewed (pdf files)
    the user would login, based on the login (mysql database has the logins) the user will see the files they have access to, I need to make sure the user cannot get other files for other members) also I need to make sure that no one from outside can get the files. how can I do that?(the most secure way)
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  4. #4
    It has been mentioned several times here how to achieve what you need.

    Basically, you use a directory that's below web root for storing files.

    For example, if you have /home/website/www as your document root, you'd use /home/website/downloads to store files.

    If you choose to have downloads directory in your document root (for example, /home/website/www/downloads) which is then accessible by public, you can use mod_rewrite to disallow any access to that directory.

    After you've ensured that directory isn't accessible directly via URL, you use PHP to read files within those directories and to output them. It's done like this:

    PHP Code:

    $file_path 
    '/path_to_file/filename.pdf'// I used .pdf for this example

    if(is_file($file_path))
    {
        
    header('Content-Type: application/pdf'); // you must specify correct mimetype for file you're serving
        
    header('Content-Disposition: attachment; filename=original_filename.pdf');
        
    header('Content-Length: 'filesize($file_path));
        
    readfile($file_path);

    This is just a sample code, there's more to headers when serving files etc.
    But I think you get the general idea. If somethings unclear, feel free to ask.

  5. #5
    Join Date
    Mar 2006
    Posts
    965
    Just as a little precaution, I'd use:

    PHP Code:
    $file_path '/path_to_file/filename.pdf'// I used .pdf for this example 
    for:

    PHP Code:
    $file_path basename(trim('/path_to_file/filename.pdf')); // I used .pdf for this example 


  6. #6
    Join Date
    Mar 2006
    Posts
    965
    In addition to what I have posted above, I'd also like to suggest that, since this is about medical files - which seem to be more private subjects - to mask your folders under queries.

  7. #7
    Join Date
    Feb 2005
    Posts
    105
    If we're dealing with medical records, it should meet HIPAA requirements.

    http://www.sans.org/resources/policies/#hipaa

  8. #8
    Join Date
    Mar 2006
    Posts
    965
    Yes, that looks pretty good too after what I read.

  9. #9
    Quote Originally Posted by horizon
    Just as a little precaution, I'd use:

    PHP Code:
    $file_path '/path_to_file/filename.pdf'// I used .pdf for this example 
    for:

    PHP Code:
    $file_path basename(trim('/path_to_file/filename.pdf')); // I used .pdf for this example 


    << removed >>

    And third - this is just an example code to show how someone can create secure file download system. I see no point in correcting or adding some unnecessary string-cleaning functions to the post, especially since it's just an example.
    Last edited by Tyler; 11-05-2006 at 02:49 PM.

  10. #10
    Join Date
    Oct 2004
    Location
    San Francisco, CA
    Posts
    2,454
    Thread has been dramatically clean. Please keep it nice, and try to help the OP and not argue with one another.
    Tyler Cole
    Eeek, a Blog

  11. #11
    Join Date
    Mar 2006
    Posts
    965
    Thanks for your support Tyler. I appreciate someone who knows what respect is all about.

  12. #12
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    Quote Originally Posted by maxymizer
    It has been mentioned several times here how to achieve what you need.

    Basically, you use a directory that's below web root for storing files.

    For example, if you have /home/website/www as your document root, you'd use /home/website/downloads to store files.

    If you choose to have downloads directory in your document root (for example, /home/website/www/downloads) which is then accessible by public, you can use mod_rewrite to disallow any access to that directory.

    After you've ensured that directory isn't accessible directly via URL, you use PHP to read files within those directories and to output them. It's done like this:

    PHP Code:

    $file_path 
    '/path_to_file/filename.pdf'// I used .pdf for this example

    if(is_file($file_path))
    {
        
    header('Content-Type: application/pdf'); // you must specify correct mimetype for file you're serving
        
    header('Content-Disposition: attachment; filename=original_filename.pdf');
        
    header('Content-Length: 'filesize($file_path));
        
    readfile($file_path);

    This is just a sample code, there's more to headers when serving files etc.
    But I think you get the general idea. If somethings unclear, feel free to ask.
    Ok.... I have a little concern.... I was planning in having the files stored on another server or in a directory that is not under html public. I think this is more secure!!! can I not do that?
    I was thinking of running it on a windows2003 platform (just since I know it much better than linux.)


    horizon
    What do you mean by to mask your folders under queries..... SOrry guys, but you have been very helpful and this is very critical to me...
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  13. #13
    Join Date
    Mar 2006
    Posts
    965
    What do you mean by to mask your folders under queries.....
    What I meant about this is that, since your original folder seem to be displayed for download purposes, it would be a good suggestion to show your PDF files like this (for example):

    PHP Code:
    download.php?file=filename.pdf 
    rather than showing the path like this:

    PHP Code:
    /path_to_file/filename.pdf 
    I'm posting these comparaison since your subject seem to be highly important (especially about medical files). That said, this would indeed increase security for downloads by masking the original path (even though, yes, it might use a little bit more server ressources).

    If this wasn't clarified enough, technicly, please say so and I will try to elaborate it for you.

  14. #14
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    very well clarified. This is what I actually had planned. I was thinking of having all the files in a different folder that is not below the public html folder.... is this not possible.

    putting it on a windows 2003, with 'Content-Type: application/pdf'); for pdf files, is there anything I need to install on the server to serve the pdf fils (plugins?)
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  15. #15
    Join Date
    Mar 2006
    Posts
    965
    very well clarified. This is what I actually had planned. I was thinking of having all the files in a different folder that is not below the public html folder.... is this not possible.
    Physically, your files will still remain under your public_html folder (if used locally). It would just mask the source folder from the web - by considering masks (technicly speaking). If you plan to download those files remotely, then you'd need to point out your files remotely. However, the answer is yes - this is possible.

    putting it on a windows 2003, with 'Content-Type: application/pdf'); for pdf files, is there anything I need to install on the server to serve the pdf fils (plugins?)
    Especially on windows 2003 server, it is unlikely a plugin would be required in order to do this. From what I remember, this feature is already part of the core.

  16. #16
    Join Date
    Nov 2001
    Location
    Vancouver
    Posts
    2,416
    Quote Originally Posted by horizon
    Just as a little precaution, I'd use:
    PHP Code:
    $file_path basename(trim('/path_to_file/filename.pdf')); // I used .pdf for this example 
    Since my comments were removed, I'll reiterate:

    This suggestion makes no sense in context with the discussion to date in this thread. Using the PHP basename function will return the wrong result for the intended purpose and may expose the application to returning the wrong file or an operating system error (no file exists).
    “Even those who arrange and design shrubberies are under
    considerable economic stress at this period in history.”

  17. #17
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    Thank you Horizon and mwatkins.
    Ok....
    just this and I think I ready to roll

    what is "you can use mod_rewrite to disallow any access to that directory" which is a dirctory under the public folder. Not really sure what that is.

    is that more secure than having the files stored at a different loctaion that is not under the public root folder.
    From what I understand, the mod_rewrite is in apache, I am planning on using windows with IIS. Is there anything I can do with that?
    Last edited by OnlineRack; 11-05-2006 at 03:54 PM.
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  18. #18
    Join Date
    Mar 2006
    Posts
    965
    is that more secure than having the files stored at a different loctaion that is not under the public root folder.
    I have always considered .htaccess a more reliable and secured feature for customizing. If you have a choice between remote downloads and local downloads, with .htaccess, I'd definitely consider to use .htaccess instead.

    Althought, unless things has changed, .htaccess is not available under Windows Server.

    Edit: I just saw your edited post. It would seem I have replied my answer right before your question fortunitely.
    Last edited by horizon; 11-05-2006 at 03:57 PM.

  19. #19
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    hmmm.. ok. How about with IIS. (I plan to use windows since I am much more familiar with that platform) I cannot use .htaccess there.
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  20. #20
    Join Date
    Mar 2006
    Posts
    965
    Last time I checked, .htaccess is not available under IIS unfortunitely.

  21. #21
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    I did not think so. What do you think the solution for that case then since htaccess is not an option.... just place the files at a different location fron pub?
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  22. #22
    Join Date
    Mar 2006
    Posts
    965
    just place the files at a different location fron pub?
    Placing your project files under a seperated folder, for instance, called: downloads would be a good suggestion. It would not be recommended to leave your files at the same location as your PHP files are actually located. However, the mask technic, since .htaccess cannot be an option for you (unless installing Linux rather than windows), would still be a good opportunity for you.

  23. #23
    Join Date
    Feb 2003
    Location
    AR
    Posts
    2,381
    The absolute safest option is to place the files where they are NOT accessible from the web.

  24. #24
    Join Date
    Nov 2001
    Location
    Vancouver
    Posts
    2,416
    mod_rewrite and .htaccess are not solutions for you on Windows, so I won't bother commenting these Apache features except to say that regardless of web server, you do not need them to build a reliable, secure, solution.

    DO Use a file access function exposed through a PHP page, as you planned, to serve up the files.

    DO store the files OUTSIDE of the public web server directory hierarchy. DO secure those files such that the minimum required access is granted to them. DO follow healthcare information security standards.

    DO NOT embed information within the file paths/urls that would allow a malicious or curious user to learn about your data. (discussed later)

    DO check the variables passed by the browser. DO ensure that you've protected your file access function from a mischievous remote user who might edit the URL parameters being passed back to your application. For example, if you dish up a page showing:

    http://someapp.com/download?file=/user22/aidstest.pdf

    Then you have to protect against a user modifying that url (by hand even). Its best not to divulge other data in the URL if you can possibly avoid it, i.e. the following can be considered insecure, even if it doesn't actually retrieve the file, because it exposes the id of the user - which can be left in caches, print outs, etc...

    http://someapp.com/download?file=/user22/aidstest.pdf

    And someone might play with it...

    http://someapp.com/download?file=/user21/aidstest.pdf
    http://someapp.com/download?file=/user23/aidstest.pdf
    http://someapp.com/download?file=/bclinton/aidstest.pdf
    http://someapp.com/download?file=/gwbush/aidstest.pdf

    DO ensure that your file access routine can't be spoofed and permit access outside of the file hierarchy that you expect. Eg this should be detected and fail:

    http://someapp.com/download?file=~/../../etc/passwd
    http://someapp.com/download?file=~/config.php

    It would be best if you could completely hide the underlying implementation of the file store. I.e., once logged in:

    http://someapp.com/download?file=lat...terol_test.pdf

    Or better yet, use random file names that have no semantic meaning.

    http://someapp.com/download?file=a0e1593b2.pdf
    “Even those who arrange and design shrubberies are under
    considerable economic stress at this period in history.”

  25. #25
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    You guys are way more help than I thought I could get. you have opened my eyes on things I did not see before, the good thing is that you gave me the solutions.

    this is then what I plan to do since it is in windows:
    once the user logs in and see their available files, they will be presented as
    https://www.domain.com/download.php?file=132

    then once the parameter 132 is passed to download.php it will be matched to a variable called $retreive for example which would run a mysql statemnt and look up the file name and location which would do an fopen on it. in which would be 8 digit number. of course access level would be verified during the process.

    does that sound like a good idea?
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  26. #26
    Join Date
    Nov 2001
    Location
    Vancouver
    Posts
    2,416
    Not knowing how you plan to structure your tables, one thing I'd be concerned about with:

    Is that users can just muck with the file ID

    So as long as your logic makes that sort of manipulation fruitless.... here's an example of a simple approach (chances are you are already down this road, but just in case I've spelled it out here) - assume you have database tables:

    Code:
    Person
      id
      first_name
      last_name
      ...
    
    Document
      id
      person_id
      volume
      path
    Then the query, where the person ID is known from the login session:

    Code:
    SELECT * from document d, person p
    WHERE d.person_id = p.id
    AND d.id = 132
    Will retrieve a document, while invalid queries (random malicious editing of the URL) will not.
    “Even those who arrange and design shrubberies are under
    considerable economic stress at this period in history.”

  27. #27
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    thank you mwatkins. This is what I was going to do but in two qeries, first match the id of the user then the file, but your solution is way better than what I was going to do as it is more controled.
    Is it worth paying a company to test its security to see if they can break it.... is there such thing? (once implemented)
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  28. #28
    Join Date
    Mar 2006
    Posts
    965
    As 'two' other alternative solutions, here's what you can do to amplify your masking:

    1 - Rather than adding the file's ID into your query (since, it's true, users could simply manipulate your downloads by playing with the ID numbers from the URL bar - which is not recommended), you could always specify the filename itself (not the full path but simply the document's filename) + urlencode it.

    2 - Create a global user session function that will allow, for each of your users to download 'as per selectively set' from your builted list you could create. This technic would allow you to specifically set downloads towards user accounts you would only wish to download. From there, as explained above my post, regarding the SQL statement, you could select the ID, from a POST query, and then add that variable into the WHERE statement + the user ID's info. That would pretty much be like it's being explained above.

    Solution no. 2 sure would require massive time to hardcode this out. Althought, it is recognized as far more secured process than solution no 1. Solution no. 1 is simply more easier to code (especially if you're in a hurry) though.

  29. #29
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    hmmmm this is just getting better and better.
    I like solution no. 2
    I will have an access level in session declared. since it is a set number of files, I will have a button for each file that would do a post to a script which retreive the file accordingly. this way no one sees anything. Is this what you are suggesting horizon. A post form is much more secure than a Get form (I am pretty sure) so this way I would be very well settled. correct.?
    Anything I should be concened about in a post form?
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  30. #30
    Join Date
    Mar 2006
    Posts
    965
    I will have an access level in session declared. since it is a set number of files, I will have a button for each file that would do a post to a script which retreive the file accordingly. this way no one sees anything. Is this what you are suggesting horizon.
    Precisely. However, I'd still recommend to randomize your filename and set a certain timeout period for each created files on your FTP server. This way, it would avoid future / un-authorized users to download unexpected files.

    This is what I'm currently doing from my end so that specific users would have the ability to click on a URL link that would allow them to follow specific instructions (for my case). As for your case, it would simply allow them to allow your documented information.

    A post form is much more secure than a Get form (I am pretty sure) so this way I would be very well settled. correct.?
    Theoricly, yes. However, handling your queries correctly would still be a priority when checking the required infos that requires downloading for such documentations. Althought, I think you would be the judge on that.

    Anything I should be concened about in a post form?
    Which brings my next recommendation through here. Make sure to code out your PHP queries correctly. I could, as several others could, help you out on this if you require further assistance for tracking the infos correctly.

  31. #31
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    Quote Originally Posted by horizon
    Precisely. However, I'd still recommend to randomize your filename and set a certain timeout period for each created files on your FTP server. This way, it would avoid future / un-authorized users to download unexpected files.

    This is what I'm currently doing from my end so that specific users would have the ability to click on a URL link that would allow them to follow specific instructions (for my case). As for your case, it would simply allow them to allow your documented information.
    What do you mean... the files will be updated once a month, (overwritten). Sessions will time out in 15 minutes. Is that what you are talking about

    Theoricly, yes. However, handling your queries correctly would still be a priority when checking the required infos that requires downloading for such documentations. Althought, I think you would be the judge on that.
    Queies will be done very carefully.... I will do it as mwatkins where the query will look for file with the access level and doc id in sql, if there is a match then it is served.
    Which brings my next recommendation through here. Make sure to code out your PHP queries correctly. I could, as several others could, help you out on this if you require further assistance for tracking the infos correctly.
    please elaborate on this one.... just so I know what you are talking about a little more.
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  32. #32
    Join Date
    Mar 2006
    Posts
    965
    What do you mean... the files will be updated once a month, (overwritten). Sessions will time out in 15 minutes. Is that what you are talking about
    Yes, that is correct. Althought, I was not referring to your content itself, about the update, but about the filenames.

    Queies will be done very carefully.... I will do it as mwatkins where the query will look for file with the access level and doc id in sql, if there is a match then it is served.
    Close to all set.

    please elaborate on this one.... just so I know what you are talking about a little more.
    I was simply offering my assistance in case you'd require further help with PHP queries, since you asked:

    Anything I should be concened about in a post form?
    Oh ! and one more thing I forgot to add, very important; since this is about file download and you wish to do it from an HTML form that is being targeted to a PHP file, make sure to add the multiform-data to your form.

  33. #33
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    as for assistance, you all have been way better than expected, and do not worry. I will let you know due to your expertise, kindness, and helpfullness.

    Oh ! and one more thing I forgot to add, very important; since this is about file download and you wish to do it from an HTML form that is being targeted to a PHP file, make sure to add the multiform-data to your form.
    What do you mean multiform-data.....

    it will be 11 butons for example, each one is coded with hidden value that is posted to download.php which would know what to do. or am I on the wrong track?
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

  34. #34
    Join Date
    Mar 2006
    Posts
    965
    it will be 11 butons for example, each one is coded with hidden value that is posted to download.php which would know what to do. or am I on the wrong track?
    Sorry for the late response. It's early here . . .

    Here's an example of what I meant:

    regular form expression:

    Code:
    <form action="your_file.php" method="post">
    <input type="hidden" name="your_action_name" value="your_variable_name">
    ... and so on ...
    multipart/form (not just form - sorry about that) :

    <form method="post" action="your_file.php" enctype="multipart/form-data" onsubmit="uploadbutton.disabled=true;">
    As you can see, the enctype has been added. I also added the option to decline multi-clickings (on the same form process) to avoid trafic and server ressources abuse.

  35. #35
    Join Date
    Feb 2003
    Location
    AR
    Posts
    2,381
    Once again, you are absolutely incorrect here horizon. You use the multipart/form-data enctype when the script is handling file uploads. That's all that it is used for. It really has no place in this form, since this form is just posting information to another script.....

    http://www.w3.org/TR/html4/interact/...ml#h-17.13.4.2

  36. #36
    Join Date
    Nov 2005
    Location
    USA
    Posts
    874
    just to be clear... the button is supposed to go to a script that would download the form and not upload it. the user can only download files that are assigned to him, will not upload anything
    GS RichCopy 360 Enterprise - Voted #1 for data migration and replication in terms of performance and features. Replicate data across between servers in the same network, WAS, or even across the internet

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •