logo

Hacking Domino: Over-riding Hidden or Computed Field Values

It might be old news to some, but have you seen how easy it is for a (power) user to alter a web form so they can pass any field values they like back to the server!?

As an example, let's say you have a form with a computed field called Status on it. In edit mode the field's value is displayed to the user, like so:

 

 Screen1

Now let's look at how easy it is to turn this computed field in to an editable one. Assuming you have Firebug installed, right click the Draft message (or anywhere on the page for that matter) and select Inspect Element. You'll then be able to edit the HTML that forms the page, like so:

 

Screen2

What if you edit the text and replace it with some HTML, like so:

 Screen3

 

Now look at the web page again; there's a field where the wasn't one before:

Screen4

Imagine this happening in a workflow scenario where you'd expect the newly-submitted document to have a Status of "Awaiting Approval", but, as you can see above, they've managed to jump past approval and get it published straight away.

Now imagine it happening in a shopping cart scenario where you skipped the "Awaiting Payment" status and went straight to "Paid", which triggers the logic in the WQS event to mail out the merchandise. Hey, it could happen.

Even if no harm is done there's always the embarrassment factor and it never looks good if a solution you've sold a customer is "hackable".

What I can't work out is how to counter an attack like this. In a SQL-based environment, when a form is submitted you can use an Update() request to change the stored values of only certain "fields" -- the ones you'd expect to be "editable" by the user. In Domino there's no way to easily say "hang on, how come that fields changed?" or "Hey that shouldn't have changed, let's change it back to what it was. Hang on, what was it again?"

Any ideas on this one folks? Is it just a case of trusting your users either not to know how to or simply not wanting to hack you site?

