Example #1
0
    def _list(self, node):
        if node.hasAttribute('style'):
            list_style = self.styles.list_styles[node.getAttribute('style')]
        else:
            list_style = platypus.flowables.ListStyle('Default')

        list_items = []
        for li in _child_get(node, 'li'):
            flow = []
            for n in li.childNodes:
                if n.nodeType == node.ELEMENT_NODE:
                    flow.append(self._flowable(n))
            if not flow:
                if li.hasAttribute('style'):
                    li_style = self.styles.styles[li.getAttribute('style')]
                else:
                    li_style = reportlab.lib.styles.getSampleStyleSheet(
                    )['Normal']

                flow = platypus.paragraph.Paragraph(self._textual(li),
                                                    li_style)

            list_item = platypus.ListItem(flow)
            list_items.append(list_item)

        return platypus.ListFlowable(list_items,
                                     style=list_style,
                                     start=list_style.__dict__.get('start'))
Example #2
0
    def save(self, directory, filetype):
        """Saves the attributes of the Country to a specified file.

        Parameters
        ----------
        directory : str
            Path to save output
        filetype : str
            For output file with country data (json or pdf)

        Raises
        ------
        NotImplementedError
            If unsupported filetype is passed in.
        """

        filename = directory + self.name.replace(' ', '_')
        if filetype == 'json':
            filename += ".json"
            with open(filename, 'w') as f:
                json.dump(vars(self), f, indent=4)
            f.close()
        elif filetype == 'pdf':
            ss = getSampleStyleSheet()
            pdf = platy.SimpleDocTemplate(filename + ".pdf")
            flowables = []
            flowables.append(platy.Paragraph(self.name, ss['Heading1']))
            for k in vars(self):
                if k == 'id' or k == 'name':
                    continue
                if type(vars(self)[k]) is str or type(vars(self)[k]) is int:
                    p = f"{k.replace('_',' ').title()}: {str(vars(self)[k])}"
                    flowables.append(platy.Paragraph(p, ss['BodyText']))
                else:
                    p = f"{k.replace('_',' ').title()}:"
                    flowables.append(platy.Paragraph(p, ss['BodyText']))
                    bullets = []
                    for v in vars(self)[k]:
                        p = v
                        if type(vars(self)[k]) is not list:
                            p += ": "+vars(self)[k][v]
                        b = platy.Paragraph(p, ss['Normal'])
                        bullets.append(platy.ListItem(b, leftIndent=35))
                    table = platy.ListFlowable(bullets, bulletType='bullet')
                    flowables.append(table)
            pdf.build(flowables)
        elif filetype == 'html':
            filename += ".json"
            json_string = json.dumps(vars(self),indent=4)
            f = open(filename, 'w')
            f.write("var data = " + json_string)
            f.close()
        else:
            raise NotImplementedError(
                f"Output file type, {filetype}, not supported")
Example #3
0
    def pdf_response_rl(self, question, filename, download=False):
        """
        Use the ReportLab api and the Model Objects provided by the context
        dict in this views pipeline.
        """
        import reportlab.platypus as RL
        import reportlab.lib.styles as SL
        from io import BytesIO

        flo = []
        out = BytesIO()  # create a byte buffer to hold PDF data
        pdf = RL.SimpleDocTemplate(out)
        pdf.showBoundary = 1
        pdf.leftMargin = pdf.rightMargin = pdf.leftMargin / 2
        pdf.topMargin = pdf.bottomMargin = pdf.topMargin / 2

        ss = SL.getSampleStyleSheet()
        h1 = RL.Paragraph("Question:", ss['Heading1'])
        h2 = RL.Paragraph(f"{str(question)}", ss['Heading2'])
        h3 = RL.Paragraph("Choices:", ss['Heading3'])
        hl = RL.HRFlowable(width='100%')

        if question.question_img:
            img = RL.Image(question.question_img.path,
                           width=100,
                           height=75,
                           hAlign="LEFT")
            flo += [img, hl]

        flo += [h1, h2, hl, h3]

        ps = [
            RL.Paragraph(f"{str(c)} [{c.votes} votes]", ss['BodyText'])
            for c in question.choice_set.all()
        ]
        ul = [RL.ListItem(x, value='sparkle') for x in ps]
        lf = RL.ListFlowable(ul, bulletType='bullet')
        flo += [lf]

        flo += [hl]
        try:
            pdf.build(flo)
        except Exception as e:
            message = (f"Unable to generate PDF from <hl><pre>{html}</pre>")
            return HttpResponse(message, status=500)

        out.seek(0)  # reset byte buffer pointer to the start

        if download:
            return FileResponse(out, as_attachment=True, filename=filename)
        return FileResponse(out, filename=filename)
