com.denimgroup.threadfix.data.dao.hibernate.HibernateVulnerabilityDao.java Source code

Java tutorial

Introduction

Here is the source code for com.denimgroup.threadfix.data.dao.hibernate.HibernateVulnerabilityDao.java

Source

////////////////////////////////////////////////////////////////////////
//
//     Copyright (c) 2009-2015 Denim Group, Ltd.
//
//     The contents of this file are subject to the Mozilla Public License
//     Version 2.0 (the "License"); you may not use this file except in
//     compliance with the License. You may obtain a copy of the License at
//     http://www.mozilla.org/MPL/
//
//     Software distributed under the License is distributed on an "AS IS"
//     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//     License for the specific language governing rights and limitations
//     under the License.
//
//     The Original Code is ThreadFix.
//
//     The Initial Developer of the Original Code is Denim Group, Ltd.
//     Portions created by Denim Group, Ltd. are Copyright (C)
//     Denim Group, Ltd. All Rights Reserved.
//
//     Contributor(s): Denim Group, Ltd.
//
////////////////////////////////////////////////////////////////////////
package com.denimgroup.threadfix.data.dao.hibernate;

import com.denimgroup.threadfix.data.dao.VulnerabilityDao;
import com.denimgroup.threadfix.data.entities.*;
import com.denimgroup.threadfix.data.enums.VulnerabilityDefectConsistencyState;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Calendar;
import java.util.List;
import java.util.Map;

import static com.denimgroup.threadfix.CollectionUtils.list;

/**
 * Hibernate Vulnerability DAO implementation. Most basic methods are
 * implemented in the AbstractGenericDao
 * 
 * @author mcollins, dwolf
 */
@Repository
public class HibernateVulnerabilityDao implements VulnerabilityDao {

    private SessionFactory sessionFactory;

