Beispiel #1
0
def sent(jd_id):
    details = srv.get_jd_details(jd_id)
    html = details.get('jd_html')

    if request.method == 'GET':
        form = TagEntryForm()
        present_tags = tag_srv.get_tagged_sentences_for_jd(jd_id).get(
            'taggings')

        if not present_tags:
            present_tags = [{
                'sentence': sent,
                'tag': 'Tags'
            } for sent in details.get('jd_sentences')]

        for ptag in present_tags:
            st = SentenceTag()
            st.sentence = ptag.get('sentence')
            st.tag = ptag.get('tag')

            form.tag_list.append_entry(st)

        return render_template('sent.html', form=form, jd_html=Markup(html))
    else:
        out = Cut({}, sep='-')

        for key, value in request.form.to_dict().items():
            out.setdefault(key, value)

        out = dict(out)
        tags = list(out['tag_list'].values())

        tag_srv.perform_sentence_tagging(jd_id, tags)

        return render_template('sent.html', tagged=True, jd_html=Markup(html))
Beispiel #2
0
    def import_cti_event(self,
                         timestamp: datetime,
                         data: dict,
                         is_update: bool = False) -> dict:
        logger.debug(f"Querying indicator: { data['x_opencti_id']}")
        entity = self.helper.api.indicator.read(id=data["x_opencti_id"])

        logger.debug(entity)

        _result: dict = {}
        _document: Cut = {}

        if data["type"] != "indicator":
            logger.error(
                f"Data type unsupported: {data['type']}. Only 'indicators are currently supported."
            )
            return None

        if is_update is True:
            update_time: str = (datetime.now(
                tz=timezone.utc).isoformat().replace("+00:00", "Z"))
            try:
                # Attempt to retreive existing document
                logger.debug(f"Retrieving document id: {data['x_opencti_id']}")
                _result = self.es_client.get(index=self.idx_pattern,
                                             id=data["x_opencti_id"],
                                             doc_type="_doc")

            except NotFoundError:
                logger.warn(
                    f"Document not found to update at /{self.idx}/_doc/{data['x_opencti_id']}"
                )
                logger.warn("Skipping")
                return {}

            except RequestError as err:
                logger.error(
                    f"Unexpected error retreiving document at /{self.idx}/_doc/{data['x_opencti_id']}:",
                    err.__dict__,
                )

            if _result["found"] is True:
                _document = Cut(_result["_source"])
                _write_idx = _result["_index"]

            if data.get("x_data_update", None):
                if data["x_data_update"].get("replace", None):
                    if entity["pattern_type"] == "stix":
                        # Pull in any indicator updates
                        _indicator: dict = self._create_ecs_indicator_stix(
                            entity)
                        if _indicator == {}:
                            return {}
                        _document["threatintel.indicator"] = _indicator
                        if entity.get("killChainPhases", None):
                            phases = []
                            for phase in sorted(
                                    entity["killChainPhases"],
                                    key=lambda i: (
                                        i["kill_chain_name"],
                                        i["x_opencti_order"],
                                    ),
                            ):
                                phases.append({
                                    "killchain_name":
                                    phase["kill_chain_name"],
                                    "phase_name":
                                    phase["phase_name"],
                                    "opencti_phase_order":
                                    phase["x_opencti_order"],
                                })

                            _document.setdefault(
                                "threatintel.opencti.killchain_phases", phases)
                    else:
                        logger.warning(
                            f"Unsupported indicator pattern type: {entity['pattern_type']}. Skipping."
                        )
                        return _document

                    for k, v in data["x_data_update"].get("replace",
                                                          {}).items():
                        logger.debug(
                            f"Updating field {k} -> {entity_field_mapping.get(k)} to {v}"
                        )
                        try:
                            _field = entity_field_mapping.get(k)
                            _document.setdefault(_field, v)
                            _document[_field] = v
                        except KeyError as err:
                            logger.error(
                                f"Unable to find field mapping for {k}", err)

                    _document["threatintel.opencti.updated_at"] = update_time

                    #  This scrubs the Cut object and returns a dict
                    _document = remove_nones(_document)

                    try:
                        # Don't render timestamped index since this is an update
                        # Submit to Elastic index
                        logger.debug(
                            f"Updating doc to {_write_idx}:\n {_document}")
                        self.es_client.index(
                            index=_write_idx,
                            id=data["x_opencti_id"],
                            body=_document,
                        )
                    except RequestError as err:
                        logger.error("Unexpected error:", err, _document)
                    except Exception as err:
                        logger.error("Something else happened", err, _document)

                    return _document

        creation_time: str = (datetime.now(
            tz=timezone.utc).isoformat().replace("+00:00", "Z"))

        _document: dict = {
            "@timestamp": timestamp,
            "event": {
                "created": creation_time,
                "kind": "enrichment",
                "category": "threat",
                "type": "indicator",
                "dataset": "threatintel.opencti",
            },
            "threatintel": {},
        }

        if len(entity.get("externalReferences", [])) > 0:
            _document["event"]["reference"] = [
                item.get("url", None) for item in entity["externalReferences"]
            ]

        if self.config.get("opencti.platform_url") is not None:
            _document["event"]["url"] = urllib.parse.urljoin(
                f"{self.config.get('opencti.platform_url')}",
                f"/dashboard/observations/indicators/{entity['id']}",
            )

        _document["event"]["risk_score"] = entity.get("x_opencti_score", None)
        _document["event"]["risk_score_norm"] = entity.get(
            "x_opencti_score", None)
        _document["threatintel"]["confidence"] = entity.get("confidence", None)
        _document["threatintel"]["confidence_norm"] = entity.get(
            "confidence", None)

        _document["threatintel"]["opencti"] = {
            "internal_id": entity.get("id", None),
            "valid_from": entity.get("valid_from", None),
            "valid_until": entity.get("valid_until", None),
            "enable_detection": entity.get("x_opencti_detection", None),
            "original_pattern": entity.get("pattern", None),
            "pattern_type": entity.get("pattern_type", None),
            "created_at": entity.get("created_at", None),
            "updated_at": entity.get("created_at", None),
            "revoked": entity.get("revoked", None),
        }

        if entity.get("killChainPhases", None):
            phases = []
            for phase in sorted(
                    entity["killChainPhases"],
                    key=lambda i: (i["kill_chain_name"], i["x_opencti_order"]),
            ):
                phases.append({
                    "killchain_name": phase["kill_chain_name"],
                    "phase_name": phase["phase_name"],
                    "opencti_phase_order": phase["x_opencti_order"],
                })

            _document["threatintel"]["opencti"]["killchain_phases"] = phases

        if entity.get("x_mitre_platforms", None):
            _document["threatintel"]["opencti"]["mitre"] = {
                "platforms": entity.get("x_mitre_platforms", None)
            }

        if entity["pattern_type"] == "stix":
            _indicator: dict = self._create_ecs_indicator_stix(entity)
            if _indicator == {}:
                return {}

            _document["threatintel"]["stix"] = {
                "id": entity.get("standard_id")
            }
            _document["threatintel"]["indicator"] = _indicator

        else:
            logger.warning(
                f"Unsupported indicator pattern type: {entity['pattern_type']}. Skipping."
            )
            return {}

        _document = remove_nones(_document)

        try:
            # Render date-specific index, if we're doing logstash style indices
            _write_idx = self.write_idx
            m = self.pattern.search(_write_idx)
            if m is not None:
                m = m.groupdict()
                if m.get("modulo", None) is not None:
                    _fmt = m.get("format") or DM_DEFAULT_FMT
                    logger.debug(f"{m['modulo']} -> {_fmt}")
                    _val = dm(m.get("modulo"), now=timestamp).format(_fmt)
                    _write_idx = self.pattern.sub(_val, _write_idx)

            # Submit to Elastic index
            logger.debug(f"Indexing doc to {_write_idx}:\n {_document}")
            self.es_client.index(
                index=_write_idx,
                id=data["x_opencti_id"],
                body=_document,
            )
        except RequestError as err:
            logger.error("Unexpected error:", err, _document)
        except Exception as err:
            logger.error("Something else happened", err, _document)

        return _document