1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
# Description: fix arbitrary code execution via crafted hostname
3
# Author: Marius Tomaschewski
4
# Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621099
7
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' dhcp3-3.1.3~/client/dhclient.c dhcp3-3.1.3/client/dhclient.c
8
--- dhcp3-3.1.3~/client/dhclient.c 2011-04-11 08:57:02.976060280 -0400
9
+++ dhcp3-3.1.3/client/dhclient.c 2011-04-11 08:57:16.536060277 -0400
14
+static int check_domain_name(const char *ptr, size_t len, int dots);
15
+static int check_domain_name_list(const char *ptr, size_t len, int dots);
16
+static int check_option_values(struct universe *universe, unsigned int opt,
17
+ const char *ptr, size_t len);
19
static void usage PROTO ((void));
21
int main (argc, argv, envp)
22
@@ -2524,13 +2529,23 @@
25
if (dhcp_option_ev_name (name, sizeof name,
27
- client_envadd (es -> client, es -> prefix,
29
- (pretty_print_option
31
- data.data, data.len,
35
+ value = pretty_print_option(oc->option,
38
+ size_t length = strlen(value);
40
+ if (check_option_values(oc->option->universe,
42
+ value, length) == 0) {
43
+ client_envadd(es->client, es->prefix,
46
+ log_error("suspect value in %s "
47
+ "option - discarded",
50
data_string_forget (&data, MDL);
53
@@ -2610,12 +2625,32 @@
54
data_string_forget (&data, MDL);
57
- if (lease -> filename)
58
- client_envadd (client,
59
- prefix, "filename", "%s", lease -> filename);
60
- if (lease -> server_name)
61
- client_envadd (client, prefix, "server_name",
62
- "%s", lease -> server_name);
63
+ if (lease->filename) {
64
+ if (check_option_values(NULL, DHO_ROOT_PATH,
66
+ strlen(lease->filename)) == 0) {
67
+ client_envadd(client, prefix, "filename",
68
+ "%s", lease->filename);
70
+ log_error("suspect value in %s "
71
+ "option - discarded",
76
+ if (lease->server_name) {
77
+ if (check_option_values(NULL, DHO_HOST_NAME,
79
+ strlen(lease->server_name)) == 0 ) {
80
+ client_envadd (client, prefix, "server_name",
81
+ "%s", lease->server_name);
83
+ log_error("suspect value in %s "
84
+ "option - discarded",
90
for (i = 0; i < lease -> options -> universe_count; i++) {
91
option_space_foreach ((struct packet *)0, (struct lease *)0,
92
@@ -3239,3 +3274,112 @@
93
data_string_forget (&ddns_dhcid, MDL);
98
+ * The following routines are used to check that certain
99
+ * strings are reasonable before we pass them to the scripts.
100
+ * This avoids some problems with scripts treating the strings
101
+ * as commands - see ticket 23722
102
+ * The domain checking code should be done as part of assembling
103
+ * the string but we are doing it here for now due to time
107
+static int check_domain_name(const char *ptr, size_t len, int dots)
111
+ /* not empty or complete length not over 255 characters */
112
+ if ((len == 0) || (len > 256))
115
+ /* consists of [[:alnum:]-]+ labels separated by [.] */
116
+ /* a [_] is against RFC but seems to be "widely used"... */
117
+ for (p=ptr; (*p != 0) && (len-- > 0); p++) {
118
+ if ((*p == '-') || (*p == '_')) {
119
+ /* not allowed at begin or end of a label */
120
+ if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
122
+ } else if (*p == '.') {
123
+ /* each label has to be 1-63 characters;
124
+ we allow [.] at the end ('foo.bar.') */
125
+ size_t d = p - ptr;
126
+ if ((d <= 0) || (d >= 64))
128
+ ptr = p + 1; /* jump to the next label */
129
+ if ((dots > 0) && (len > 0))
131
+ } else if (isalnum((unsigned char)*p) == 0) {
132
+ /* also numbers at the begin are fine */
136
+ return(dots ? -1 : 0);
139
+static int check_domain_name_list(const char *ptr, size_t len, int dots)
142
+ int ret = -1; /* at least one needed */
144
+ if ((ptr == NULL) || (len == 0))
147
+ for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
151
+ if (check_domain_name(ptr, p - ptr, dots) != 0)
158
+ return(check_domain_name(ptr, p - ptr, dots));
163
+static int check_option_values(struct universe *universe,
171
+ /* just reject options we want to protect, will be escaped anyway */
172
+ if ((universe == NULL) || (universe == &dhcp_universe)) {
174
+ case DHO_HOST_NAME:
175
+ case DHO_NIS_DOMAIN:
176
+ case DHO_NETBIOS_SCOPE:
177
+ return check_domain_name(ptr, len, 0);
179
+ case DHO_DOMAIN_NAME: /* accept a list for compatibiliy */
180
+ return check_domain_name_list(ptr, len, 0);
182
+ case DHO_ROOT_PATH:
185
+ for (; (*ptr != 0) && (len-- > 0); ptr++) {
186
+ if(!(isalnum((unsigned char)*ptr) ||
187
+ *ptr == '#' || *ptr == '%' ||
188
+ *ptr == '+' || *ptr == '-' ||
189
+ *ptr == '_' || *ptr == ':' ||
190
+ *ptr == '.' || *ptr == ',' ||
191
+ *ptr == '@' || *ptr == '~' ||
192
+ *ptr == '\\' || *ptr == '/' ||
193
+ *ptr == '[' || *ptr == ']' ||
194
+ *ptr == '=' || *ptr == ' '))
205
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' dhcp3-3.1.3~/common/options.c dhcp3-3.1.3/common/options.c
206
--- dhcp3-3.1.3~/common/options.c 2011-04-11 08:57:02.966060280 -0400
207
+++ dhcp3-3.1.3/common/options.c 2011-04-11 08:57:16.536060277 -0400
208
@@ -2951,7 +2951,8 @@
211
} else if (**src == '"' || **src == '\'' || **src == '$' ||
212
- **src == '`' || **src == '\\') {
213
+ **src == '`' || **src == '\\' || **src == '|' ||