Example #4
0
def save_org(org, directory, filetype, assessment):
    """
    Saves information about the organization to a file.

    Paramters
    ---------
    org : stix2 Identity object
        the organization to save
    directory : str
        Path to save output
    filetype : str
        Type of output file (json or pdf)
    assessment : dictionary
        representation of NIST 800-171 assessment table
    """

    filename = directory + org.name.replace(' ', '')
    org_desc = json.loads(org.description)
    org_dict = {
        "name": org.name,
        "background": org_desc['Background'],
        "network_size": org_desc['Network']['size'],
        "vulnerability_level": org_desc['Security Posture']['vulnerability'],
        "NIST vulnerabilities": org_desc['Security Posture']['vulns'],
        "sectors": org.sectors
    }

    if filetype == 'json':
        with open(filename+".json", 'w') as f:
            json.dump(org_dict, f)
        f.close()
    elif filetype == 'pdf':
        ss = getSampleStyleSheet()
        pdf = platy.SimpleDocTemplate(filename + ".pdf")
        flowables = []
        flowables.append(platy.Paragraph(org.name, ss['Heading1']))
        p = f'Sector: {", ".join(org.sectors)}'
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        flowables.append(platy.Paragraph("Background", ss['Heading2']))
        p = (
            f'{org.name} is headquartered in the country of '
            f'{org_desc["Background"]["headquarters"]}. It has '
            f'{org_desc["Background"]["number of employees"]} employees and an'
            f' annual revenue of {org_desc["Background"]["annual revenue"]}.'
        )
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        flowables.append(platy.Paragraph("Computer Network", ss['Heading2']))
        p = f"Network size: {org_desc['Network']['size']} (on a scale of 100)"
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        p = "NIST 800-171 Security Evaluation Results"
        flowables.append(platy.Paragraph(p, ss['Heading2']))
        p = f"Score: {org_desc['Security Posture']['vulnerability']}/100"
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        p = "Vulnerabilities (failed requirements):"
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        bullets = []
        nist_reqs = {}
        for cat in assessment:
            for req in assessment[cat]:
                nist_reqs[req["Requirement"]] = req["Description"]
        for vuln in org_desc['Security Posture']['vulns']:
            p = platy.Paragraph(f'({vuln}) {nist_reqs[vuln]}', ss['Normal'])
            bullets.append(platy.ListItem(p, leftIndent=35))
        flowables.append(platy.ListFlowable(bullets, bulletType='bullet'))
        pdf.build(flowables)
    elif filetype == 'html':
        filename += ".json"
        f = open(filename, 'w')
        f.write("var data = " + str(org_dict))
        f.close()
    else:
        raise NotImplementedError(
            f"Output file type, {filetype}, not supported")
