mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-15 23:55:03 +03:00
Adds support to the transformation normalisePathWin
This commit is contained in:
parent
1353403c93
commit
62d004cf04
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include "actions/transformations/normalise_path_win.h"
|
#include "actions/transformations/normalise_path_win.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -24,26 +26,28 @@
|
|||||||
|
|
||||||
#include "modsecurity/assay.h"
|
#include "modsecurity/assay.h"
|
||||||
#include "actions/transformations/transformation.h"
|
#include "actions/transformations/transformation.h"
|
||||||
|
#include "src/utils.h"
|
||||||
|
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
namespace actions {
|
namespace actions {
|
||||||
namespace transformations {
|
namespace transformations {
|
||||||
|
|
||||||
NormalisePathWin::NormalisePathWin(std::string action)
|
|
||||||
: Transformation(action) {
|
|
||||||
this->action_kind = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NormalisePathWin::evaluate(std::string value,
|
std::string NormalisePathWin::evaluate(std::string value,
|
||||||
Assay *assay) {
|
Assay *assay) {
|
||||||
/**
|
int changed;
|
||||||
* @todo Implement the transformation NormalisePathWin
|
char *tmp = strdup(value.c_str());
|
||||||
*/
|
int res = normalize_path_inplace((unsigned char *)tmp,
|
||||||
assay->debug(4, "Transformation NormalisePathWin is not implemented yet.");
|
value.size(), 1, &changed);
|
||||||
return value;
|
std::string ret("");
|
||||||
|
ret.assign(tmp);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace transformations
|
} // namespace transformations
|
||||||
} // namespace actions
|
} // namespace actions
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
#ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
||||||
#define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
#define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
class Assay;
|
class Assay;
|
||||||
|
|
||||||
@ -30,7 +30,9 @@ namespace transformations {
|
|||||||
|
|
||||||
class NormalisePathWin : public Transformation {
|
class NormalisePathWin : public Transformation {
|
||||||
public:
|
public:
|
||||||
explicit NormalisePathWin(std::string action);
|
explicit NormalisePathWin(std::string action)
|
||||||
|
: Transformation(action) { }
|
||||||
|
|
||||||
std::string evaluate(std::string exp,
|
std::string evaluate(std::string exp,
|
||||||
Assay *assay) override;
|
Assay *assay) override;
|
||||||
};
|
};
|
||||||
@ -39,6 +41,5 @@ class NormalisePathWin : public Transformation {
|
|||||||
} // namespace actions
|
} // namespace actions
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
#endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_
|
||||||
|
@ -88,7 +88,7 @@ Transformation* Transformation::instantiate(std::string a) {
|
|||||||
IF_MATCH(md5) { return new Md5(a); }
|
IF_MATCH(md5) { return new Md5(a); }
|
||||||
IF_MATCH(none) { return new None(a); }
|
IF_MATCH(none) { return new None(a); }
|
||||||
IF_MATCH(normalise_path) { return new NormalisePath(a); }
|
IF_MATCH(normalise_path) { return new NormalisePath(a); }
|
||||||
IF_MATCH(normalise_path_win) { return new NormalisePathWin(a); }
|
IF_MATCH(normalisePathWin) { return new NormalisePathWin(a); }
|
||||||
IF_MATCH(parity_even_7bit) { return new ParityEven7bit(a); }
|
IF_MATCH(parity_even_7bit) { return new ParityEven7bit(a); }
|
||||||
IF_MATCH(parity_odd_7bit) { return new ParityOdd7bit(a); }
|
IF_MATCH(parity_odd_7bit) { return new ParityOdd7bit(a); }
|
||||||
IF_MATCH(parity_zero_7bit) { return new ParityZero7bit(a); }
|
IF_MATCH(parity_zero_7bit) { return new ParityZero7bit(a); }
|
||||||
|
167
src/utils.cc
167
src/utils.cc
@ -619,6 +619,173 @@ HTML_ENT_OUT:
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* IMP1 Assumes NUL-terminated
|
||||||
|
*/
|
||||||
|
int normalize_path_inplace(unsigned char *input, int input_len,
|
||||||
|
int win, int *changed) {
|
||||||
|
unsigned char *src;
|
||||||
|
unsigned char *dst;
|
||||||
|
unsigned char *end;
|
||||||
|
int ldst = 0;
|
||||||
|
int hitroot = 0;
|
||||||
|
int done = 0;
|
||||||
|
int relative;
|
||||||
|
int trailing;
|
||||||
|
|
||||||
|
*changed = 0;
|
||||||
|
|
||||||
|
/* Need at least one byte to normalize */
|
||||||
|
if (input_len <= 0) return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ENH: Deal with UNC and drive letters?
|
||||||
|
*/
|
||||||
|
|
||||||
|
src = dst = input;
|
||||||
|
end = input + (input_len - 1);
|
||||||
|
ldst = 1;
|
||||||
|
|
||||||
|
relative = ((*input == '/') || (win && (*input == '\\'))) ? 0 : 1;
|
||||||
|
trailing = ((*end == '/') || (win && (*end == '\\'))) ? 1 : 0;
|
||||||
|
|
||||||
|
|
||||||
|
while (!done && (src <= end) && (dst <= end)) {
|
||||||
|
/* Convert backslash to forward slash on Windows only. */
|
||||||
|
if (win) {
|
||||||
|
if (*src == '\\') {
|
||||||
|
*src = '/';
|
||||||
|
*changed = 1;
|
||||||
|
}
|
||||||
|
if ((src < end) && (*(src + 1) == '\\')) {
|
||||||
|
*(src + 1) = '/';
|
||||||
|
*changed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always normalize at the end of the input. */
|
||||||
|
if (src == end) {
|
||||||
|
done = 1;
|
||||||
|
} else if (*(src + 1) != '/') {
|
||||||
|
/* Skip normalization if this is NOT the
|
||||||
|
*end of the path segment. */
|
||||||
|
goto copy; /* Skip normalization. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Normalize the path segment. ***/
|
||||||
|
|
||||||
|
/* Could it be an empty path segment? */
|
||||||
|
if ((src != end) && *src == '/') {
|
||||||
|
/* Ignore */
|
||||||
|
*changed = 1;
|
||||||
|
goto copy; /* Copy will take care of this. */
|
||||||
|
} else if (*src == '.') {
|
||||||
|
/* Could it be a back or self reference? */
|
||||||
|
/* Back-reference? */
|
||||||
|
if ((dst > input) && (*(dst - 1) == '.')) {
|
||||||
|
/* If a relative path and either our normalization has
|
||||||
|
* already hit the rootdir, or this is a backref with no
|
||||||
|
* previous path segment, then mark that the rootdir was hit
|
||||||
|
* and just copy the backref as no normilization is possible.
|
||||||
|
*/
|
||||||
|
if (relative && (hitroot || ((dst - 2) <= input))) {
|
||||||
|
hitroot = 1;
|
||||||
|
|
||||||
|
goto copy; /* Skip normalization. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove backreference and the previous path segment. */
|
||||||
|
dst -= 3;
|
||||||
|
while ((dst > input) && (*dst != '/')) {
|
||||||
|
dst--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* But do not allow going above rootdir. */
|
||||||
|
if (dst <= input) {
|
||||||
|
hitroot = 1;
|
||||||
|
dst = input;
|
||||||
|
|
||||||
|
/* Need to leave the root slash if this
|
||||||
|
* is not a relative path and the end was reached
|
||||||
|
* on a backreference.
|
||||||
|
*/
|
||||||
|
if (!relative && (src == end)) {
|
||||||
|
dst++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) goto length; /* Skip the copy. */
|
||||||
|
src++;
|
||||||
|
|
||||||
|
*changed = 1;
|
||||||
|
} else if (dst == input) {
|
||||||
|
/* Relative Self-reference? */
|
||||||
|
*changed = 1;
|
||||||
|
|
||||||
|
/* Ignore. */
|
||||||
|
|
||||||
|
if (done) goto length; /* Skip the copy. */
|
||||||
|
src++;
|
||||||
|
} else if (*(dst - 1) == '/') {
|
||||||
|
/* Self-reference? */
|
||||||
|
*changed = 1;
|
||||||
|
|
||||||
|
/* Ignore. */
|
||||||
|
|
||||||
|
if (done) goto length; /* Skip the copy. */
|
||||||
|
dst--;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
} else if (dst > input) {
|
||||||
|
/* Found a regular path segment. */
|
||||||
|
hitroot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy:
|
||||||
|
/*** Copy the byte if required. ***/
|
||||||
|
|
||||||
|
/* Skip to the last forward slash when multiple are used. */
|
||||||
|
if (*src == '/') {
|
||||||
|
unsigned char *oldsrc = src;
|
||||||
|
|
||||||
|
while ((src < end)
|
||||||
|
&& ((*(src + 1) == '/') || (win && (*(src + 1) == '\\'))) ) {
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
if (oldsrc != src) *changed = 1;
|
||||||
|
|
||||||
|
/* Do not copy the forward slash to the root
|
||||||
|
* if it is not a relative path. Instead
|
||||||
|
* move over the slash to the next segment.
|
||||||
|
*/
|
||||||
|
if (relative && (dst == input)) {
|
||||||
|
src++;
|
||||||
|
goto length; /* Skip the copy */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*(dst++) = *(src++);
|
||||||
|
|
||||||
|
length:
|
||||||
|
ldst = (dst - input);
|
||||||
|
}
|
||||||
|
/* Make sure that there is not a trailing slash in the
|
||||||
|
* normalized form if there was not one in the original form.
|
||||||
|
*/
|
||||||
|
if (!trailing && (dst > input) && *(dst - 1) == '/') {
|
||||||
|
ldst--;
|
||||||
|
dst--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always NUL terminate */
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
return ldst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a single hexadecimal digit into a decimal value.
|
* Converts a single hexadecimal digit into a decimal value.
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,8 @@ namespace ModSecurity {
|
|||||||
int css_decode_inplace(unsigned char *input, int64_t input_len);
|
int css_decode_inplace(unsigned char *input, int64_t input_len);
|
||||||
static unsigned char xsingle2c(unsigned char *what);
|
static unsigned char xsingle2c(unsigned char *what);
|
||||||
int html_entities_decode_inplace(unsigned char *input, int input_len);
|
int html_entities_decode_inplace(unsigned char *input, int input_len);
|
||||||
|
int normalize_path_inplace(unsigned char *input, int input_len,
|
||||||
|
int win, int *changed);
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
|
||||||
#define SRC_UTILS_H_
|
#define SRC_UTILS_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user