I guess I need to look into the auth.signature functionality. We already had our grid conditional be db.pages.stores_id=STORE_INFO.id but we were able to edit Store 1's page while logged into Store 2's administration area, just by changing the ID in the URL. Are you saying that auth.signature will prevent this?

Kevin Cackler
Tech Daddies
501-205-1512
http://www.techdaddies.com

On 9/7/2012 2:39 PM, Massimo Di Pierro wrote:
In some sense the grid does what you say.

For example:

@auth.requires_login()
def index():
     db.define_table('thing',Field('name'),auth.signature)
     grid = SQLFORM.grid(db.thing.created_by==auth.user_id)
     return locals()

Notice all the URLs linked by the grid are digitally signed. They are one time URLs. They can only be used by the user within this session and they cannot be tampered with. For example replacing the id of a record with another record in the edit page will not give access to the other record because would break the signature. This was broken in 1.99.7 for the grid (and in fact it was experimental) but it is fixed in 2.0.x.

Users can digitally sign any URL:

def index():
    ...
    link = URL('edit',args=id,user_signature=True)
    return dict(link=link)

@auth.requires_signature()
def edit():
    ...

Now the http://.../edit/<id>?signature=<signature> is still the id of the record but without the signature the URL is not valid.





On Friday, 7 September 2012 13:27:49 UTC-5, MichaelF wrote:

    Thanks, Massimo.

    Re. needing a way to reference individual records: of course. But
    it doesn't have to be the internal record id (primary key value).
    The php code we used gave out unique-per-request values so that
    one couldn't, say, use a key retrieved from one form in another form.

    The @auth infrastructure is great. It's not a record-level design
    (or is it?). I just hate to think that internal db keys are public
    info. Okay, perhaps I'm going over the edge being worried about
    exposing database primary keys. But I find that when I decide I'm
    going over the edge, that means that some cracker will find a way
    to use that information against my site.

    I don't think web2py is much different from other infrastructures
    on this issue. I wanted to know what others thought; thanks for
    your reply.

    Michael

    On Friday, September 7, 2012 10:28:08 AM UTC-6, Massimo Di Pierro
    wrote:

        I strongly disagree with this.

        Publishing record IDs does not imply indirect object reference
        vulnerability. Any application that publishes record
        information must have a way to reference individual records.
        If the individual access is not validated than the app is
        vulnerable to indirect object reference, whether or not the
        reference is done by id or not.

        Who can access what is a matter of policy and policy must be
        implemented by the developer. Web2py provides the
        @auth.requires_permission and @auth.requires_membership and
        $auth.requires_signature.

        Massimo

        On Friday, 7 September 2012 09:22:12 UTC-5, MichaelF wrote:

            I appreciate that web2py has ways to handle this, and I
            also agree that it's somewhat hackish. The problem
            remains, though, that we're still exposing (publishing)
            internal primary keys to the browser. Isn't the main
            problem the fact that we're dealing with primary key
            values being sent to the browser? Look at
            https://www.owasp.org/index.php/Top_10_2010-A4
            <https://www.owasp.org/index.php/Top_10_2010-A4> for one
            description of the vulnerability.

            In our php application we wrote a class that hashed
            primary keys sent to the browser, giving different hashes
            on each GET/POST so that, for example, the hashed primary
            key 1 would different if the user visited the same page
            two times.

            Thoughts?

            Thanks.

            On Thursday, September 6, 2012 8:18:44 AM UTC-6, Anthony
            wrote:

                How about
                http://web2py.com/books/default/chapter/29/06#Common-filters
                <http://web2py.com/books/default/chapter/29/06#Common-filters> 
or
                
http://web2py.com/books/default/chapter/29/06#Common-fields-and-multi-tenancy
                
<http://web2py.com/books/default/chapter/29/06#Common-fields-and-multi-tenancy>?


                Anthony

                On Wednesday, September 5, 2012 8:48:49 PM UTC-4,
                Kevin C wrote:

                    We did something similar but it feels very
                    hackish, considering it has to be done in every
                    method of the admin controller.  I just wanted to
                    see if there was a better way.

                    Thank you.

                    Kevin Cackler
                    Tech Daddies
                    501-205-1512
                    http://www.techdaddies.com

                    On 9/5/2012 7:45 PM, Bruno Rocha wrote:
                    You can do:

                        if request.args(0) in ['edit', 'delete']:
                            STORE_DETAILS.id == int(request.args(2))
                    or redirect(URL('default', 'wherever'))

                    db.pages.stores_id.default = STORE_DETAILS.id
                        query = ((db.pages.stores_id ==
                    STORE_DETAILS.id))
                        form = SQLFORM.grid(query=query)

                        return dict(form=form)



                    On Wed, Sep 5, 2012 at 9:38 PM, Kevin C
                    <[email protected]> wrote:

                        Basically, we are generating a SQLFORM.grid
                        with the following code:

                        db.pages.stores_id.default = STORE_DETAILS.id
                            query = ((db.pages.stores_id ==
                        STORE_DETAILS.id))
                            form = SQLFORM.grid(query=query)

                            return dict(form=form)

                        This is working perfectly fine for us.
                         However, we have noticed that if we just
                        change the ID in the query string for the
                        edit page, we are allowed to edit other
                        store's entries.

                        IE
                        
http://test.oursite.com/test/admin/pages/edit/pages/6?_signature=f8c5560743.
                        
<http://test.shofty.com/shofty/admin/pages/edit/pages/6?_signature=f8c55607435864253b5f5b37a6b7109956e4a8fa>..

                        What is the proper way to do this, then?  The
                        grid itself looks great, but just by changing
                        the page ID in the URL, we are allowed to
                        edit pages not belonging to us.  I guess I
                        was hoping that the query conditional would
                        be passed to each function (add, edit,
                        delete) but that obviously is not the case.
                         Is multi-tenancy the solution to this issue
                        or are we overlooking something simple?
--




--



--




--



Reply via email to