    @Autowired
    public HibernateVulnerabilityDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Vulnerability> retrieveAllByApplication(int applicationId) {
        return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class)
                .createAlias("application", "app").add(Restrictions.eq("app.id", applicationId)).list();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Vulnerability> retrieveAllByGenericVulnerabilityAndApp(Vulnerability vulnerability) {
        return sessionFactory.getCurrentSession()
                .createQuery("from Vulnerability vuln where vuln.application = :appId "
                        + "and vuln.genericVulnerability = :gvId and vuln.expired = :false")
                .setInteger("gvId", vulnerability.getGenericVulnerability().getId())
                .setInteger("appId", vulnerability.getApplication().getId()).setBoolean("false", false).list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Vulnerability> retrieveByApplicationIdList(List<Integer> applicationIdList) {
        if (applicationIdList == null || applicationIdList.isEmpty()) {
            return list();
        }

        return sessionFactory.getCurrentSession()
                .createQuery("from Vulnerability vulnerability "
                        + "where vulnerability.hidden = false and vulnerability.application.id in (:idList)")
                .setParameterList("idList", applicationIdList).list();
    }

    @Override
    public List<Map<String, Object>> retrieveMapByApplicationIdList(List<Integer> applicationIdList) {

        return (List<Map<String, Object>>) sessionFactory.getCurrentSession()
                .createQuery("select new map( " + "vulnerability.genericSeverity.name as severity, "
                        + "vulnerability.genericVulnerability.name as genericVulnName, "
                        + "vulnerability.openTime as importTime, " + "vulnerability.closeTime as closeTime, "
                        + "vulnerability.active as active, " + "vulnerability.hidden as hidden, "
                        + "vulnerability.isFalsePositive as isFalsePositive, "
                        + "vulnerability.application.name as appName, " + "vulnerability.application.id as appId, "
                        + "vulnerability.application.organization.name as teamName, "
                        + "vulnerability.application.organization.id as teamId " + ") "
                        + "from Vulnerability vulnerability " + "where vulnerability.hidden = false and "
                        + "vulnerability.isFalsePositive = false "
                        + "and vulnerability.application.id in (:idList) " +
                        //                        "and vulnerability.active = true " +
                        "order by vulnerability.genericSeverity.name, vulnerability.application.name")
                .setParameterList("idList", applicationIdList).list();
    }

    @Override
    public Vulnerability retrieveById(int id) {
        Vulnerability vuln = (Vulnerability) sessionFactory.getCurrentSession().get(Vulnerability.class, id);
        if (vuln != null && !vuln.isExpired()) {
            return vuln;
        } else {
            assert false : "Attempted to retrieve invalid vulnerability id.";
            return null;
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Vulnerability> retrieveSimilarHashes(Vulnerability vulnerability) {
        return sessionFactory.getCurrentSession()
                .createQuery("from Vulnerability vuln where vuln.application = :appId "
                        + "and vuln.expired = :false " + "and (vuln.locationVariableHash = :lvHash or "
                        + "vuln.locationHash = :lHash or vuln.variableHash = :vHash)")
                .setString("lvHash", vulnerability.getLocationVariableHash())
                .setString("lHash", vulnerability.getLocationHash())
                .setString("vHash", vulnerability.getVariableHash())
                .setInteger("appId", vulnerability.getApplication().getId()).setBoolean("false", false).list();
    }

    @Override
    public void saveOrUpdate(Vulnerability vulnerability) {
        sessionFactory.getCurrentSession().saveOrUpdate(vulnerability);
    }

    @Override
    public void delete(Vulnerability vulnerability) {

        if (vulnerability.getDocuments() != null) {
            for (Document document : vulnerability.getDocuments()) {
                sessionFactory.getCurrentSession().delete(document);
            }
        }

        if (vulnerability.getEvents() != null) {
            for (Event event : vulnerability.getEvents()) {
                event.setVulnerability(null);
                sessionFactory.getCurrentSession().save(event);
            }
        }

        sessionFactory.getCurrentSession().save(new DeletedVulnerability(vulnerability));
        sessionFactory.getCurrentSession().delete(vulnerability);

    }

    /**
     * I would feel bad about having so much logic here but the alternatives are
     * passing in a query string which is a terrible idea or
     * having a ton of methods which also isn't any good.
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Vulnerability> retrieveActiveByAppIdAndPage(int appId, int page, int sort, int field, Integer cwe,
            String description, String severity, String path, String param, boolean open, boolean falsePositive,
            boolean hidden) {

        String[] headers = new String[] { "", "vuln.name", "severity.intValue", "surface.path",
                "surface.parameter" };

        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Vulnerability.class);

        if (hidden) {
            criteria.add(Restrictions.eq("hidden", true));
        } else {
            criteria.add(Restrictions.eq("hidden", false));

            if (!open && falsePositive) {
                criteria.add(Restrictions.eq("isFalsePositive", true));
            } else {
                criteria.add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false))
                        .add(Restrictions.eq("isFalsePositive", falsePositive));
            }
        }

        criteria.add(Restrictions.eq("application.id", appId)).createAlias("genericSeverity", "severity")
                .createAlias("genericVulnerability", "vuln").createAlias("surfaceLocation", "surface")
                .setFirstResult((page - 1) * 100).setMaxResults(100);

        // Add Filtering restrictions
        if (description != null) {
            criteria.add(Restrictions.like("vuln.name", "%" + description + "%").ignoreCase());
        }

        if (severity != null) {
            criteria.add(Restrictions.like("severity.name", "%" + severity + "%").ignoreCase());
        }

        if (path != null) {
            criteria.add(Restrictions.like("surface.path", "%" + path + "%").ignoreCase());
        }

        if (param != null) {
            criteria.add(Restrictions.like("surface.parameter", "%" + param + "%").ignoreCase());
        }

        if (cwe != null) {
            criteria.add(Restrictions.eq("vuln.id", cwe));
        }

        // Add Ordering
        if (sort != 1 && sort != 2 || field <= 0 || field > headers.length) {
            criteria.addOrder(Order.desc("severity.intValue")).addOrder(Order.asc("vuln.name"))
                    .addOrder(Order.asc("surface.path")).addOrder(Order.asc("surface.parameter"));
        } else {
            String item = headers[field];
            if (sort == 1) {
                criteria.addOrder(Order.asc(item));
            } else if (sort == 2) {
                criteria.addOrder(Order.desc(item));
            }
        }

        return criteria.list();
    }

    @Override
    public long getVulnCountWithFilters(Integer appId, String description, String severity, String path,
            String param, Integer cweInteger, boolean open, boolean falsePositive, boolean hidden) {

        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Vulnerability.class);

        if (hidden) {
            criteria.add(Restrictions.eq("hidden", true));
        } else {
            criteria.add(Restrictions.eq("hidden", false));

            if (!open && falsePositive) {
                criteria.add(Restrictions.eq("isFalsePositive", true));
            } else {
                criteria.add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false))
                        .add(Restrictions.eq("isFalsePositive", falsePositive));
            }
        }

        criteria.createAlias("genericVulnerability", "vuln").add(Restrictions.eq("application.id", appId));

        // Add Filtering restrictions
        if (description != null) {
            criteria.add(Restrictions.like("vuln.name", "%" + description + "%").ignoreCase());
        }

        if (severity != null) {
            criteria.createAlias("genericSeverity", "severity")
                    .add(Restrictions.like("severity.name", "%" + severity + "%").ignoreCase());
        }

        if (path != null) {
            criteria.createAlias("surfaceLocation", "surface")
                    .add(Restrictions.like("surface.path", "%" + path + "%").ignoreCase());
        }

        if (cweInteger != null) {
            criteria.add(Restrictions.eq("vuln.id", cweInteger));
        }

        if (param != null) {
            criteria.createAlias("surfaceLocation", "surface")
                    .add(Restrictions.like("surface.parameter", "%" + param + "%").ignoreCase());
        }

        return (Long) criteria.setProjection(Projections.rowCount()).uniqueResult();
    }

    @Override
    public long getVulnCount(Integer appId, boolean open) {
        return (Long) sessionFactory.getCurrentSession().createCriteria(Vulnerability.class)
                .add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false))
                .add(Restrictions.eq("isFalsePositive", false)).add(Restrictions.eq("application.id", appId))
                .setProjection(Projections.rowCount()).uniqueResult();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Vulnerability> getFalsePositiveVulnCount(Application application, boolean value) {
        return sessionFactory.getCurrentSession()
                .createQuery("from Vulnerability vuln where vuln.application = :appId "
                        + "and vuln.isFalsePositive = :fp")
                .setBoolean("fp", value).setInteger("appId", application.getId()).list();
    }

    @Override
    public void evict(Finding finding) {
        sessionFactory.getCurrentSession().evict(finding);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Vulnerability> retrieveByIdList(List<Integer> vulnerabilityIds) {
        return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class)
                .add(Restrictions.in("id", vulnerabilityIds)).list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public void markAllClosed(List<Vulnerability> vulns) {
        for (Vulnerability vuln : vulns) {
            if (vuln != null && vuln.isActive()) {
                vuln.setActive(false);
                vuln.setCloseTime(Calendar.getInstance());
                vuln.setFoundByScanner(false);
                determineVulnerabilityDefectConsistencyState(vuln);
                saveOrUpdate(vuln);
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void markAllOpen(List<Vulnerability> vulns) {
        for (Vulnerability vuln : vulns) {
            if (vuln != null && !vuln.isActive()) {
                vuln.setActive(true);
                vuln.setFoundByScanner(true);
                determineVulnerabilityDefectConsistencyState(vuln);
                saveOrUpdate(vuln);
            }
        }
    }

    @Override
    public boolean activeVulnerabilitiesExist() {
        return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class)
                .createAlias("application", "app").add(Restrictions.eq("app.active", true)).setMaxResults(1)
                .uniqueResult() != null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Integer> getTopTenVulnTypes(List<Integer> applicationIdList) {
        return sessionFactory.getCurrentSession()
                .createQuery("select vuln.genericVulnerability.id " + "from Vulnerability vuln "
                        + "where vuln.active = true " + "and vuln.hidden = false "
                        + "and vuln.application.id in (:ids) " + "group by vuln.genericVulnerability.id "
                        + "order by count(vuln.genericVulnerability.id) desc")
                .setParameterList("ids", applicationIdList).setMaxResults(10).list();
    }

    @Override
    public List<Object[]> getTopVulnsInfo(List<Integer> applicationIdList, List<Integer> vulnIds) {
        List<Object[]> results = sessionFactory.getCurrentSession().createQuery(
                "select vulnerability.genericVulnerability.id as genericVulnId, count(vulnerability) as vulnCount "
                        + "from Vulnerability vulnerability " + "where vulnerability.active = true "
                        + "and vulnerability.application.active = true "
                        + "and vulnerability.isFalsePositive = false " + "and vulnerability.hidden = false "
                        + "and vulnerability.application.id in (:appIds) "
                        + "and vulnerability.genericVulnerability.id in (:vulnIds) "
                        + "group by vulnerability.genericVulnerability.id " + "order by count(vulnerability) desc")
                .setParameterList("appIds", applicationIdList).setParameterList("vulnIds", vulnIds).list();

        if (results == null)
            results = list();
        return results;
    }

    public Criteria getActiveVulnCriteria() {
        return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class)
                .add(Restrictions.eq("active", true)).add(Restrictions.eq("hidden", false))
                .add(Restrictions.eq("isFalsePositive", false));
    }

    @Override
    public VulnerabilityDefectConsistencyState determineVulnerabilityDefectConsistencyState(
            Vulnerability vulnerability) {
        VulnerabilityDefectConsistencyState vulnerabilityDefectConsistencyState = null;

        Defect defect = vulnerability.getDefect();
        if (defect != null) {
            if (vulnerability.isActive() == defect.isOpen()) {
                vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.CONSISTENT;
            } else if (defect.isOpen()) {
                vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_CLOSED_DEFECT_OPEN_NEEDS_SCAN;
            } else {
                Calendar latestScanDate = null;
                for (Finding finding : vulnerability.getFindings()) {
                    Calendar scanDate = finding.getScan().getImportTime();
                    if ((latestScanDate == null) || scanDate.after(latestScanDate)) {
                        latestScanDate = scanDate;
                    }
                    if (finding.getScanRepeatFindingMaps() != null) {
                        for (ScanRepeatFindingMap scanRepeatFindingMap : finding.getScanRepeatFindingMaps()) {
                            Scan scan = scanRepeatFindingMap.getScan();
                            if (scan != null) {
                                scanDate = scan.getImportTime();
                                if ((latestScanDate == null) || scanDate.after(latestScanDate)) {
                                    latestScanDate = scanDate;
                                }
                            }

                        }
                    }
                }
                Calendar defectStatusUpdatedDate = defect.getStatusUpdatedDate();
                if (defectStatusUpdatedDate == null) {
                    defectStatusUpdatedDate = Calendar.getInstance();
                    defectStatusUpdatedDate.setTime(defect.getModifiedDate());
                }
                if ((latestScanDate != null) && latestScanDate.after(defectStatusUpdatedDate)) {
                    vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_STILL_IN_SCAN;
                } else {
                    vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_NEEDS_SCAN;
                }
            }
        }

        vulnerability.setVulnerabilityDefectConsistencyState(vulnerabilityDefectConsistencyState);
        return vulnerabilityDefectConsistencyState;
    }
}