Example #5
0
def save(actor, directory, filetype, fs_gen, fs_real):
    """Saves the attributes of the Threat Actor to a specified file.

    Parameters
    ----------
    actor : stix2 ThreatActor object
        the threat actor to save
    directory : str
        Path to save output
    filetype : str
        For output file with country data (json or pdf)
    fs_gen : FileSystemStore  object
        Data store with info about threat actor
    fs_real : FileSystemSource object
        Data store with reference information about real world data
    """

    filename = directory + actor.name.replace(' ', '')

    relationships = fs_gen.query([
        Filter("type", "=", "relationship"),
        Filter("source_ref", "=", actor.id)])
    ttps, tools, malwares = [], [], []
    for r in relationships:
        if "attack-pattern" in r.target_ref:
            ttps.append(r.target_ref)
        elif "tool" in r.target_ref:
            tools.append(r.target_ref)
        elif "malware" in r.target_ref:
            malwares.append(r.target_ref)
        elif "location" in r.target_ref:
            countries = fs_gen.query([
                Filter("type", "=", "location"),
                Filter("id", "=", r.target_ref)])
    tool_names = [fs_real.query([
        Filter("type", "=", "tool"), Filter("id", "=", t)])[0].name
        for t in tools]
    m_s = [fs_real.query([
        Filter("type", "=", "malware"), Filter("id", "=", m)])[0].name
        for m in malwares]
    actor_dict = {
        "name": actor.name,
        "aliases": actor.aliases,
        "first_seen": actor.first_seen.strftime("%B %Y"),
        "last_seen": actor.last_seen.strftime("%B %Y"),
        "attribution": countries[0].name,
        "resource_level": actor.resource_level,
        "primary motivation": actor.primary_motivation,
        "secondary motivations": actor.secondary_motivations,
        "description": actor.description,
        "ttps": ttps,
        "tools": tool_names,
        "malware": m_s
    }

    if filetype == 'json':
        with open(filename+".json", 'w') as f:
            json.dump(actor_dict, f)
        f.close()
    elif filetype == 'pdf':
        ss = getSampleStyleSheet()
        pdf = platy.SimpleDocTemplate(filename + ".pdf")
        flowables = []

        try:
            actor_dict = json.loads(actor.description)
            p = (
                f'{actor.name} is a {actor_dict["actor_type"]} group also '
                f'known as {" or ".join(actor.aliases)}. It was first seen in '
                f'{actor.first_seen.strftime("%B %Y")}, and is attributed to '
                f'the state of {countries[0].name}. Its level of '
                f'sophistication is {actor_dict["sophistication"]}, and its '
                f'primary motivation is {actor.primary_motivation}, though it '
                f'is sometimes motivated by '
                f'{" and ".join(actor.secondary_motivations)}.'
            )
        except json.decoder.JSONDecodeError:
            actor_dict = None
            p = actor.description
        flowables.append(platy.Paragraph(actor.name, ss['Heading1']))
        flowables.append(platy.Paragraph(p, ss['BodyText']))

        if actor_dict is not None:
            p = actor.name + "'s goals are "
            flowables.append(platy.Paragraph(p, ss['BodyText']))
            bullets = []
            for g in actor.goals:
                p = platy.Paragraph(g, ss['Normal'])
                bullets.append(platy.ListItem(p, leftIndent=35))
            flowables.append(platy.ListFlowable(bullets, bulletType='bullet'))

        flowables.append(platy.Paragraph('Tools', ss['Heading2']))
        p = "This threat actor is known to use the following tools."
        flowables.append(platy.Paragraph(p, ss['BodyText']))

        bullets = []
        for tool in sorted(tool_names[:10], key=str.casefold):
            p = platy.Paragraph(tool, ss['Normal'])
            bullets.append(platy.ListItem(p, leftIndent=35))

        flowables.append(platy.ListFlowable(bullets, bulletType='bullet'))

        flowables.append(platy.Paragraph('Malware', ss['Heading2']))
        p = "This threat actor is known to use the following malware."
        flowables.append(platy.Paragraph(p, ss['BodyText']))

        bullets = []
        for malware in sorted(m_s[:5], key=str.casefold):
            p = platy.Paragraph(malware, ss['Normal'])
            bullets.append(platy.ListItem(p, leftIndent=35))
        flowables.append(platy.ListFlowable(bullets, bulletType='bullet'))

        flowables.append(
            platy.Paragraph('Attack Patterns', ss['Heading2']))
        for t in ttps:
            ttp = fs_real.query([
                Filter("type", "=", "attack-pattern"),
                Filter("id", "=", t)])[0]
            p = f"{ttp.name}"
            flowables.append(platy.Paragraph(p, ss['Italic']))
            p = []
            for ref in ttp.external_references:
                if ref.source_name == "mitre-attack":
                    p.append("Mitre Attack: "+ref.external_id)
                elif ref.source_name == "capec":
                    p.append(ref.external_id)
            if len(p) > 0:
                p = "(" + ", ".join(p) + ")\n"
                flowables.append(platy.Paragraph(p, ss['BodyText']))
            else:
                try:
                    flowables.append(platy.Paragraph(
                        ttp.description+'\n', ss['BodyText']))
                except AttributeError:
                    pass
            flowables.append(platy.Paragraph("", ss['Heading2']))

        flowables.append(
            platy.Paragraph('Related Reporting', ss['Heading2']))
        p = f"These reported incidents are likely or highly likely to be \
            attributed to {actor.name}, though there may be others:"
        flowables.append(platy.Paragraph(p, ss['BodyText']))
        sightings = fs_gen.query([
            Filter("type", "=", "sighting"),
            Filter("sighting_of_ref", "=", actor.id)])
        r_nums = [
            str(s.first_seen).replace('-', '') for s in sightings][:15]
        bullets = []
        for r in sorted(r_nums):
            p = platy.Paragraph(
                r.replace(' ', '_').replace(':', '')[:15], ss['Normal'])
            bullets.append(platy.ListItem(p, leftIndent=35))
        flowables.append(platy.ListFlowable(bullets, bulletType='bullet'))

        pdf.build(flowables)
    elif filetype == 'html':
        filename += ".json"
        f = open(filename, 'w')
        f.write("var data = " + str(actor_dict))
        f.close()
    else:
        raise NotImplementedError(
            f"Output file type, {filetype}, not supported")