Self-sent fake PDF attachment with misleading link

Detects messages sent from a user to themselves containing a fake PDF icon from Google's CDN, claiming to have an attachment while only containing images, and including links that appear to be PDF files.

Sublime rule (View on GitHub)

 1name: "Self-sent fake PDF attachment with misleading link"
 2description: "Detects messages sent from a user to themselves containing a fake PDF icon from Google's CDN, claiming to have an attachment while only containing images, and including links that appear to be PDF files."
 3type: "rule"
 4severity: "low"
 5source: |
 6  type.inbound
 7  and (
 8    // pdf image
 9    strings.contains(body.html.raw,
10                     'https://ci3.googleusercontent.com/meips/ADKq_Naq6rm1GwC4XYZepCUQtEMnJ-r-HjyX_C5lBU7lpxQk1OIDV7vvQYvSJQWYmQCzG8moTgX3Wak625OtyHWRinVeUJs7K710JiIZ4JNXVpTmC8PJjV4K34GsBA=s0-d-e1-ft#https://res-1.cdn.office.net/assets/mail/file-icon/png/pdf_16x16.png'
11    )
12    // or there is an small attached image, directly before the link ending in .pdf
13    or any(filter(attachments,
14                  .file_type in $file_types_images
15                  and strings.icontains(body.html.raw, .content_id)
16                  // use megapixels to get a rough idea of the actual size of the image
17                  and any(beta.parse_exif(.).fields,
18                          .key == "Megapixels"
19                          and strings.parse_float(.value) < 0.1
20                  )
21           ),
22           any(html.xpath(body.html,
23                          '//a[preceding-sibling::*[1][self::img or .//img] or parent::*/preceding-sibling::*[1][self::img or .//img]]'
24               ).nodes,
25               any(.links, strings.iends_with(.display_text, '.pdf'))
26               and any(html.xpath(.,
27                                  'preceding-sibling::*[1]/descendant-or-self::img | parent::*/preceding-sibling::*[1]/descendant-or-self::img'
28                       ).nodes,
29                       strings.icontains(.raw, ...content_id)
30               )
31           )
32    )
33  )
34  // mentions attachments but there are none or just images with no pdfs
35  and (
36    strings.starts_with(body.current_thread.text, 'Please see attached.')
37    or strings.icontains(body.current_thread.text, 'Please find attached')
38    // NLU
39    or any(ml.nlu_classifier(body.current_thread.text).entities,
40           .name == "request"
41           and strings.istarts_with(.text, 'please ')
42           and strings.icontains(.text, 'attached')
43    )
44  )
45  and all(attachments, .file_type in $file_types_images)
46  // self sender
47  and (
48    length(recipients.to) == 1
49    and sender.email.email == recipients.to[0].email.email
50  )
51  // display text ends with .pdf
52  and any(body.current_thread.links,
53          strings.ends_with(.display_text, '.pdf')
54          and .href_url.domain.subdomain is not null
55          and .visible
56          and not (
57            .href_url.domain.root_domain == "googleusercontent.com"
58            and strings.istarts_with(.href_url.path, "/mail-sig")
59          )
60  )  
61attack_types:
62  - "Credential Phishing"
63tactics_and_techniques:
64  - "Evasion"
65  - "Free subdomain host"
66  - "Social engineering"
67detection_methods:
68  - "Content analysis"
69  - "URL analysis"
70  - "Sender analysis"
71id: "8a285d2e-3e40-5dfa-b269-947011663a5a"
to-top