OpenVAS Libraries  9.0.3
www_funcs.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

char * build_encode_URL (struct arglist *, char *, char *, char *, char *)
 

Function Documentation

◆ build_encode_URL()

char* build_encode_URL ( struct arglist ,
char *  ,
char *  ,
char *  ,
char *   
)
Todo:
Evaluate if GLib functions for building paths are applicable here

Definition at line 83 of file www_funcs.c.

85 {
86  int i, l = 0, n_slash = 0, n_backslash = 0, start_with_slash = 0;
87  char *ret, *ret2;
88  /* NIDS evasion options */
89  char *s, *s2;
90  int double_slash, reverse_traversal, self_ref_dir;
91  int prem_req_end, param_hiding, cgipm_param;
92  int dos_win_syntax, null_method, tab_sep, http09;
93  char *abs_URI_type, *abs_URI_host;
94  char sep_c;
95 #define URL_CODE_NONE 0
96 #define URL_CODE_HEX 1
97 #define URL_CODE_UTF16 2
98 #define URL_CODE_UTF16MS 3
99 #define URL_CODE_UTF8BAD 4
100  int url_encoding;
101  char gizmo[32];
102  kb_t kb = plug_get_kb (data);
103 
104  /* Basically, we need to store the path, a slash, and the name.
105  * Encoding will expand this
106  * We'll add the method in front of all this and the HTTP version
107  * at the end when all is done. That's not optimized, but that's simpler.
108  */
109  l = path != NULL ? strlen (path) : 0;
110  l += strlen (name) + (path != NULL);
111 
113  ret = g_malloc0 (l + 1);
114  if (path == NULL)
115  strcpy (ret, name);
116  else
117  sprintf (ret, "%s/%s", path, name);
118 
119 #ifdef URL_DEBUG
120  log_legacy_write ("Request => %s\n", ret);
121 #endif
122 
123  for (s = ret; *s != '\0'; s++)
124  if (*s == '/')
125  n_slash++;
126  else if (*s == '\\')
127  n_backslash++;
128 
129  if (kb_item_get_int (kb, "NIDS/HTTP/enabled") != 1)
130  {
131  ret2 = g_strdup_printf ("%s %s %s", method, ret, httpver);
132  g_free (ret);
133  return ret2;
134  }
135 
136  start_with_slash = (*ret == '/');
137 
138  s = kb_item_get_str (kb, "NIDS/HTTP/CGIpm_param");
139  cgipm_param = (s != NULL && strcmp (s, "yes") == 0);
140  if (cgipm_param)
141  {
142 #ifdef URL_DEBUG
143  i = 0;
144 #endif
145  for (s = ret; *s != '\0' && *s != '?'; s++)
146  ;
147  if (*s == '?')
148  for (; *s != '\0'; s++)
149  if (*s == '&')
150  {
151  *s = ';';
152 #ifdef URL_DEBUG
153  i++;
154 #endif
155  }
156 #ifdef URL_DEBUG
157  if (i > 0)
158  log_legacy_write ("Request = %s\n", ret);
159 #endif
160  }
161 
162  s = kb_item_get_str (kb, "NIDS/HTTP/self_ref_dir");
163  self_ref_dir = (s != NULL && strcmp (s, "yes") == 0);
164  if (self_ref_dir)
165  {
166  l += 2 * n_slash;
167  ret2 = g_malloc0 (l + 1);
168  for (s = ret, s2 = ret2; *s != '\0' && *s != '?'; s++)
169  if (*s != '/')
170  *s2++ = *s;
171  else
172  {
173  strncpy (s2, "/./", l);
174  s2 += 3;
175  }
176  while (*s != '\0')
177  *s2++ = *s++;
178  *s2 = '\0';
179  g_free (ret);
180  ret = ret2;
181  n_slash *= 2;
182 #ifdef URL_DEBUG
183  log_legacy_write ("Request = %s\n", ret);
184 #endif
185  }
186 
187  s = kb_item_get_str (kb, "NIDS/HTTP/reverse_traversal");
188  reverse_traversal = (s == NULL ? 0 : atoi (s));
189 
190  if (reverse_traversal > 0)
191  {
192  l += (reverse_traversal + 4) * n_slash;
193  ret2 = g_malloc0 (l + 1);
194 
195  for (s = ret, s2 = ret2; *s != '\0' && *s != '?'; s++)
196  if (*s != '/')
197  *s2++ = *s;
198  else
199  {
200  *s2++ = '/';
201  for (i = reverse_traversal; i > 0; i--)
202  *s2++ = lrand48 () % 26 + 'a';
203  strncpy (s2, "/../", l);
204  s2 += 4;
205  }
206  while (*s != '\0')
207  *s2++ = *s++;
208  *s2 = '\0';
209  g_free (ret);
210  ret = ret2;
211  n_slash *= 3;
212 #ifdef URL_DEBUG
213  log_legacy_write ("Request = %s\n", ret);
214 #endif
215  }
216 
217  s = kb_item_get_str (kb, "NIDS/HTTP/premature_request_ending");
218  prem_req_end = (s != NULL && strcmp (s, "yes") == 0);
219  if (prem_req_end)
220  {
221  l += 36;
222  ret2 = g_malloc0 (l + 1);
223  n_slash += 4;
224 
225  s = gizmo;
226  *s++ = lrand48 () % 26 + 'A';
227  for (i = 1; i < 8; i++)
228  *s++ = lrand48 () % 26 + 'a';
229  *s++ = '\0';
230  snprintf (ret2, l, "/%%20HTTP/1.0%%0d%%0a%s:%%20/../..%s", gizmo, ret);
231  g_free (ret);
232  ret = ret2;
233 #ifdef URL_DEBUG
234  log_legacy_write ("Request = %s\n", ret);
235 #endif
236  }
237 
238  s = kb_item_get_str (kb, "NIDS/HTTP/param_hiding");
239  param_hiding = (s != NULL && strcmp (s, "yes") == 0);
240  if (param_hiding)
241  {
242  l += 25;
243  ret2 = g_malloc0 (l + 1);
244  n_slash += 2;
245 
246  s = gizmo;
247  for (i = 0; i < 8; i++)
248  *s++ = lrand48 () % 26 + 'a';
249  *s++ = '\0';
250  snprintf (ret2, l, "/index.htm%%3f%s=/..%s", gizmo, ret);
251  g_free (ret);
252  ret = ret2;
253 #ifdef URL_DEBUG
254  log_legacy_write ("Request = %s\n", ret);
255 #endif
256  }
257 
258  s = kb_item_get_str (kb, "NIDS/HTTP/double_slash");
259  double_slash = (s != NULL && strcmp (s, "yes") == 0);
260  if (double_slash)
261  {
262  l += n_slash;
263 
264  ret2 = g_malloc0 (l + 1);
265  for (s = ret, s2 = ret2; *s != '\0' && *s != '?'; s++)
266  if (*s != '/')
267  *s2++ = *s;
268  else
269  {
270  *s2++ = '/';
271  *s2++ = '/';
272  }
273  while (*s != '\0')
274  *s2++ = *s++;
275  *s2 = '\0';
276  g_free (ret);
277  ret = ret2;
278  n_slash *= 2;
279 #ifdef URL_DEBUG
280  log_legacy_write ("Request = %s\n", ret);
281 #endif
282  }
283 
284  s = kb_item_get_str (kb, "NIDS/HTTP/dos_win_syntax");
285  dos_win_syntax = (s != NULL && strcmp (s, "yes") == 0);
286  if (dos_win_syntax)
287  {
288  for (s = ret + 1; *s != '\0' && *s != '?'; s++)
289  if (*s == '/')
290  {
291  *s = '\\';
292  n_backslash++;
293  }
294 #ifdef URL_DEBUG
295  log_legacy_write ("Request = %s\n", ret);
296 #endif
297  }
298 
299  s = kb_item_get_str (kb, "NIDS/HTTP/URL_encoding");
300  url_encoding = URL_CODE_NONE;
301  if (s != NULL)
302  {
303  if (strcmp (s, "Hex") == 0)
304  url_encoding = URL_CODE_HEX;
305  else if (strcmp (s, "UTF-16 (double byte)") == 0)
306  url_encoding = URL_CODE_UTF16;
307  else if (strcmp (s, "UTF-16 (MS %u)") == 0)
308  url_encoding = URL_CODE_UTF16MS;
309  else if (strcmp (s, "Incorrect UTF-8") == 0)
310  url_encoding = URL_CODE_UTF8BAD;
311  }
312 
313 
314  switch (url_encoding)
315  {
316  case URL_CODE_UTF16:
317  case URL_CODE_UTF16MS:
318  case URL_CODE_UTF8BAD:
319  /* Let's try first without encoding [back]slashes */
320  l = (l - n_slash - n_backslash) * 6 + n_slash + n_backslash;
321  break;
322  case URL_CODE_HEX:
323  /* We do not encode slashes, as this does not work against Apache,
324  * at least apache-1.3.22-2 from redhat */
325  l = (l - n_slash) * 3 + n_slash;
326  break;
327  }
328 
329  if (url_encoding != URL_CODE_NONE)
330  {
331  ret2 = g_malloc0 (l + 1);
332 
333  for (s = ret, s2 = ret2; *s != '\0'; s++)
334  if (*s == '/'
335  ||
336  ((url_encoding == URL_CODE_UTF8BAD || url_encoding == URL_CODE_UTF16
337  || url_encoding == URL_CODE_UTF16MS) && *s == '\\'))
338  *s2++ = *s;
339  else if (s[0] == '%' && isxdigit (s[1]) && isxdigit (s[2]))
340  {
341  /* Already % encoded. Do not change it! */
342  *s2++ = *s++;
343  *s2++ = *s++;
344  *s2++ = *s;
345  }
346  else if (s[0] == '%' && tolower (s[1]) == 'u' && isxdigit (s[2])
347  && isxdigit (s[3]) && isxdigit (s[4]) && isxdigit (s[5]))
348  {
349  /* Already %u encoded. Do not change it! */
350  *s2++ = *s++;
351  *s2++ = *s++;
352  *s2++ = *s++;
353  *s2++ = *s++;
354  *s2++ = *s;
355  }
356  else if (url_encoding == URL_CODE_UTF16MS)
357  {
358  sprintf (s2, "%%u00%02x", *(unsigned char *) s);
359  /* The argument MUST be "unsigned char" */
360  s2 += 6;
361  }
362  else if (url_encoding == URL_CODE_UTF16)
363  {
364  sprintf (s2, "%%00%%%02x", *(unsigned char *) s);
365  /* The argument MUST be "unsigned char" */
366  s2 += 6;
367  }
368  else if (url_encoding == URL_CODE_UTF8BAD)
369  {
370  unsigned char c = *(unsigned char *) s;
371  sprintf (s2, "%%%02x%%%02x", 0xC0 | (c >> 6), 0x80 | (c & 0x3F));
372  s2 += 6;
373  /* Note: we could also use the raw unencoded characters */
374  }
375  else
376  {
377  sprintf (s2, "%%%02x", *(unsigned char *) s);
378  /* The argument MUST be "unsigned char", so that it stays between
379  * 0 and 255. Otherwise, we might get something like %FFFFFF42 */
380  s2 += 3;
381  if (*s == '\\')
382  n_backslash--;
383  }
384  *s2 = '\0';
385  g_free (ret);
386  ret = ret2;
387 #ifdef URL_DEBUG
388  log_legacy_write ("Request = %s\n", ret);
389 #endif
390  }
391 
392  abs_URI_type = kb_item_get_str (kb, "NIDS/HTTP/absolute_URI/type");
393  if (start_with_slash && abs_URI_type != NULL
394  && strcmp (abs_URI_type, "none") != 0)
395  {
396 #ifndef MAXHOSTNAMELEN
397 # define MAXHOSTNAMELEN 64
398 #endif
399  char h[MAXHOSTNAMELEN];
400 
401  abs_URI_host = kb_item_get_str (kb, "NIDS/HTTP/absolute_URI/host");
402  h[0] = '\0';
403  if (abs_URI_host != NULL)
404  {
405  if (strcmp (abs_URI_host, "host name") == 0)
406  {
407  if ((s = (char *) plug_get_hostname (data)) != NULL)
408  strncpy (h, s, sizeof (h));
409  h[sizeof (h) - 1] = '\0';
410  }
411  else if (strcmp (abs_URI_host, "host IP") == 0)
412  {
413  struct in6_addr *ptr;
414 
415  if ((ptr = plug_get_host_ip (data)) != NULL)
416  {
417  char *asc = addr6_as_str (ptr);
418  strncpy (h, asc, sizeof (h));
419  g_free (asc);
420  }
421  h[sizeof (h) - 1] = '\0';
422  }
423  else if (strcmp (abs_URI_host, "random name") == 0)
424  {
425  for (s2 = h, i = 0; i < 16; i++)
426  *s2++ = lrand48 () % 26 + 'a';
427  *s2++ = '\0';
428  }
429  else if (strcmp (abs_URI_host, "random IP") == 0)
430  sprintf (h, "%d.%d.%d.%d", rand () % 256, rand () % 256,
431  rand () % 256, rand () % 256);
432  }
433 
434  l += strlen (h) + strlen (abs_URI_type) + 3;
435  ret2 = g_malloc0 (l + 1);
436 
437  snprintf (ret2, l, "%s://%s%s", abs_URI_type, h, ret);
438  g_free (ret);
439  ret = ret2;
440 #ifdef URL_DEBUG
441  log_legacy_write ("Request = %s\n", ret);
442 #endif
443  }
444 
445 
446  s = kb_item_get_str (kb, "NIDS/HTTP/null_method");
447  null_method = (s != NULL && strcmp (s, "yes") == 0);
448  if (null_method)
449  {
450  l += 3;
451  ret2 = g_malloc0 (l + 1);
452  strncpy (ret2, "%00", l);
453  strncpy (ret2 + 3, ret, (l - 3));
454  g_free (ret);
455  ret = ret2;
456  }
457 
458  l += strlen (method) + 1;
459 
460  s = kb_item_get_str (kb, "NIDS/HTTP/http09");
461  http09 = (s != NULL && strcmp (s, "yes") == 0);
462  if (!http09)
463  {
464  s = kb_item_get_str (kb, "NIDS/HTTP/protocol_string");
465  if (s != NULL && *s != '\0')
466  httpver = s;
467  l += strlen (httpver) + 2;
468  }
469 
470 
471  s = kb_item_get_str (kb, "NIDS/HTTP/tab_separator");
472  tab_sep = (s != NULL && strcmp (s, "yes") == 0);
473  sep_c = (tab_sep ? '\t' : ' ');
474 
475  ret2 = g_malloc0 (l + 1);
476  if (http09)
477  snprintf (ret2, l, "%s%c%s", method, sep_c, ret);
478  else
479  snprintf (ret2, l, "%s%c%s%c%s", method, sep_c, ret, sep_c, httpver);
480  g_free (ret);
481  ret = ret2;
482 
483 #ifdef URL_DEBUG
484  log_legacy_write ("Request <= %s\n", ret);
485 #endif
486  return ret;
487 }
#define URL_CODE_NONE
#define URL_CODE_UTF16
void log_legacy_write(const char *format,...)
Legacy function to write a log message.
#define URL_CODE_HEX
kb_t plug_get_kb(struct arglist *args)
Definition: plugutils.c:710
#define MAXHOSTNAMELEN
Top-level KB. This is to be inherited by KB implementations.
Definition: kb.h:102
#define URL_CODE_UTF8BAD
char * addr6_as_str(const struct in6_addr *addr6)
struct in6_addr * plug_get_host_ip(struct arglist *desc)
Definition: plugutils.c:216
const char * name
Definition: nasl_init.c:524
const char * plug_get_hostname(struct arglist *desc)
Definition: plugutils.c:190
#define URL_CODE_UTF16MS

References log_legacy_write(), name, and plug_get_kb().

Here is the call graph for this function: