Class: Unisec::Bidi::Spoof — Documentation by YARD 0.9.44

# Class: Unisec::Bidi::Spoof

Inherits:
  Object
  - Object
  - Unisec::Bidi::Spoof
  show all

Defined in:
  lib/unisec/bidi.rb

## Overview

Attack using BiDi code points like RtLO, for example, for spoofing a domain name or a file name

## Instance Attribute Summary collapse

- #spoof_payload ⇒ String readonly

  The string for the spoofing attack with the BiDi characters.

- #spoof_string ⇒ String readonly

  The string for the spoofing attack without the BiDi characters.

- #target_display ⇒ String readonly

  The target string to spoof (eg. URL, domain or file name).

## Class Method Summary collapse

- .bidi_affix(input, **opts) ⇒ String

  Inject BiDi characters into the input string.

- .reverse(target, **opts) ⇒ String

  Reverse the (sub)-string (grapheme cluster aware).

## Instance Method Summary collapse

- #bidi_affix ⇒ Object

  Call Spoof.bidi_affix with `@spoof_string` as input.

- #display(light: false) ⇒ String

  Display a CLI-friendly output summurizing the spoof payload.

- #initialize(input, **opts) ⇒ Spoof constructor

  A new instance of Spoof.

- #reverse ⇒ Object

  Call Spoof.reverse with `@target_display` as default input (target).

- #set_target_display(input, **opts) ⇒ String

  Set a new target string to spoof.

## Constructor Details

### #initialize(input, **opts) ⇒ `Spoof`

Returns a new instance of Spoof.

#### Examples:

    bd = Unisec::Bidi::Spoof.new('https://moc.example.org//:sptth')
    bd.target_display # => "https://moc.example.org//:sptth"
    bd.spoof_string # => "https://gro.elpmaxe.com//:sptth"
    bd.spoof_payload => "‮https://gro.elpmaxe.com//:sptth‬"

Parameters:

- input (`String`) —

  the target string

- opts (`Hash`) —

  optional parameters, see bidi_affix

    43
    44
    45
    46
    47
    48
    49
    # File 'lib/unisec/bidi.rb', line 43

    def initialize(input, **opts)
      opts[:index] ||= opts[:infix_pos]

      @target_display = input
      @spoof_string = reverse(**opts)
      @spoof_payload = bidi_affix(**opts)
    end

## Instance Attribute Details

### #spoof_payload ⇒ `String` (readonly)

The string for the spoofing attack with the BiDi characters. (Spoof payload = spoof string + BiDi)

Returns:

- (`String`) —

  the spoof string (with BiDi)

    34
    35
    36
    # File 'lib/unisec/bidi.rb', line 34

    def spoof_payload
      @spoof_payload
    end

### #spoof_string ⇒ `String` (readonly)

The string for the spoofing attack without the BiDi characters

Returns:

- (`String`) —

  the spoof string (without BiDi)

    30
    31
    32
    # File 'lib/unisec/bidi.rb', line 30

    def spoof_string
      @spoof_string
    end

### #target_display ⇒ `String` (readonly)

The target string to spoof (eg. URL, domain or file name)

Returns:

- (`String`) —

  the target string

    13
    14
    15
    # File 'lib/unisec/bidi.rb', line 13

    def target_display
      @target_display
    end

## Class Method Details

### .bidi_affix(input, **opts) ⇒ `String`

Inject BiDi characters into the input string

#### Examples:

    # By default inject a RLO prefix, a PDF suffix and no infix.
    Unisec::Bidi::Spoof.bidi_affix('acceis')
    # => "‮acceis‬"

    # RLI ... PDI
    Unisec::Bidi::Spoof.bidi_affix('acceis', prefix: "\u{2067}", suffix: "\u{2069}")
    # => "⁧acceis⁩"

    # RLE ... PDF
    Unisec::Bidi::Spoof.bidi_affix('acceis', prefix: "\u{202B}", suffix: "\u{202C}")
    # => "‫acceis‬"

    # RLO ... PDF
    Unisec::Bidi::Spoof.bidi_affix('https://moc.example.org//:sptth', prefix: "\u{202E}", suffix: "\u{202C}")
    # => "‮https://moc.example.org//:sptth‬"

    # FSI RLO ... PDF PDI
    Unisec::Bidi::Spoof.bidi_affix('https://moc.example.org//:sptth', prefix: "\u{2068 202E}", suffix: "\u{202C 2069}")
    # => "⁨‮https://moc.example.org//:sptth‬⁩"

    # RLM ...
    Unisec::Bidi::Spoof.bidi_affix('unicode', prefix: "\u{200F}", suffix: '')
    # => "‏unicode"

    # For file name spoofing, it is useful to be able to inject just a RLO before the fake extension
    # so we can void the prefix and suffix and just set the position of an infix
    ex = Unisec::Bidi::Spoof.bidi_affix('document_anntxt.exe', prefix: '', suffix: '', infix_bidi: "\u{202E}", infix_pos: 12)
    # => "document_ann‮txt.exe"
    puts ex
    # document_ann‮txt.exe

Parameters:

- input (`String`) —

  input string

- opts (`Hash`) —

  optional parameters

Options Hash (`**opts`):

- :prefix (`String`) —

  Prefix Bidi. Default: RLO (U+202E).

- :suffix (`String`) —

  Suffix Bidi. Default: PDF (U+202C).

