0

I am trying to create a dynamic data catalog for products depends on a JSON object that contains some columns name from database, for example:

{
    'name':'clothes-for-men',
    'action':'Category',
    'id':'Products.cat_id'
}

where Products is a table in database, Products.cat_id category is also a table and cat_id is a reference to that specific category.

That JSON object is dynamic, because i have yet another categories-based , subcategory and under subcategory, so its like a mega dropdown menu, on each anchor i have an angularjs ng-click event:

<ul class="menu-category">
    {% for category in g.category %}
        <li class="has-submenu">
            <a href="javascript:void(0)" class="text-dark" ng-click="get_products_by_category({'name':'{{category.slug}}', 'action':'Category', 'id':'Products.cat_id'})">{{category.name}} </a>
            <ul class="submenu p-5">
                <div class="row">
                    {% for sub_cat in category.sub_menu %}
                        <div class="col-sm-4 mb-5">
                            <h4><a href="javascript:void(0)" ng-click="get_products_by_category({'name':'{{sub_cat.slug}}', 'action':'SubCategory', 'id':'Products.sub_id'})" class="text-primary">{{sub_cat.name}}</a></h4>
                            {% for sub_und in sub_cat.unders %}
                                <li> <a href="javascript:void(0)" class="text-dark" ng-click="get_products_by_category({'name':'{{sub_und.slug}}', 'action':'SubUnder', 'id':'Products.under_id'})">{{sub_und.name}} </a></li>
                            {% endfor %}
                        </div>
                    {% endfor %}
                </div>
            </ul>
        </li>
    {% endfor %}
</ul>

All that because , i don't want to create an if statement for each event, i just did the following, i am getting the id as a string and converting it to class object in the back-end using method eval(), here is an example:

if data_page.get('category'):
    ob = data_page.get('category')
    test = Products.query.join(eval(ob['action']), eval(ob['action']).id == eval(ob['id'])).order_by(Products.published.desc()).all()

So again the question is, is it safe to do that? and does that lead to sql injection vulnerability?, in fact, i tried to manipulate the value of id using inspect element, but it didn't get changed in the back.

swordfish
  • 959
  • 16
  • 39
  • 1
    Using `eval` on arbitrary user input is really really dangerous and is likely the biggest vulnerability you could introduce. If it's self contained and there is no way for a user to modify this JSON schema that you control, then sure it's "safe" but I think any use of eval in code is a code smell anyway since it could lead to situations where people misunderstand the danger and use code that uses `eval` on user input. It's hard to say exactly what you should be doing instead from this snippet alone, but have you considered not doing this dynamically from config? – Rach Sharp Jun 13 '19 at 14:04
  • I am 100% sure that there is no way for a user to modify the schema, even if there is a way, i am protecting every single request with CSRFToken protection also , i am disallowing any incoming request , so i feel it's safe. – swordfish Jun 13 '19 at 17:35
  • 2
    More than likely there is a safer way to accomplish what you are after that does not involve exposing yourself. You say that those values come from the DB, but how did they get there? Could the user influence that? Anyway, `ob['action']` is the name of a class, so create a mapping `dict` and look the actual class up from that. No `eval` needed. `ob['id']` is a bit trickier, but doable in the same fashion. – Ilja Everilä Jun 13 '19 at 18:04
  • 1
    Values are classes in my DB models, and yep, I've already changed that to exactly what you said, now no eval() method needed ;) – swordfish Jun 14 '19 at 01:01

0 Answers0