unisec 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b6f74de3dc3d0f9aebac59ff68bc5731b7185e9e73e86e87477c23408900452
4
- data.tar.gz: 910be7b95b71022f352cc6d612c7752fe2ea13a0e6e3dc89aca4566cb1879569
3
+ metadata.gz: 60d2859aca7324908f4894b8ca2cc99b145657e7ea68fbc51e11a1e787886a57
4
+ data.tar.gz: 4c426795faa520f02daec94f1cf14379a4a994a0902cc52640e2a358b210c28b
5
5
  SHA512:
6
- metadata.gz: 47b730a884a30979be5968d90a30bc214ec93725383f20c48a02ec1090ce64e6043f95427c7ed79ebc31b3b4e1d3b66e01c7b0d63f936793f6c8eb008ce5f9fe
7
- data.tar.gz: be9ca5cc40baaf9cd56141a3a8e41f5709c6071d5e7797ebd64a1daf231671e6835c168bce53f540e72ead4f68fc93bfd2d211764ba474e1cd8a4ca1bf5e7a65
6
+ metadata.gz: 8d5c67bf6bc1e76253971cc4b3bdccc513fb13fd3d3fa2dcdffa97329e09b45654b2f2f0a2c734e54c87bcffdb71adfa392a352ec757b6de0f761feaa8b73d28
7
+ data.tar.gz: 7be763bb5b2adb2139771c3e3f789c101f884209c7ca7e5488df18e97c6cac25578b11c34b451efaddeb11a9926fefeb935857da32a33e3de192b0e39cb46532
@@ -24,7 +24,8 @@ module Unisec
24
24
  register 'confusables randomize', Confusables::Randomize
25
25
  register 'grep', Grep
26
26
  register 'hexdump', Hexdump
27
- register 'normalize', Normalize
27
+ register 'normalize all', Normalize::All
28
+ register 'normalize replace', Normalize::Replace
28
29
  register 'properties char', Properties::Char
29
30
  register 'properties codepoints', Properties::Codepoints
30
31
  register 'properties list', Properties::List
@@ -8,45 +8,77 @@ module Unisec
8
8
  module CLI
9
9
  module Commands
10
10
  # CLI sub-commands `unisec normalize xxx` for the class {Unisec::Normalization} from the lib.
11
- #
12
- # Command `unisec normalize "example"`
13
- #
14
- # Example:
15
- #
16
- # ```plaintext
17
- # ➜ unisec normalize ẛ̣
18
- # Original: ẛ̣
19
- # U+1E9B U+0323
20
- # NFC: ẛ̣
21
- # U+1E9B U+0323
22
- # NFKC: ṩ
23
- # U+1E69
24
- # NFD: ẛ̣
25
- # U+017F U+0323 U+0307
26
- # NFKD: ṩ
27
- # U+0073 U+0323 U+0307
28
- #
29
- # ➜ unisec normalize ẛ̣ --form nfkd
30
- # ṩ
31
- # ```
32
- class Normalize < Dry::CLI::Command
33
- desc 'Normalize in all forms'
34
-
35
- argument :input, required: true,
36
- desc: 'String input. Read from STDIN if equal to -.'
37
-
38
- option :form, default: nil, values: %w[nfc nfkc nfd nfkd],
39
- desc: 'Output only in the specified normalization form.'
40
-
41
- # Normalize in all forms
42
- # @param input [String] Input string to normalize
43
- def call(input: nil, **options)
44
- input = $stdin.read.chomp if input == '-'
45
- if options[:form].nil?
46
- puts Unisec::Normalization.new(input).display
47
- else
48
- # using send() is safe here thanks to the value whitelist
49
- puts Unisec::Normalization.send(options[:form], input)
11
+ module Normalize
12
+ # Command `unisec normalize all "example"`
13
+ #
14
+ # Example:
15
+ #
16
+ # ```plaintext
17
+ # ➜ unisec normalize all ẛ̣
18
+ # Original: ẛ̣
19
+ # U+1E9B U+0323
20
+ # NFC: ẛ̣
21
+ # U+1E9B U+0323
22
+ # NFKC: ṩ
23
+ # U+1E69
24
+ # NFD: ẛ̣
25
+ # U+017F U+0323 U+0307
26
+ # NFKD: ṩ
27
+ # U+0073 U+0323 U+0307
28
+ #
29
+ # ➜ unisec normalize all ẛ̣ --form nfkd
30
+ # ṩ
31
+ # ```
32
+ class All < Dry::CLI::Command
33
+ desc 'Normalize in all forms'
34
+
35
+ argument :input, required: true,
36
+ desc: 'String input. Read from STDIN if equal to -.'
37
+
38
+ option :form, default: nil, values: %w[nfc nfkc nfd nfkd],
39
+ desc: 'Output only in the specified normalization form.'
40
+
41
+ # Normalize in all forms
42
+ # @param input [String] Input string to normalize
43
+ def call(input: nil, **options)
44
+ input = $stdin.read.chomp if input == '-'
45
+ if options[:form].nil?
46
+ puts Unisec::Normalization.new(input).display
47
+ else
48
+ # using send() is safe here thanks to the value whitelist
49
+ puts Unisec::Normalization.send(options[:form], input)
50
+ end
51
+ end
52
+ end
53
+
54
+ # Command `unisec normalize replace "example"`
55
+ #
56
+ # Example:
57
+ #
58
+ # ```plaintext
59
+ # ➜ unisec normalize replace "<svg onload=\"alert('XSS')\">"
60
+ # Original: <svg onload="alert('XSS')">
61
+ # U+003C U+0073 U+0076 U+0067 U+0020 U+006F U+006E U+006C U+006F U+0061 U+0064 U+003D U+0022 U+0061 U+006C U+0065 U+0072 U+0074 U+0028 U+0027 U+0058 U+0053 U+0053 U+0027 U+0029 U+0022 U+003E
62
+ # Bypass payload: ﹤svg onload="alert('XSS')"﹥
63
+ # U+FE64 U+0073 U+0076 U+0067 U+0020 U+006F U+006E U+006C U+006F U+0061 U+0064 U+003D U+FF02 U+0061 U+006C U+0065 U+0072 U+0074 U+0028 U+FF07 U+0058 U+0053 U+0053 U+FF07 U+0029 U+FF02 U+FE65
64
+ # NFKC: <svg onload="alert('XSS')">
65
+ # U+003C U+0073 U+0076 U+0067 U+0020 U+006F U+006E U+006C U+006F U+0061 U+0064 U+003D U+0022 U+0061 U+006C U+0065 U+0072 U+0074 U+0028 U+0027 U+0058 U+0053 U+0053 U+0027 U+0029 U+0022 U+003E
66
+ # NFKD: <svg onload="alert('XSS')">
67
+ # U+003C U+0073 U+0076 U+0067 U+0020 U+006F U+006E U+006C U+006F U+0061 U+0064 U+003D U+0022 U+0061 U+006C U+0065 U+0072 U+0074 U+0028 U+0027 U+0058 U+0053 U+0053 U+0027 U+0029 U+0022 U+003E
68
+ #
69
+ # ➜ echo -n "<svg onload=\"alert('XSS')\">" | unisec normalize replace -
70
+ # ```
71
+ class Replace < Dry::CLI::Command
72
+ desc 'Prepare a XSS payload for HTML escape bypass (HTML escape followed by NFKC / NFKD normalization)'
73
+
74
+ argument :input, required: true,
75
+ desc: 'String input. Read from STDIN if equal to -.'
76
+
77
+ # Prepare a XSS payload for HTML escape bypass (HTML escape followed by NFKC / NFKD normalization)
78
+ # @param input [String] Input string to normalize
79
+ def call(input: nil, **_options)
80
+ input = $stdin.read.chomp if input == '-'
81
+ puts Unisec::Normalization.new(input).display_replace
50
82
  end