- :infix_bidi (`String`) —

  Bidi injected at a chosen position. Default: none (empty string).

- :infix_pos (`String`) —

  Position (index) where to inject an extra BiDi. Default: 0.

Returns:

- (`String`) —

  spoof payload (input string with injected BiDi)

    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    # File 'lib/unisec/bidi.rb', line 112

    def self.bidi_affix(input, **opts)
      opts[:prefix] ||= "\u{202E}" # RLO
      opts[:suffix] ||= "\u{202C}" # PDF
      opts[:infix_bidi] ||= ''
      opts[:infix_pos] ||= 0

      out = "#{opts[:prefix]}#{input}#{opts[:suffix]}"
      out.insert(opts[:infix_pos], opts[:infix_bidi])
      out
    end

### .reverse(target, **opts) ⇒ `String`

Reverse the (sub)-string (grapheme cluster aware)

#### Examples:

    Unisec::Bidi::Spoof.reverse('document_anntxt.exe', index: 12)
    # => "document_annexe.txt"

    Unisec::Bidi::Spoof.reverse("🇫🇷🐓")
    # => "🐓🇫🇷"

Parameters:

- target (`String`) —

  string to reverse

- opts (`Hash`) —

  optional parameters

Options Hash (`**opts`):

- :index (`String`) —

  Index at which the revese starts (before this position will be left untouched)

Returns:

- (`String`) —

  the reversed string

    62
    63
    64
    65
    66
    # File 'lib/unisec/bidi.rb', line 62

    def self.reverse(target, **opts)
      opts[:index] ||= 0

      target[0...opts[:index]] + Unisec::Utils::String.grapheme_reverse(target[opts[:index]..])
    end

## Instance Method Details

### #bidi_affix ⇒ `Object`

Call bidi_affix with `@spoof_string` as input.

    124
    125
    126
    # File 'lib/unisec/bidi.rb', line 124

    def bidi_affix(**)
      Spoof.bidi_affix(@spoof_string, **)
    end

### #display(light: false) ⇒ `String`

Display a CLI-friendly output summurizing the spoof payload

The light version displays only the spoof payload for easy piping with other commands.

#### Examples:

    puts Unisec::Bidi::Spoof.new('noraj').display
    # Target string: noraj
    # Spoof payload (display) ⚠: ‮jaron‬
    # Spoof string 🛈: jaron
    # Spoof payload (hex): e280ae6a61726f6ee280ac
    # Spoof payload (hex, escaped): \xe2\x80\xae\x6a\x61\x72\x6f\x6e\xe2\x80\xac
    # Spoof payload (base64): 4oCuamFyb27igKw=
    # Spoof payload (urlencode): %E2%80%AEjaron%E2%80%AC
    # Spoof payload (code points): U+202E U+006A U+0061 U+0072 U+006F U+006E U+202C
    #
    #
    #
    # ⚠: for the spoof payload to display correctly, be sure your VTE has RTL support, e.g. see https://wiki.archlinux.org/title/Bidirectional_text#Terminal.
    # 🛈: Does not contain the BiDi character (e.g. RtLO).

    puts Unisec::Bidi::Spoof.new('noraj').display(light: true)
    # ‮jaron‬

Parameters:

- light (`Boolean`) (defaults to: `false`) —

  `true` = light display (displays only the spoof payload for easy piping with other commands), `false` (default) = full display.

Returns:

- (`String`) —

  CLI-ready output

    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    # File 'lib/unisec/bidi.rb', line 151

    def display(light: false)
      if light == false # full display
        "Target string: #{@target_display}\n" \
          "Spoof payload (display) ⚠: #{@spoof_payload}\n" \
          "Spoof string 🛈: #{@spoof_string}\n" \
          "Spoof payload (hex): #{@spoof_payload.to_hex}\n" \
          "Spoof payload (hex, escaped): #{@spoof_payload.to_hex(prefixall: '\\x')}\n" \
          "Spoof payload (base64): #{@spoof_payload.to_b64}\n" \
          "Spoof payload (urlencode): #{@spoof_payload.urlencode}\n" \
          "Spoof payload (code points): #{Unisec::Utils::String.chars2codepoints(@spoof_payload)}\n" \
          "\n\n\n" \
          '⚠: for the spoof payload to display correctly, be sure your VTE has RTL support, ' \
          "e.g. see https://wiki.archlinux.org/title/Bidirectional_text#Terminal.\n" \
          '🛈: Does not contain the BiDi character (e.g. RtLO).'
      else # light display
        @spoof_payload
      end
    end

### #reverse ⇒ `Object`

Call reverse with `@target_display` as default input (target).

    69
    70
    71
    # File 'lib/unisec/bidi.rb', line 69

    def reverse(**)
      Spoof.reverse(@target_display, **)
    end

### #set_target_display(input, **opts) ⇒ `String`

Set a new target string to spoof

It will automatically set `@spoof_string` and `@spoof_payload` as well.

Parameters:

- input (`String`) —

  the target string

- opts (`Hash`) —

  optional parameters, see bidi_affix

Returns:

- (`String`) —

  the target string

    21
    22
    23
    24
    25
    26
    # File 'lib/unisec/bidi.rb', line 21

    def set_target_display(input, **opts)
      @target_display = input
      @spoof_string = reverse(**opts)
      @spoof_payload = bidi_affix(**opts)
      @target_display
    end