aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca <deri@ntop.org>2022-02-03 09:17:54 +0100
committerLuca <deri@ntop.org>2022-02-03 09:17:54 +0100
commit37ff626e78149b4eb877b042672801b58d797100 (patch)
tree7654aeb95ebd3761a18ab49176d82bad1785f962
parentcd3d720ae36e943a3e9ddd7275b983df6c6652d0 (diff)
Added new IDN/Punycode risk for spotting internationalized domain names
-rw-r--r--doc/flow_risks.rst6
-rw-r--r--python/ndpi.py1
-rw-r--r--src/include/ndpi_typedefs.h1
-rw-r--r--src/lib/ndpi_main.c11
-rw-r--r--src/lib/ndpi_utils.c4
-rw-r--r--tests/pcap/punycode-idn.pcapbin0 -> 2236 bytes
-rw-r--r--tests/result/punycode-idn.pcap.out13
-rw-r--r--wireshark/ndpi.lua1
8 files changed, 35 insertions, 2 deletions
diff --git a/doc/flow_risks.rst b/doc/flow_risks.rst
index 52e19212c..890347e02 100644
--- a/doc/flow_risks.rst
+++ b/doc/flow_risks.rst
@@ -253,3 +253,9 @@ The risk is set whenever a possible exploit (e.g. Log4J/Log4Shell) is detected.
NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE
===================================
The risk is set whenever a TLS certificate is close to the expiration date.
+
+.. _Risk 042:
+
+NDPI_PUNYCODE_IDN
+===================================
+The risk is set whenever a domain name is specified in IDN format
diff --git a/python/ndpi.py b/python/ndpi.py
index 8b90c912e..1b47d8a17 100644
--- a/python/ndpi.py
+++ b/python/ndpi.py
@@ -333,6 +333,7 @@ typedef enum {
NDPI_INVALID_CHARACTERS,
NDPI_POSSIBLE_EXPLOIT,
NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE,
+ NDPI_PUNYCODE_IDN,
/* Leave this as last member */
NDPI_MAX_RISK
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index c5e98ec78..e1e5dc90c 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -116,6 +116,7 @@ typedef enum {
NDPI_INVALID_CHARACTERS,
NDPI_POSSIBLE_EXPLOIT, /* Log4J and other exploits */
NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE,
+ NDPI_PUNYCODE_IDN, /* https://en.wikipedia.org/wiki/Punycode */
/* Leave this as last member */
NDPI_MAX_RISK /* must be <= 63 due to (**) */
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 063b65a54..a72eff8b8 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -110,6 +110,7 @@ static ndpi_risk_info ndpi_known_risks[] = {
{ NDPI_INVALID_CHARACTERS, NDPI_RISK_HIGH, CLIENT_HIGH_RISK_PERCENTAGE },
{ NDPI_POSSIBLE_EXPLOIT, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE },
{ NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE, NDPI_RISK_MEDIUM, CLIENT_LOW_RISK_PERCENTAGE },
+ { NDPI_PUNYCODE_IDN, NDPI_RISK_LOW, CLIENT_LOW_RISK_PERCENTAGE },
/* Leave this as last member */
{ NDPI_MAX_RISK, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE }
@@ -7246,11 +7247,13 @@ u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_
memset(ret_match, 0, sizeof(*ret_match));
- rc = ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len,
+ rc = ndpi_automa_match_string_subprotocol(ndpi_str, flow,
+ string_to_match, string_to_match_len,
master_protocol_id, ret_match);
id = ret_match->protocol_category;
- if(ndpi_get_custom_category_match(ndpi_str, string_to_match, string_to_match_len, &id) != -1) {
+ if(ndpi_get_custom_category_match(ndpi_str, string_to_match,
+ string_to_match_len, &id) != -1) {
/* if(id != -1) */ {
flow->category = ret_match->protocol_category = id;
rc = master_protocol_id;
@@ -7266,6 +7269,10 @@ u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_
ndpi_set_risk(ndpi_str, flow, NDPI_RISKY_DOMAIN);
}
+ /* Add punycode check */
+ if(ndpi_strnstr(string_to_match, "xn--", string_to_match_len))
+ ndpi_set_risk(ndpi_str, flow, NDPI_PUNYCODE_IDN);
+
return(rc);
}
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index 521e57615..dea83dbdc 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -1844,6 +1844,10 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) {
case NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE:
return("TLS Certificate About To Expire");
break;
+
+ case NDPI_PUNYCODE_IDN:
+ return("IDN Domain Name");
+ break;
default:
snprintf(buf, sizeof(buf), "%d", (int)risk);
diff --git a/tests/pcap/punycode-idn.pcap b/tests/pcap/punycode-idn.pcap
new file mode 100644
index 000000000..fe7354dee
--- /dev/null
+++ b/tests/pcap/punycode-idn.pcap
Binary files differ
diff --git a/tests/result/punycode-idn.pcap.out b/tests/result/punycode-idn.pcap.out
new file mode 100644
index 000000000..769a639f5
--- /dev/null
+++ b/tests/result/punycode-idn.pcap.out
@@ -0,0 +1,13 @@
+Guessed flow protos: 1
+
+DPI Packets (TCP): 8 (8.00 pkts/flow)
+DPI Packets (UDP): 4 (2.00 pkts/flow)
+Confidence DPI : 3 (flows)
+
+DNS 2 162 1
+HTTP 12 1597 1
+Spotify 2 197 1
+
+ 1 TCP 192.168.2.140:56011 <-> 170.33.9.230:80 [proto: 7/HTTP][ClearText][Confidence: DPI][cat: Web/5][7 pkts/568 bytes <-> 5 pkts/1029 bytes][Goodput ratio: 29/69][0.57 sec][Hostname/SNI: www.love.xn--55qx5d][bytes ratio: -0.289 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 77/122 222/352 90/163][Pkt Len c2s/s2c min/avg/max/stddev: 54/60 81/206 137/765 36/280][URL: www.love.xn--55qx5d/][StatusCode: 403][Content-Type: text/html][User-Agent: curl/7.77.0][Risk: ** IDN Domain Name **][Risk Score: 10][PLAIN TEXT (GET / HTTP/1.1)][Plen Bins: 0,0,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+ 2 UDP 192.168.2.140:45520 <-> 192.168.2.1:53 [proto: 5.156/DNS.Spotify][ClearText][Confidence: DPI][cat: Music/25][1 pkts/69 bytes <-> 1 pkts/128 bytes][Goodput ratio: 39/67][0.02 sec][Hostname/SNI: i.scdn.co][146.75.62.248][PLAIN TEXT (scdnco)][Plen Bins: 50,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+ 3 UDP 192.168.2.140:60156 <-> 192.168.2.1:53 [proto: 5/DNS][ClearText][Confidence: DPI][cat: Network/14][1 pkts/81 bytes <-> 1 pkts/81 bytes][Goodput ratio: 48/48][0.00 sec][Hostname/SNI: www.xn--mnich-kva.com][::][Risk: ** IDN Domain Name **][Risk Score: 10][Plen Bins: 0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
diff --git a/wireshark/ndpi.lua b/wireshark/ndpi.lua
index ff6c255d0..dfda193ec 100644
--- a/wireshark/ndpi.lua
+++ b/wireshark/ndpi.lua
@@ -80,6 +80,7 @@ flow_risks[38] = ProtoField.bool("ndpi.flow_risk.dns_fragmented", "DNS fragmente
flow_risks[39] = ProtoField.bool("ndpi.flow_risk.invalid_characters", "Invalid characters", num_bits_flow_risks, nil, bit(7), "nDPI Flow Risk: Text contains non-printable characters")
flow_risks[40] = ProtoField.bool("ndpi.flow_risk.possible_exploit", "Possible Exploit", num_bits_flow_risks, nil, bit(8), "nDPI Flow Risk: Possible exploit detected")
flow_risks[41] = ProtoField.bool("ndpi.flow_risk.cert_about_to_expire", "TLS cert about to expire", num_bits_flow_risks, nil, bit(9), "nDPI Flow Risk: TLS certificate about to expire")
+flow_risks[42] = ProtoField.bool("ndpi.flow_risk.punycode_idn", "IDN Domain Name", num_bits_flow_risks, nil, bit(10), "nDPI Flow Risk: IDN Domain Name")
-- Last one: keep in sync the bitmask when adding new risks!!
flow_risks[64] = ProtoField.new("Unused", "ndpi.flow_risk.unused", ftypes.UINT32, nil, base.HEX, bit(32) - bit(10))