EXPLORE
← Back to Explore
sublimemediumRule

Scam: Piano giveaway

This rule is designed to identify and mitigate a specific type of fraudulent activity commonly targeted at educational institutions. This rule operates by analyzing incoming email content for certain characteristics indicative of a scam involving the offer of a free piano, often framed within the context of downsizing or a giveaway.

Detection Query

length(body.links) < 10
and length(body.current_thread.text) < 2000
and (
  // body detection
  // be sure to update the attachment detection regexes too!
  (
    (
      // items and brands
      // Guitars
      regex.icontains(body.current_thread.text,
                      '(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)\s*[^\r\n]{0,50}\s*guitar',
                      'guitar\s*[^\r\n]{0,50}\s*(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)',
      )
      // Piano/Keyboards
      or regex.icontains(body.current_thread.text,
                         '(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})\s*[^\r\n]{0,50}(?:baby.grand|piano|baby.grand.piano|keyboard)',
                         '(?:baby.grand|piano|baby.grand.piano|keyboard)\s*[^\r\n]{0,50}(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})',
                         // strong indicators for generalized instrument
                         '(?:piano|keyboard)\s*[^\r\n]{0,50}(?:available|sale|rehome|gift)'
      )
      // Violins & Orchestral 
      or regex.icontains(body.current_thread.text,
                         '(?:Stradivarius|Guarneri|Yamaha|Stentor|Eastman|Cremona|Cecilio|Mendini)\s*[^\r\n]{0,50}(violin|viola|cello|celli)',
      )
      // brass/wind/woodwinds
      or regex.icontains(body.current_thread.text,
                         '(?:Bach|Yamaha|Selmer|Conn|King|Jupiter|Buffet Crampon |Pearl)\s*[^\r\n]{0,50}(trombone|trumpet|saxophone|clarinet|flute)'
      )

      // generic
      or strings.ilike(body.current_thread.text,
                       '* musical instruments *',
                       '* instrument as a gift*'
      )
    )
    and (
      // often a person is moving
      strings.ilike(body.current_thread.text,
                    '* downsizing *',
                    '* relocating *',
                    '* to relocate *',
                    '* relocation *',
                    '* moving *'
      )
      or strings.ilike(body.current_thread.text,
                       '* give away*',
                       '* generously offering *',
                       '*a loving home*',
                       '*a good home*',
                       '*find a new home *',
                       '*rehome these instruments *',
                       '* free donation*',
                       '*free*member of the music community*'
      )
      // generally someone died
      or regex.icontains(body.current_thread.text,
                         'inherited instruments',
                         'late (?:husband|father|dad|wife|mother|mom)',
                         '(?:husband|father|dad|wife|mother|mom)[^\r\n]{0,50}estate'
      )
      // passion/love for the item
      or strings.ilike(body.current_thread.text,
                       '* genuinely cherish*',
                       '* cherished possessions*',
                       '* passionate instrument*',
                       '* music lover*',
                       '* had a passion for music*',
                       '* appreciates music*',
                       "* special piece*",
                       "* a lot of meaning*",
                       "* profound sentimental*",
                       '* will cherish*',
                       '* passion for music*',
                       '* treasured items *'
      )
    )
    and (
      // it talks about a shipping fee upfront
      regex.icontains(body.current_thread.text,
                      'shipping (?:fee|cost|arrangement)',
                      '(?:responsible|pay) for shipping',
                      'no (?:local\s)?pick.?up',
                      '(?:local\s)?pick.?up.{0,50}not available',
                      'delivery only',
                      'moving company'
      )
      // recipient or someone they know might have an interest
      or strings.ilike(body.current_thread.text,
                       '* if you will take it *',
                       '* or have someone *',
                       '* indicate your interest *',
                       '* to someone you know *',
                       '* know someone who *',
                       '* someone you know would *',
                       '* someone who will *',
                       '* someone who truly *',
                       '* anyone you know *',
      )
      or regex.icontains(body.current_thread.text,
                         'if you[^\r\n]{0,20}(?:(?:might|will|would) be|are)[^\r\n]{0,20}interested',
                         '(?:any|some)one[^\r\n]{0,20}(is|will|would|might be)[^\r\n]{0,20}interested',
                         'who (?:will|would|might) appreciate',
      )
      or (
        // there's an email in the body 
        any(regex.extract(body.current_thread.text,
                          "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
            ),
            strings.parse_email(.full_match).domain.domain in $free_email_providers
            or strings.parse_email(.full_match).domain.root_domain in $free_email_providers
        )
        // reply-to doesn't match sender
        or (
          length(headers.reply_to) > 0
          and sender.email.email not in map(headers.reply_to, .email.email)
        )
        // there are no recipients
        or length(recipients.to) == 0
        // redirects to a phone number
        or regex.icontains(body.current_thread.text,
                           '(?:call|contact|text)[^\r\n]{0,50} at'
        )
        or regex.icontains(body.current_thread.text,
                           '(?:private|personal) (?:e-?)?mail'
        )
        or strings.icontains(body.current_thread.text, ' kindly ')
        or strings.icontains(body.current_thread.text, ' (kindly ')
      )
    )
  )
  or (
    any(filter(attachments, .size < 10000),
        (
          // items and brands
          // Guitars
          regex.icontains(file.parse_text(.).text,
                          '(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)\s*[^\r\n]{0,50}\s*guitar',
                          'guitar\s*[^\r\n]{0,50}\s*(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)',
          )
          // Piano/Keyboards
          or regex.icontains(file.parse_text(.).text,
                             '(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?)\s*[^\r\n]{0,50}(?:baby.grand|piano|baby.grand.piano|keyboard)',
                             '(?:baby.grand|piano|baby.grand.piano|keyboard)\s*[^\r\n]{0,50}(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})',
                             // strong indicators for generalized instrument
                             '(?:piano|keyboard)\s*[^\r\n]{0,50}(?:available|sale|rehome|gift)'
          )
          // Violins & Orchestral 
          or regex.icontains(file.parse_text(.).text,
                             '(?:Stradivarius|Guarneri|Yamaha|Stentor|Eastman|Cremona|Cecilio|Mendini)\s*[^\r\n]{0,50}(violin|viola|cello|celli)',
          )
          // brass/wind/woodwinds
          or regex.icontains(file.parse_text(.).text,
                             '(?:Bach|Yamaha|Selmer|Conn|King|Jupiter|Buffet Crampon |Pearl)\s*[^\r\n]{0,50}(trombone|trumpet|saxophone|clarinet|flute)'
          )

          // generic
          or strings.ilike(file.parse_text(.).text,
                           '* musical instruments *',
                           '* instrument as a gift*'
          )
        )
        and (
          // often a person is moving
          strings.ilike(file.parse_text(.).text,
                        '* downsizing *',
                        '* relocating *',
                        '* to relocate *',
                        '* relocation *',
          )
          or strings.ilike(file.parse_text(.).text,
                           '* give away*',
                           '* generously offering *',
                           '*a loving home*',
                           '*a good home*',
                           '*find a new home *',
                           '*rehome these instruments *',
                           '* free donation*',
                           '*free*member of the music community*'
          )
          // generally someone died
          or regex.icontains(file.parse_text(.).text,
                             'inherited instruments',
                             'late (?:husband|father|dad|wife|mother|mom)',
                             '(?:husband|father|dad|wife|mother|mom)[^\r\n]{0,50}estate'
          )
          // passion/love for the item/music
          or strings.ilike(file.parse_text(.).text,
                           '* genuinely cherish*',
                           '* cherished possessions*',
                           '* passionate instrument*',
                           '* music lover*',
                           '* had a passion for music*',
                           '* appreciates music*',
                           "* special piece*",
                           "* a lot of meaning*",
                           "* profound sentimental*",
                           '* will cherish*',
                           '* passion for music*',
                           '* treasured items *'
          )
        )
        and (
          // it talks about a shipping fee upfront
          regex.icontains(file.parse_text(.).text,
                          'shipping (?:fee|cost|arrangement)',
                          '(?:responsible|pay) for shipping',
                          'no (?:local\s)?pick.?up',
                          '(?:local\s)?pick.?up.{0,50}not available',
                          'delivery only',
                          'moving company'
          )
          or strings.ilike(file.parse_text(.).text,
                           '* if you will take it *',
                           '* or have someone *',
                           '* indicate your interest *',
                           '* to someone you know *',
                           '* know someone who *',
                           '* someone you know would *',
                           '* someone who will *',
                           '* anyone you know *',
          )
          or regex.icontains(file.parse_text(.).text,
                             'if you[^\r\n]{0,20}(?:(?:might|will|would) be|are)[^\r\n]{0,20}interested',
                             '(?:any|some)one[^\r\n]{0,20}(is|will|would|might be)[^\r\n]{0,20}interested',
                             'who (?:will|would|might) appreciate',
          )
          // there's an email in the body 
          or any(regex.extract(file.parse_text(.).text,
                               "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
                 ),
                 strings.parse_email(.full_match).domain.domain in $free_email_providers
                 or strings.parse_email(.full_match).domain.root_domain in $free_email_providers
          )

          // reply-to doesn't match sender
          or (
            length(headers.reply_to) > 0
            and sender.email.email not in map(headers.reply_to, .email.email)
          )
          // there are no recipients
          or length(recipients.to) == 0
          // redirects to a phone number
          or regex.icontains(file.parse_text(.).text,
                             '(?:call|contact|text)[^\r\n]{0,50} at'
          )
          or regex.icontains(file.parse_text(.).text,
                             '(?:private|personal) (?:e-?)?mail'
          )
          or strings.icontains(file.parse_text(.).text, ' kindly ')
          or strings.icontains(file.parse_text(.).text, ' (kindly ')
        )
    )
  )
)

