Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_ssrf.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#include "nilorea/n_log.h"
29#include "nilorea/n_ssrf.h"
30
31#include <string.h>
32
33static int failures = 0;
34
35#define OK4(a, b, c, d) \
36 do { \
37 const uint8_t ip[4] = {a, b, c, d}; \
38 if (!n_ssrf_ipv4_allowed(ip)) { \
39 n_log(LOG_ERR, "FAIL: %d.%d.%d.%d should be allowed", a, b, c, \
40 d); \
41 failures++; \
42 } \
43 } while (0)
44
45#define NO4(a, b, c, d) \
46 do { \
47 const uint8_t ip[4] = {a, b, c, d}; \
48 if (n_ssrf_ipv4_allowed(ip)) { \
49 n_log(LOG_ERR, "FAIL: %d.%d.%d.%d should be blocked", a, b, c, \
50 d); \
51 failures++; \
52 } \
53 } while (0)
54
55int main(void) {
57
58 /* public unicast: allowed */
59 OK4(8, 8, 8, 8);
60 OK4(1, 1, 1, 1);
61 OK4(93, 184, 216, 34);
62
63 /* private / reserved / special: blocked */
64 NO4(0, 0, 0, 0); /* this host */
65 NO4(10, 0, 0, 1); /* RFC1918 */
66 NO4(127, 0, 0, 1); /* loopback */
67 NO4(169, 254, 169, 254); /* link-local metadata endpoint */
68 NO4(172, 16, 0, 1); /* RFC1918 */
69 NO4(192, 168, 1, 1); /* RFC1918 */
70 NO4(100, 64, 0, 1); /* CGNAT */
71 NO4(224, 0, 0, 1); /* multicast */
72 NO4(255, 255, 255, 255); /* broadcast/reserved */
73
74 /* NULL is rejected */
75 if (n_ssrf_ipv4_allowed(NULL) || n_ssrf_ipv6_allowed(NULL)) {
76 n_log(LOG_ERR, "FAIL: NULL must be rejected");
77 failures++;
78 }
79
80 /* IPv6: loopback blocked, a public v6 allowed */
81 {
82 uint8_t lo[16] = {0};
83 uint8_t pub[16] = {0x26, 0x06, 0x47, 0x00}; /* 2606:4700:: public */
84 lo[15] = 1;
85 if (n_ssrf_ipv6_allowed(lo)) {
86 n_log(LOG_ERR, "FAIL: ::1 must be blocked");
87 failures++;
88 }
89 if (!n_ssrf_ipv6_allowed(pub)) {
90 n_log(LOG_ERR, "FAIL: a public v6 should be allowed");
91 failures++;
92 }
93 }
94
95 /* the smuggling cases: a private IPv4 wrapped in IPv6 must stay blocked */
96 {
97 /* ::ffff:127.0.0.1 (IPv4-mapped loopback) */
98 uint8_t mapped[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff,
99 127, 0, 0, 1};
100 /* 64:ff9b::a00:1 (NAT64 wrapping 10.0.0.1) */
101 uint8_t nat64[16] = {0x00, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0,
102 10, 0, 0, 1};
103 /* 2002:c0a8:0101:: (6to4 wrapping 192.168.1.1) */
104 uint8_t sixto4[16] = {0x20, 0x02, 192, 168, 1, 1};
105 if (n_ssrf_ipv6_allowed(mapped) || n_ssrf_ipv6_allowed(nat64) ||
106 n_ssrf_ipv6_allowed(sixto4)) {
107 n_log(LOG_ERR, "FAIL: a private IPv4 smuggled in IPv6 must block");
108 failures++;
109 }
110 }
111
112 if (failures) {
113 n_log(LOG_ERR, "ex_ssrf: %d failure(s)", failures);
114 return 1;
115 }
116 n_log(LOG_NOTICE, "ex_ssrf: all checks passed");
117 return 0;
118}
static int failures
Definition ex_atlas.c:51
int main(void)
Definition ex_atlas.c:117
#define NO4(a, b, c, d)
Definition ex_ssrf.c:45
#define OK4(a, b, c, d)
Definition ex_ssrf.c:35
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
Generic log system.
int n_ssrf_ipv4_allowed(const uint8_t ip[4])
classify an IPv4 address as safe-to-connect or not
Definition n_ssrf.c:60
int n_ssrf_ipv6_allowed(const uint8_t ip[16])
classify an IPv6 address as safe-to-connect or not
Definition n_ssrf.c:101
SSRF address guard: is a resolved IP a public, routable unicast address?