Skip to content

Instantly share code, notes, and snippets.

@airween
Last active November 4, 2019 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save airween/efb8a737193910b5ae893d93e0325902 to your computer and use it in GitHub Desktop.
Save airween/efb8a737193910b5ae893d93e0325902 to your computer and use it in GitHub Desktop.
Cookie parse method for ModSecurity3
/*
* cookie parsing algorithms for ModSecurity3
*
* g++ -O0 -g cookieparse.cpp -o cookieparse
*
* ./cookieparse " key1= foo ; key2=bar=apple; key3 = peach,orange; key 4 = banane ; key5"
*/
#include <iostream>
#include <vector>
#include <sstream>
// copied from src/utils/string.cc
std::vector<std::string> ssplit(std::string str, char delimiter) {
std::vector<std::string> internal;
std::stringstream ss(str); // Turn the string into a stream.
std::string tok;
ssize_t n = str.length();
int i = 0;
while (getline(ss, tok, delimiter)) {
n -= tok.length();
if (i > 0) n--;
internal.push_back(n == 1 ? tok + delimiter : tok);
i++;
}
return internal;
}
// copied from src/utils/string.cc
std::vector<std::string> split(std::string str, char delimiter) {
std::vector<std::string> internal = ssplit(str, delimiter);
if (internal.size() == 0) {
internal.push_back(str);
}
return internal;
}
// new method, setting of variable just marked
int method_new(std::string &value) {
std::string value2 = value;
size_t localOffset = 0;
size_t pos1, pos2;
for(pos1 = 0; pos1 < value.length(); pos1++) {
value2[pos1] = ' ';
}
std::vector<std::string> cookies = ssplit(value, ';');
for (const std::string &c : cookies) {
pos1 = c.find_first_of("=", 0);
std::string ckey = "";
std::string cval = "";
if (pos1 == std::string::npos) {
ckey = c;
}
else {
ckey = c.substr(0, pos1);
cval = c.substr(pos1+1, c.length());
}
// remove leading spaces
while (ckey.length() > 0 && ckey.at(0) == ' ') {
ckey.erase(0, 1);
localOffset++;
}
// replace remained spaces with underscore
// eg " foo bar = foobar" -> "foo_bar= foobar"
pos2 = 0;
while(ckey.length() > 0 && pos2 < ckey.length()) {
if (ckey.at(pos2) == ' ') {
ckey.replace(pos2, 1, "_");
}
pos2++;
}
// set cookie name, localOffset...
value2[localOffset] = '^';
localOffset = localOffset + ckey.length() + 1;
// if cval != '' set cookie value, localOffset...
if (cval != "") {
value2[localOffset] = '^';
localOffset = localOffset + cval.length() + 1;
}
}
std::cout << value << "\n";
std::cout << value2 << "\n";
return 0;
}
// original method, setting of variable commented out
int method_orig(std::string &value) {
size_t localOffset = 0;
std::string value2 = value;
size_t pos1;
for(pos1 = 0; pos1 < value.length(); pos1++) {
value2[pos1] = ' ';
}
std::vector<std::string> cookies = ssplit(value, ';');
for (const std::string &c : cookies) {
std::vector<std::string> s = split(c,
'=');
if (s.size() > 1) {
if (s[0].at(0) == ' ') {
s[0].erase(0, 1);
}
//m_variableRequestCookiesNames.set(s[0],
// s[0], localOffset);
value2[localOffset] = '^';
localOffset = localOffset + s[0].size() + 1;
//m_variableRequestCookies.set(s[0], s[1], localOffset);
value2[localOffset] = '^';
localOffset = localOffset + s[1].size() + 2;
}
}
std::cout << value << "\n";
std::cout << value2 << "\n";
return 0;
}
int main(int argc, char* argv[]) {
std::string value = "";
if (argc > 1) {
value = argv[1];
}
else {
value = " key1= foo ; key2=bar=apple; key3 = peach,orange; key 4 = banane ; key5";
}
method_orig(value);
std::cout << "======\n";
method_new(value);
return 0;
}
g++ -O0 -g cookieparse.cpp -o cookieparse
./cookieparse " key1= foo ; key2=bar=apple; key3 = peach,orange; key 4 = banane ; key5"
key1= foo ; key2=bar=apple; key3 = peach,orange; key 4 = banane ; key5
^ ^ ^ ^ ^ ^ ^ ^
======
key1= foo ; key2=bar=apple; key3 = peach,orange; key 4 = banane ; key5
^ ^ ^ ^ ^ ^ ^ ^ ^
the markers shows how catch the algorithms the keys and values. In case of current method, the extremist format of a cookie string, like in the example the keys and values are confused. But with the new version, all interpreted as well (I think - I compared them with Apache (PHP) and Python Bottle).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment