Board index » delphi » how to hide path in isapi call

how to hide path in isapi call


2008-04-16 08:10:57 AM
delphi132
We have an isapi dll that now works beautifully. It accepts a parameter
with an id number in it & returns nicely formatted html. However, the
concern is to avoid giving a curious user the ability to edit the id number
and get back something that doesn't belong to him.
We could of course use the request object and read fields from the calling
page, which might make it harder to for the curious to experiment on. But
this increases the coupling between the web page and the dll.
We've also talked about writing something to scrample the id. It would need
a check-digit or such to prevent tinkering, but it could be done. Any
thoughts on this?
And also, we could pass in the id plus another value that had to somehow
match it. Only a valid pair would be allowed.
Jeremy
 
 

Re:how to hide path in isapi call

Couple of suggestions:
- Whenever we use an identifier to identify an entity, we *always* check that the user is allowed to see that particular entity (e.g. invoice). So if you were running a query to show the details of the selected invoice, you would use a query like "select * from invoices where id = ? and customer = ?". You would typically pull the customer identifier from the session information.
- You could MIME encode the Id to stop casual users from modifying it. Very fast but very unsecure. It is more security through obscurity rather than actual security.
- You could actually encrypt it using a symmetric algorithm. E.g. BlowFish, etc. You could store the key in an INI file and regularly update it (e.g. when doing an update to the application - though you'd have to watch out for id's using the old key).
- Use a UID (e.g. A01D602D-9020-41B8-938C-E59EF4BA94C0) to identify the entity rather than a sequential identifier. *very* difficult to guess another UID that way. What we do is have an internal identifier (e.g. primary key) which is typically an int but have a external identifier, a GUID, which users (customers, external applications via API's) use to refer to that particular entity. This assumes your database supports GUID data types.
 

Re:how to hide path in isapi call

Nicholas, thanks, these are some great ideas. GUIDs would be great. If I
understand correctly, the probability that our database of a million or so
records would have 2 GUIDs that differed by only a few digits is pretty
small, and the likelihood of morphing one into another with a small change
would be microscopic.
The other one that strikes me as clever is using 2 (or more) facts that have
to agree, but are otherwise independent (invoice id + customer id). So
simple, but pretty effective. And we don't even have to add a column to a
table!
Jeremy
"Nicholas Brooks" <XXXX@XXXXX.COM>writes
Quote
Couple of suggestions:

- Whenever we use an identifier to identify an entity, we *always* check
that the user is allowed to see that particular entity (e.g. invoice). So
if you were running a query to show the details of the selected invoice,
you would use a query like "select * from invoices where id = ? and
customer = ?". You would typically pull the customer identifier from the
session information.

- You could MIME encode the Id to stop casual users from modifying it.
Very fast but very unsecure. It is more security through obscurity rather
than actual security.

- You could actually encrypt it using a symmetric algorithm. E.g.
BlowFish, etc. You could store the key in an INI file and regularly
update it (e.g. when doing an update to the application - though you'd
have to watch out for id's using the old key).

- Use a UID (e.g. A01D602D-9020-41B8-938C-E59EF4BA94C0) to identify the
entity rather than a sequential identifier. *very* difficult to guess
another UID that way. What we do is have an internal identifier (e.g.
primary key) which is typically an int but have a external identifier, a
GUID, which users (customers, external applications via API's) use to
refer to that particular entity. This assumes your database supports GUID
data types.
 

Re:how to hide path in isapi call

If you make good use of your sessions you can store most of the id variables
in the session, rather than pass them as fat URLs. My main always passes
foreign keys but never shows them in the HTML or web address, only the
session number ever comes in the URL.
Using a customer ID to cross check the right to access the data is always a
good idea. At critical data entry and edit points I always check the CID (in
SQL) but not just for reports. The session number itself is pretty good
defense.
You can write an ISAPI filter to mask the URL but this is complex, I gave
up.
In my newest app I send every get and post request from javacsript. The A
link attribute is "#" then I have an onclick event to call the javascript
function to send the request, passing the params as javascript variables.
This hides the params from the URL and the URL always presents as www
mydomain com/#. In this case the params are clearly visible in the html as
part of the javascript call but you can remove white space in your html to
make it hard.
Finally you can hide the HTML, thereby totally obscuring any visibility of
javacsript parameters from the page by using the XMLRequestObject (find a
function from a toolkit) from the Javascript calling function. Wriet the
response to the page at a div using InnerHTML or by using DOM, or a
combination of both. The HTML will never be visible in View Page Source
(somebody might correct on this but its certainly the case in IE and, I
think, in Firefox). A links will always show your domain name only.
Email me me and i will send a link that demonstrates this. It is pure ISAPI
web broker.
hth
Mark Horrocks
 

Re:how to hide path in isapi call

For the casual user yes it'll be hidden, but for someone with firefox
and firebug not so much.
DD
 

Re:how to hide path in isapi call

In my apps, I allow an ID on the address line but I always confirm in my
code that a user has access to that ID. For instance:
function ReturnPage(UserID, InvoiceID): string;
begin
CheckAccess(UserID, InvoiceID); // raises exception if no access
Result:= BuildPage(InvoiceID);
end;
-Bill