51
83
  end
52
84
  end
@@ -5,6 +5,16 @@ require 'ctf_party'
5
5
  module Unisec
6
6
  # Normalization Forms
7
7
  class Normalization
8
+ # HTML escapable characters mapped with their Unicode counterparts that will
9
+ # cast to themself after applying normalization forms using compatibility mode.
10
+ HTML_ESCAPE_BYPASS = {
11
+ '<' => ['﹤', '<'],
12
+ '>' => ['﹥', '>'],
13
+ '"' => ['"'],
14
+ "'" => ['''],
15
+ '&' => ['﹠', '&']
16
+ }.freeze
17
+
8
18
  # Original input
9
19
  # @return [String] untouched input
10
20
  attr_reader :original
@@ -64,6 +74,25 @@ module Unisec
64
74
  str.unicode_normalize(:nfkd)
65
75
  end
66
76
 
77
+ # Replace HTML escapable characters with their Unicode counterparts that will
78
+ # cast to themself after applying normalization forms using compatibility mode.
79
+ # Usefull for XSS, to bypass HTML escape.
80
+ # If several values are possible, one is picked randomly.
81
+ # @param str [String] the target string
82
+ # @return [String] escaped input
83
+ def self.replace_bypass(str)
84
+ str = str.dup
85
+ HTML_ESCAPE_BYPASS.each do |k, v|
86
+ str.gsub!(k, v.sample)
87
+ end
88
+ str
89
+ end
90
+
91
+ # Instance version of {Normalization.replace_bypass}.
92
+ def replace_bypass
93
+ Normalization.replace_bypass(@original)
94
+ end
95
+
67
96
  # Display a CLI-friendly output summurizing all normalization forms
68
97
  # @return [String] CLI-ready output
69
98
  # @example
@@ -90,5 +119,19 @@ module Unisec
90
119
  colorize.call('NFD', @nfd) +
91
120
  colorize.call('NFKD', @nfkd)
92
121
  end
122
+
123
+ # Display a CLI-friendly output of the XSS payload to bypass HTML escape and
124
+ # what it does once normalized in NFKC & NFKD.
125
+ def display_replace
126
+ colorize = lambda { |form_title, form_attr|
127
+ "#{Paint[form_title.to_s, :underline,
128
+ :bold]}: #{form_attr}\n #{Paint[Unisec::Properties.chars2codepoints(form_attr), :red]}\n"
129
+ }
130
+ payload = replace_bypass
131
+ colorize.call('Original', @original) +
132
+ colorize.call('Bypass payload', payload) +
133
+ colorize.call('NFKC', Normalization.nfkc(payload)) +
134
+ colorize.call('NFKD', Normalization.nfkd(payload))
135
+ end
93
136
  end
94
137
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Unisec
4
4
  # Version of unisec library and app
5
- VERSION = '0.0.5'
5
+ VERSION = '0.0.6'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unisec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre ZANNI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-16 00:00:00.000000000 Z
11
+ date: 2024-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ctf-party