Comments

  1. Just thinking out loud....

    what about the referral url, to determine new document vs edit document and then in the query save removing all items that you weren't expecting and setting key fields to the correct value.

    just an idea - never tried it.

  2. You could leave the field out of the form that the user sees, and set it with WQS.

    If you want the admin/etc to see it, use computed subform.

    Maybe use two fields for extra security. One "visible" to the user, and one admin-only (for approval).

    Another approach is server-side validation based on roles. If a user is a customer, he can only submit certain kind of values. If status=Paid -> status=Invalid.

    • avatar
    • Jake Howlett
    • Wed 24 Sep 2008 05:17 AM

    Tony,

    Not sure about the new vs edit bit (what about .isnewnote?) -- why is that significant?

    The trouble with WQS (as I understand it) is that the document context object is the same thing as the document object that is actually stored, so there's no way of comparing the field values being submitted to field values stored, which is a shame.

    Tommy,

    I think I see what you mean. Surely though, if the field exists on the backend document the user can "inject" it, even if they don't see the subform that the actual field exists on? I'd have to test that.

  3. Been there. Done that. Having an eCommerce site of my own (www.up1.co.uk) I have had these sort of attacks (and more) for the past 10 years. There are a lot of tricks you can use to detect this sort of thing. there are also a lot of tricks which you can do to prevent this sort of thing too.

    In fact for the past 3 years I have been submitting proposals to Lotusphere entitled "Hacking the Domino Server for fun and profit". They keep getting rejected (maybe because they don't like admitting that even the most secure application can break under a determined hacker). I guess i ought to submit them to ILUG or UKLUG as well. Might go down better with that crowd.

    E-commerce crime is big "business". Not a week goes by without some news reports about servers being hacked. Credit Card or personal data being stolen. It all ends up in the hands of the criminals. Domino is pretty secure, but if you don't consider how you write your web facing apps then then can break under the slightest pressure.

    My servers are attacked about 15-20 times a day. Having an SSL cert automatically means you are a logical target for potential thieves. My best advice would be to never, ever have live data on an expose app. UP1 is purely a gateway to a secure internal database which is never exposed, the external app itself only contains the stock listings.

  4. I think the trick is to only pass a temporary document back to the user, and let them do whatever they want. And only update the 'real' document from the proxy document...

    ---* Bill

    • avatar
    • Jake Howlett
    • Wed 24 Sep 2008 05:44 AM

    Tommy,

    Looks like I was wrong. As you suggested, putting the restricted fields on a subform, which the user can't see, stops them being able to edit them. I'd thought that the "field" just had to exist in the backend document to allow editing. Did that change at some point?

    A useful lesson anyway. Thanks Tommy!

    Dragon and Bill,

    What you're suggesting then is to design outside of the standard Domino paradigm and separate the form the user sees from the stored document with a WQS agent to tie the two together? Seems a big step to take, but, I guess, should the situation demand that level of paranoia it's the only way to go. So you'd never see a ?EditDocument URL?

    PS: What's UP1 Dragon?

    PPS: If you want to write about what you know I'd be happy to let you publish here if it's useful for the wider community and all that.

  5. This may seem like a silly question so please be gentle but doesn't the user need to know the name of the underlying field? Or is there a way to find out the field names?

    Surely some cryptic field naming would get around this.

    • avatar
    • Jake Howlett
    • Wed 24 Sep 2008 06:18 AM

    Not a silly question Adrian. Yes, they'd need to know the name. Like most hacking (I'd guess) it involves a certain amount of trial and error guesswork to make it work. Oddly-named fields would make it much harder.

    The trouble might come if your site is based on a freely-available template.

    • avatar
    • YoGi
    • Wed 24 Sep 2008 06:20 AM

    @Adrian : Security through obscurity is never a good solution.

    One way to prevent this (without hiding restricted fields) would be to override Domino's paradigm while submitting to agents which gather parameters and update/save the underlying documents manually (a variant of Bill's method)

    I've done that before (at the time I needed to handle data, because in some cases Domino has decoding issues), but that requires a lot of work. Way too much to stick with that platform, imho.

    • avatar
    • Mats Hasselquist
    • Wed 24 Sep 2008 06:24 AM

    Jake

    You can compare the submitted values against the ones that are stored. What you need to do is to pick the document using the unid like

    Set Context=Session.DocumentContext

    Set Db=Session.CurrentDatabase

    Set Doc=Db.GetDocumentByUNID(Context.UniversalID)

    and there you have your already saved copy of the document ready for comparsion.

    • avatar
    • Jake Howlett
    • Wed 24 Sep 2008 06:31 AM

    Mats,

    Are you sure about that? I'd always thought the two objects were, in effect, the same thing?

  6. "PS: What's UP1 Dragon?"

    Link - my ecommerce site. Well mine as in I wrote it, but not mine as in I own the company.

    • avatar
    • Glen Urban
    • Wed 24 Sep 2008 06:37 AM

    Jake,

    don't know if this is useful in your scenario but you can tick the "must have at least editor access to use" option on a field and limit end user access to Author.

  7. "What you're suggesting then is to design outside of the standard Domino paradigm and separate the form the user sees from the stored document with a WQS agent to tie the two together? Seems a big step to take, but, I guess, should the situation demand that level of paranoia it's the only way to go. So you'd never see a ?EditDocument URL?"

    Exactly. When you have credit card info or customer data you MUST take every precaution not to expose that data. On UP1 if somebody requests a "My Account" update then a temporary document is created (albeit minus some very important details such as the credit card number). That document will only last for a maximum of 10 minutes after creation/modification by the user, and it will never directly update the original document. It is added and a change logged in against it which is resolved at a later date *if* somebody places an order afterwards. (Stops people creating a valid account, submitting on order, then changing the billing/deliver address after ordering).

    • avatar
    • jay
    • Wed 24 Sep 2008 06:47 AM

    Mats is right, you can get hold of the back-end/stored document and the one in context. The solution is also sitting on codestore ;). See Matt Holthe's comment from here => Link

    • avatar
    • Matt Holthe
    • Wed 24 Sep 2008 06:52 AM

    I've done pretty secure web sites in the past, and one technique I used was a temporary database visible to end users and a "true" database with no web access available to Notes. Submitting in the temporary database would update the "true" database. I wouldn't blindly update all the fields in the documents - only the ones that were supposed to change. It was a bit more work to set up, but I knew the data integrity would be there.

    • avatar
    • Mats Hasselquist
    • Wed 24 Sep 2008 06:53 AM

    Jake

    Yes I',m sure, I have used it. I haven't tested it on Domino 8 but see no reason to why it shouldn't work there. DocumentContext is the in-memory document but Db.GetDocumentByUNID picks the document saved in the database. If that solution should of some strange reason fail you can always create a view sorted by @Text(@DocumentUniqueID) and then do a

    Set Doc=view.GetDocumentByKey(Context.UniversalID, True)

    • avatar
    • Erik brooks
    • Wed 24 Sep 2008 08:19 AM

    Have you reported this with an SPR? Domino already has quite a bit of field-level security happening on-post.

    For example, if you submit a file in the POST when there are no file-upload controls on the form, Domino ignores the file (I can't remember whether it throws an error or just processes the rest).

    I thought it did the same thing with fields (e.g. you can't simple submit a value for a field unless it is editable). Are you certain this works?

    • avatar
    • Glen Urban
    • Wed 24 Sep 2008 08:21 AM

    Another thing occured to me with the field option "must have at least editor access to use". This option can be set and re-set in LotusScript via the IsProtected property of NotesItem. This means that, for example, the Status field could be protected from end user interference but still updated in the WebQuerySave by resetting the IsProtected flag, updating the item's value and then setting the IsProtected flag again. I've just tried it and it works a treat.

    This is ideal for my own applications as I never give end users higher than Author access, prefering to use roles to grant access to documents where required.

    • avatar
    • Ferdy
    • Wed 24 Sep 2008 08:32 AM

    Jake,

    I can confirm what Mats is saying, this does work. To me it looks like the best, less obscure method of detecting such attacks. Notice how it is the same advise I gave you a few weeks back concerning the orchestration of two agents that needed shared access to the same doc.

    regards,

    Ferdy

    • avatar
    • Partha
    • Wed 24 Sep 2008 09:06 AM

    May be a dumb question, but how does the hacker know the computed field name is status?

  8. @Jake: The subform behavior has been like that as long as I've worked on Domino. I started out on 7.

    What's great is that the form is computed even when you don't open it in a web browser.

    If a (computed) subform only is visible when a user with a certain role opens the form, the same is true for a ?SaveDocument/?CreateDocument Post-request is issued.

    AFAIK only agents can circumvent this behavior.

    • avatar
    • serge
    • Wed 24 Sep 2008 10:39 AM

    I like Matt Holthe's solution. I would use a transaction based system where only relevant fields in the secure database are updated from the transaction form submitted by user.

    • avatar
    • Mark C.
    • Wed 24 Sep 2008 12:01 PM

    I ran into a problem a little while ago that might be a solution here.

    I had multiple address fields and if the "Same as above" check box was checked, I'd disable the second set of fields and update them with JavaScript if the user changed the details of first set of fields.

    The problem was that the updated second set of fields wouldn't be saved when the document was submitted. I solved it by re-enabling the fields when the user clicked "Submit".

    I don't know if the enabled/disabled property is something that Firebug could be used to change as well, simply adding one more step to the hack.

  9. You could store a list of valid fields in a control or profile document and use them to tell you if a field is valid for this transaction. Get a list of fields from the DocumentContext doc and compare each field to your list of valid fields for this web form. If the field is not valid then you could delete the field from DocumentContext or quarantine the document for review. You would need to remember to not delete the extra field used by Domino for check boxes and radio buttons.

    You can also use Matt Holthe's method Link of getting the "realdocument" and verify that the current status is correct for this transaction. You could check the source document to see if the web page can change the status from "Awaiting Payment" to "Paid".

    The first method prevents the web user from submitting fields they shouldn't have access to and the second method checks the validity of the contents of the field for the type of transaction.

    Also, especially for a shopping cart application, fields should never be stored on the web form. They should only reside in the database. This prevents a user from changing an order of one item at 10.99 to 100 items at 10.99.

    BTW, in IE you can change input fields, hidden or otherwise using the javascript: URL command or the Mouseover DOM Inspector Link

    • avatar
    • Jake Howlett
    • Thu 25 Sep 2008 02:02 AM

    Thanks for all the feedback guys! All very thought-provoking and useful stuff. Sorry I left in the middle of it.

    Weirdly, I still just can't get Mats code to work as expected and see the same result as I did 4 years ago (I'd half forgotten about that post jay) where the two reported values are the same. Matt Holthe's solution of setting the context document to nothing and back again still works, but I think I now prefer the db.getView("AllByUNID").getDocumentByKey(context.UniversalID) trick to get the backend document.

    However I still think I prefer Tommy's solution of putting access-restricted fields on a subform that normal users don't see. The only downside to this being that the fields in the subform don't get added to a *new* document following a ?OpenForm/CreateDocument request.

    Mark C. Disabled fields don't get submitted to the server by the browser. Yes, Firefox could re-enable the fields.

    As for using temporary documents for the user and real ones in the backend, which the user can't access, this is something I'd try and avoid if I can, for the obvious reasons.

    It's not that I have a current requirement that demands this level of paranoia. It's just that I've been doing quite a bit of work with XSS-prevention and editing hidden fields was one area I was looking in to. More late...

  10. @Jake: "The only downside to this being that the fields in the subform don't get added to a *new* document following a ?OpenForm/CreateDocument request."

    If you -really- want the field in the document, fill it with WQS if the document is new, or have another computed subform only visible to new documents with computed fields. Computed fields are the only (stored) fields the developer has full control over in regards to web applications.

    • avatar
    • mark bryson
    • Thu 25 Sep 2008 04:12 PM

    Firebug is a great weapon for developers and for hackers - a truly two-edged sword.

    My tip: avoid using fields when you just want to display a value by putting the field value in a computed-text field. If you need the value for javascript put an ID on the computed-text and get it that way. I can't see any reason why a computed field needs to be used as such on a web form.

    • avatar
    • Patrick Ryan
    • Fri 26 Sep 2008 02:46 AM

    Sorry to be a bit late into this ...

    A few years back (more than 5, I think), I wrote a CMS where the Domino database was only updated by a set of backend objects. Any submitted data would be processed by another set of objects (the business logic) which would then make calls to the backend objects. In essence, it was similar to what Matt Holthe was referring to.

    Granted, it's a lot of extra work, but it does get around this particular problem.

    There was also another reason for doing it on that project: they wanted to be able to port to a different database platform.

  11. @Mark C -- if you want to prevent users from accidentally editing a field but still want it submitted, use readonly rather than disabled.

  12. why not adding the computed values as data in an embedded image and abstract that data when saving the document.

    probably with such a method 99% of most 'kiddy' hackers that try to run hacks read in books are filtered out.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Wed 24 Sep 2008

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

Elsewhere

Here are the external links posted on the same day.

More links are available in the archive »

More Content