// not high trust sender domains
and not (
  sender.email.domain.root_domain in $high_trust_sender_root_domains
  and headers.auth_summary.dmarc.pass
)
and not sender.email.domain.root_domain in (
  'ridleyacademy.com', // person provides piano lessons and offers to give a Roland baby-grand away
  'mountainpiano.com' // legitimate piano moving company in Denver 
)

Data Sources

Email MessagesEmail HeadersEmail Attachments

Platforms

email
Raw Content
name: "Scam: Piano giveaway"
description: "This rule is designed to identify and mitigate a specific type of fraudulent activity commonly targeted at educational institutions. This rule operates by analyzing incoming email content for certain characteristics indicative of a scam involving the offer of a free piano, often framed within the context of downsizing or a giveaway."
type: "rule"
severity: "medium"
source: |
  length(body.links) < 10
  and length(body.current_thread.text) < 2000
  and (
    // body detection
    // be sure to update the attachment detection regexes too!
    (
      (
        // items and brands
        // Guitars
        regex.icontains(body.current_thread.text,
                        '(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)\s*[^\r\n]{0,50}\s*guitar',
                        'guitar\s*[^\r\n]{0,50}\s*(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)',
        )
        // Piano/Keyboards
        or regex.icontains(body.current_thread.text,
                           '(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})\s*[^\r\n]{0,50}(?:baby.grand|piano|baby.grand.piano|keyboard)',
                           '(?:baby.grand|piano|baby.grand.piano|keyboard)\s*[^\r\n]{0,50}(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})',
                           // strong indicators for generalized instrument
                           '(?:piano|keyboard)\s*[^\r\n]{0,50}(?:available|sale|rehome|gift)'
        )
        // Violins & Orchestral 
        or regex.icontains(body.current_thread.text,
                           '(?:Stradivarius|Guarneri|Yamaha|Stentor|Eastman|Cremona|Cecilio|Mendini)\s*[^\r\n]{0,50}(violin|viola|cello|celli)',
        )
        // brass/wind/woodwinds
        or regex.icontains(body.current_thread.text,
                           '(?:Bach|Yamaha|Selmer|Conn|King|Jupiter|Buffet Crampon |Pearl)\s*[^\r\n]{0,50}(trombone|trumpet|saxophone|clarinet|flute)'
        )
  
        // generic
        or strings.ilike(body.current_thread.text,
                         '* musical instruments *',
                         '* instrument as a gift*'
        )
      )
      and (
        // often a person is moving
        strings.ilike(body.current_thread.text,
                      '* downsizing *',
                      '* relocating *',
                      '* to relocate *',
                      '* relocation *',
                      '* moving *'
        )
        or strings.ilike(body.current_thread.text,
                         '* give away*',
                         '* generously offering *',
                         '*a loving home*',
                         '*a good home*',
                         '*find a new home *',
                         '*rehome these instruments *',
                         '* free donation*',
                         '*free*member of the music community*'
        )
        // generally someone died
        or regex.icontains(body.current_thread.text,
                           'inherited instruments',
                           'late (?:husband|father|dad|wife|mother|mom)',
                           '(?:husband|father|dad|wife|mother|mom)[^\r\n]{0,50}estate'
        )
        // passion/love for the item
        or strings.ilike(body.current_thread.text,
                         '* genuinely cherish*',
                         '* cherished possessions*',
                         '* passionate instrument*',
                         '* music lover*',
                         '* had a passion for music*',
                         '* appreciates music*',
                         "* special piece*",
                         "* a lot of meaning*",
                         "* profound sentimental*",
                         '* will cherish*',
                         '* passion for music*',
                         '* treasured items *'
        )
      )
      and (
        // it talks about a shipping fee upfront
        regex.icontains(body.current_thread.text,
                        'shipping (?:fee|cost|arrangement)',
                        '(?:responsible|pay) for shipping',
                        'no (?:local\s)?pick.?up',
                        '(?:local\s)?pick.?up.{0,50}not available',
                        'delivery only',
                        'moving company'
        )
        // recipient or someone they know might have an interest
        or strings.ilike(body.current_thread.text,
                         '* if you will take it *',
                         '* or have someone *',
                         '* indicate your interest *',
                         '* to someone you know *',
                         '* know someone who *',
                         '* someone you know would *',
                         '* someone who will *',
                         '* someone who truly *',
                         '* anyone you know *',
        )
        or regex.icontains(body.current_thread.text,
                           'if you[^\r\n]{0,20}(?:(?:might|will|would) be|are)[^\r\n]{0,20}interested',
                           '(?:any|some)one[^\r\n]{0,20}(is|will|would|might be)[^\r\n]{0,20}interested',
                           'who (?:will|would|might) appreciate',
        )
        or (
          // there's an email in the body 
          any(regex.extract(body.current_thread.text,
                            "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
              ),
              strings.parse_email(.full_match).domain.domain in $free_email_providers
              or strings.parse_email(.full_match).domain.root_domain in $free_email_providers
          )
          // reply-to doesn't match sender
          or (
            length(headers.reply_to) > 0
            and sender.email.email not in map(headers.reply_to, .email.email)
          )
          // there are no recipients
          or length(recipients.to) == 0
          // redirects to a phone number
          or regex.icontains(body.current_thread.text,
                             '(?:call|contact|text)[^\r\n]{0,50} at'
          )
          or regex.icontains(body.current_thread.text,
                             '(?:private|personal) (?:e-?)?mail'
          )
          or strings.icontains(body.current_thread.text, ' kindly ')
          or strings.icontains(body.current_thread.text, ' (kindly ')
        )
      )
    )
    or (
      any(filter(attachments, .size < 10000),
          (
            // items and brands
            // Guitars
            regex.icontains(file.parse_text(.).text,
                            '(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)\s*[^\r\n]{0,50}\s*guitar',
                            'guitar\s*[^\r\n]{0,50}\s*(?:Gibson|Fender|Lowden|Martin|Taylor|Ibanez|Knaggs)',
            )
            // Piano/Keyboards
            or regex.icontains(file.parse_text(.).text,
                               '(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?)\s*[^\r\n]{0,50}(?:baby.grand|piano|baby.grand.piano|keyboard)',
                               '(?:baby.grand|piano|baby.grand.piano|keyboard)\s*[^\r\n]{0,50}(?:Yamaha|Kawai|Baldwin|Roland|Stei?nway(?: (?:&|and) Sons?)?|\d{4})',
                               // strong indicators for generalized instrument
                               '(?:piano|keyboard)\s*[^\r\n]{0,50}(?:available|sale|rehome|gift)'
            )
            // Violins & Orchestral 
            or regex.icontains(file.parse_text(.).text,
                               '(?:Stradivarius|Guarneri|Yamaha|Stentor|Eastman|Cremona|Cecilio|Mendini)\s*[^\r\n]{0,50}(violin|viola|cello|celli)',
            )
            // brass/wind/woodwinds
            or regex.icontains(file.parse_text(.).text,
                               '(?:Bach|Yamaha|Selmer|Conn|King|Jupiter|Buffet Crampon |Pearl)\s*[^\r\n]{0,50}(trombone|trumpet|saxophone|clarinet|flute)'
            )
  
            // generic
            or strings.ilike(file.parse_text(.).text,
                             '* musical instruments *',
                             '* instrument as a gift*'
            )
          )
          and (
            // often a person is moving
            strings.ilike(file.parse_text(.).text,
                          '* downsizing *',
                          '* relocating *',
                          '* to relocate *',
                          '* relocation *',
            )
            or strings.ilike(file.parse_text(.).text,
                             '* give away*',
                             '* generously offering *',
                             '*a loving home*',
                             '*a good home*',
                             '*find a new home *',
                             '*rehome these instruments *',
                             '* free donation*',
                             '*free*member of the music community*'
            )
            // generally someone died
            or regex.icontains(file.parse_text(.).text,
                               'inherited instruments',
                               'late (?:husband|father|dad|wife|mother|mom)',
                               '(?:husband|father|dad|wife|mother|mom)[^\r\n]{0,50}estate'
            )
            // passion/love for the item/music
            or strings.ilike(file.parse_text(.).text,
                             '* genuinely cherish*',
                             '* cherished possessions*',
                             '* passionate instrument*',
                             '* music lover*',
                             '* had a passion for music*',
                             '* appreciates music*',
                             "* special piece*",
                             "* a lot of meaning*",
                             "* profound sentimental*",
                             '* will cherish*',
                             '* passion for music*',
                             '* treasured items *'
            )
          )
          and (
            // it talks about a shipping fee upfront
            regex.icontains(file.parse_text(.).text,
                            'shipping (?:fee|cost|arrangement)',
                            '(?:responsible|pay) for shipping',
                            'no (?:local\s)?pick.?up',
                            '(?:local\s)?pick.?up.{0,50}not available',
                            'delivery only',
                            'moving company'
            )
            or strings.ilike(file.parse_text(.).text,
                             '* if you will take it *',
                             '* or have someone *',
                             '* indicate your interest *',
                             '* to someone you know *',
                             '* know someone who *',
                             '* someone you know would *',
                             '* someone who will *',
                             '* anyone you know *',
            )
            or regex.icontains(file.parse_text(.).text,
                               'if you[^\r\n]{0,20}(?:(?:might|will|would) be|are)[^\r\n]{0,20}interested',
                               '(?:any|some)one[^\r\n]{0,20}(is|will|would|might be)[^\r\n]{0,20}interested',
                               'who (?:will|would|might) appreciate',
            )
            // there's an email in the body 
            or any(regex.extract(file.parse_text(.).text,
                                 "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
                   ),
                   strings.parse_email(.full_match).domain.domain in $free_email_providers
                   or strings.parse_email(.full_match).domain.root_domain in $free_email_providers
            )
  
            // reply-to doesn't match sender
            or (
              length(headers.reply_to) > 0
              and sender.email.email not in map(headers.reply_to, .email.email)
            )
            // there are no recipients
            or length(recipients.to) == 0
            // redirects to a phone number
            or regex.icontains(file.parse_text(.).text,
                               '(?:call|contact|text)[^\r\n]{0,50} at'
            )
            or regex.icontains(file.parse_text(.).text,
                               '(?:private|personal) (?:e-?)?mail'
            )
            or strings.icontains(file.parse_text(.).text, ' kindly ')
            or strings.icontains(file.parse_text(.).text, ' (kindly ')
          )
      )
    )
  )
  
  // not high trust sender domains
  and not (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and headers.auth_summary.dmarc.pass
  )
  and not sender.email.domain.root_domain in (
    'ridleyacademy.com', // person provides piano lessons and offers to give a Roland baby-grand away
    'mountainpiano.com' // legitimate piano moving company in Denver 
  )
attack_types:
  - "BEC/Fraud"
tactics_and_techniques:
  - "Free email provider"
detection_methods:
  - "Content analysis"
  - "Natural Language Understanding"
  - "Sender analysis"
id: "1a91a203-b1fe-52b7-9f71-cecdbf5cdce0"