user3138518
user3138518

Reputation: 11

How to Prevent direct access of PDF or xls or doc files in IIS 6.0

We have got a site (eg abc.com) that is built in classic ASP and hosted on IIS 6.0. We have got a content folder in IIS 6.0, which consists of static files like PDF or XLS. We came to know recently that in various search engines, direct links of our website (www.abc.com/content/xyz.PDF) to PDF/xls are getting displayed in the search results and any user can access those files directly. As these files should be accessible to only logged in users, what is the way of preventing the anonymous users from accessing those files directly. We are using cookie and database for authenticating a valid user. The actions we have taken so far are:-

1) Included robots.txt in our website and through various webmaster tools, prevented the listing of direct links in the search results but we don’t think it is the optimal solution.

2) In our website there were various functionalities, through which the links to direct access of PDF’s were used to show it to the user. That we have stopped by not showing the direct URL path to the user.

Questions: - As we are using IIS6.0 and classic ASP, is there any way to implement anything at IIS level to prevent direct access of PDF/XLS files. Like, if the user types ‘www.abc.com/temp/xyz.PDF’ or the url consisting of .pdf/.xls should be intercepted by our asp or any other page first for the authentication(to check the user is logged in or not) and based on that it should allow to open.

Upvotes: 1

Views: 3511

Answers (2)

vespadj
vespadj

Reputation: 1

David code falls in "intFilelength \ chunck" : chunck is 0. Insert a declaration:

Dim chunck
chunck = 2^13 '8K

Many others related questions tells also about:

Call Response.AddHeader("Cache-Control", "private, max-age=1")

Upvotes: 0

David
David

Reputation: 1613

Our company have a similar type of website, with lots of file that must not be accessible by anyone except the user who uploaded the file. We solved it like this:

  1. Place all the content files outside the web site directory. This means that no-one can access the files, even if they know the complete path of a file.
  2. Give the Website READ access to the content directory.
  3. Build a script that can deliver a single file on request. This file makes sure that a user must be logged on before any file can be downloaded.
  4. on the html page, instead of linking directly to the file, have a link that looks something like this      <a href='downloadFile.asp?fileID=2341'>appManual.pdf</a>

Example of 'download-file-code'

dim filePath

'Is user logged on?
if Session("userID") > 0 then
    'Good, the user is logged on.
    'See if we can find the file the user is requesting
    filePath = GetFilePAthFromDatabaseByID(request("fileID"))
    if filePath != "" AND DoFileExists(filePath) then
        'We found the file, send it to clients browser
        SendFileToClient(filePath)
    else
        response.write "Sorry, we can't find the file with ID = " & request("fileID")
    end if
else
    response.write "Sorry, you are not allowed to download files unless you are logged on"
end if




Function DoFileExists(filePath)
    dim fso
    Set fso = Server.CreateObject("Scripting.FileSystemObject")  
    if fso.FileExists(filePath) then  
        'return value
        DoFileExists = true
    else
        'return value
        DoFileExists = false    
    end if 
End Function


Function SendFileToClient(strFile,strFileEnd)  
    dim objText, strContentDisp, strFilename, strm, fso, fsofile, intFilelength, icount, oldScriptTimeout

    strFilename = strFile

    'Important that buffer is set to false to be able to handle big documents extending the buffer size
    'the binary documents is sent in chunks to the client.......
    'Leaving buffer to true will cut-off the binary stream at "buffer full" and the document is not readable by the client.
    Response.Buffer = False 

    Set strm = Server.CreateObject("ADODB.Stream")  
    strm.Open
    strm.Type = 1

    Set fso = Server.CreateObject("Scripting.FileSystemObject")  
    if not fso.FileExists(strFilename) then  
        Response.Write("The corresponding file does not exist")
        Response.End  
    end if  

    Set fsofile = fso.GetFile(strFilename)  
    intFilelength = fsofile.size  
    strm.LoadFromFile(strFilename)   


    'All the known filetypes below will be sent to the browser as a known MIME type, this will embed and open the documents 
    'directly in the browser.
    'If some of the document types are to be opened in an full application instead of a browser embedded application, just comment out
    'the case section containing the extension type and the file will be downloaded as an "application/octet-stream"

    'Default Content-Disposition
    strContentDisp = "filename=" & fsofile.name     


    select case ucase(strFileEnd)
    Case "TIF", "TIFF"
        Response.ContentType = "image/tiff"
    Case "GIF"
        Response.ContentType = "image/gif"
    Case "JPEG", "JPG"
        Response.ContentType = "image/jpeg"
    Case "PNG"
        Response.ContentType = "image/png"
    Case "BMP"
        Response.ContentType = "image/bmp"
    Case "PDF"  
        Response.ContentType = "application/pdf"
    Case "XLS"
        Response.ContentType = "application/vnd.ms-excel"
    Case "DOC"
        Response.ContentType = "application/msword"
    Case "TXT"
        Response.ContentType = "text/plain"
    Case "HTM", "HTML"
        Response.ContentType = "text/html"
    Case "XML"
        Response.ContentType = "text/xml"
    Case Else
        strContentDisp = "attachment; filename=" & fsofile.name  
        Response.ContentType = "application/octet-stream" 
        Response.CharSet = "UTF-8"  
    End Select

    Response.AddHeader "Content-Disposition", strContentDisp
    'Remove setting of content-length when using IIS 7.5 since it does not work there
    Response.AddHeader "Content-Length", intFilelength 

    'Set the Timeout to a large value when downloading big documents
    oldScriptTimeout = Server.ScriptTimeout
    Server.ScriptTimeout = 30000 


    For icount = 1 To intFilelength \ chunk 
        If Not Response.IsClientConnected Then Exit For 
        Response.BinaryWrite strm.Read(chunk) 
    Next 

    If intFilelength Mod chunk > 0 Then 
        If Response.IsClientConnected Then 
            Response.BinaryWrite strm.Read(intFilelength Mod chunk) 
        End If 
    End If 

    Response.Flush  
    Response.Buffer = True

    'Reset the original timeout
    Server.ScriptTimeout = oldScriptTimeout 

    strm.Close  
    Set strm = Nothing  
    set fsofile = Nothing 
End Function

Example of custom 404-page

<%
dim downloadURL, url, urlPattern, arrTmpUrl, arrTmp
dim filename, fileID

' ** Base path for downloads (new)
downloadURL = "http://www.yourDomain.com/downloadFile.asp?fileID="
' ** Fetch QUERY_STRING  (this tells us which page the user tried to access)
url = Request.ServerVariables("QUERY_STRING")
' ** URL pattern  (did the user try to download a content file?)
urlPattern = "^(http://|http://www.|www.)yourDomain.(se|com):80/(ContentDir|AltContentDir)/[a-zA-Z0-9_åäöÅÄÖ .]{2,100}/?$"

arrTmpUrl = split(url,"404;")
if  1 = (UBound(arrTmpUrl) - LBound(arrTmpUrl)) then
    if RegExTest(arrTmpUrl(UBound(arrTmpUrl)), urlPattern) Then
        arrTmp = split(arrTmpUrl(UBound(arrTmpUrl)),"/")
        filename = trim(arrTmp(UBound(arrTmp)))

        'See if we can find the file name in database
        fileID = GetFileIDFromDatabaseByName(filename)
        if fileID > 0 then
            downloadURL = downloadURL & Cstr(fileID)

            'Redirect user to proper download link
            response.redirect downloadURL
        else
            'We did not find a matching file
            'Show standard 404 page
            ShowStd404Page("We did not find a matching file")
        end if
    else
        'The URL did not match the pattern
        'Show standard 404 page
        ShowStd404Page("no match")
    End if
else
    'The queryString did not look like as expected
    'Show standard 404 page
    ShowStd404Page("unexpected queryString")
End if
%>

Upvotes: 2

Related Questions