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 +4 -4
- data/lib/unisec/cli/cli.rb +2 -1
- data/lib/unisec/cli/normalization.rb +71 -39
- data/lib/unisec/normalization.rb +43 -0
- data/lib/unisec/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60d2859aca7324908f4894b8ca2cc99b145657e7ea68fbc51e11a1e787886a57
|
4
|
+
data.tar.gz: 4c426795faa520f02daec94f1cf14379a4a994a0902cc52640e2a358b210c28b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d5c67bf6bc1e76253971cc4b3bdccc513fb13fd3d3fa2dcdffa97329e09b45654b2f2f0a2c734e54c87bcffdb71adfa392a352ec757b6de0f761feaa8b73d28
|
7
|
+
data.tar.gz: 7be763bb5b2adb2139771c3e3f789c101f884209c7ca7e5488df18e97c6cac25578b11c34b451efaddeb11a9926fefeb935857da32a33e3de192b0e39cb46532
|
data/lib/unisec/cli/cli.rb
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
data/lib/unisec/normalization.rb
CHANGED
@@ -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
|
data/lib/unisec/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2024-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ctf-party
|