While using https://github.com/sewenew/redis-plus-plus as library for talking to redis, the following question came up.
How would you escape user send data, which should be saved as a value of e.g. a json object (in order to not allow redis command injection)?
json.set doc $ '{"key": "value"}'
The user could send:
val\"ue
as a new value for key.
I'm using the raw command for json.set in redis-plus-plus and had to pass it like this in order to get processed correctly by redis (value below would be the string val"ue):
m_pDb->jsonSet(key, "$.key", "\"" + value + "\"");
which calls this funtion:
void result(const std::vector<std::string>& cmd)
{
auto val = m_pRedis->command(cmd.cbegin(), cmd.cend());
ue could now be interpreted as further redis command.
If I'm not wrong the command would at the end be like this:
json.set doc $.key "val"ue"
The point is, it should not be possible to "escape" out of the value and cause an parser error or whatever.
Is value passed wrong? Is there some build in escaping?
Should every possible injection escaped by the developer?
Related
I'm trying to use a pre-request script to build out a request object based on data pulled from a CSV file. The problem is that the request seems to be set in stone prior to the pre-request script being run. That would seem to make this a mid-request script almost rather than a pre-request.
My code is as follows:
if(ipList === undefined) ipList = "1.2.3.4,2.3.4.5,123.234.345.465";
let ips = ipList.split(',');
let queryArray = [];
for( i=0; i<ips.length; i++){
queryArray.push({ "key": "ip", "value": ips[i] });
}
console.log(queryArray);
pm.request.url.query = queryArray;
console.log(pm.request);
When I hardcode a url query variable in the request to equal 4.3.2.1, the pm.response.url object like this:
pm.request.url.query[0] = {key:"ip", value:"4.3.2.1"}
Note that the url.query[0] part of the object matches the parameter in the actual get request.
When I change the value of pm.request.url.query to equal the new query array, however as you can see here, the query array is set correctly, but the parameters are not appended to the request URL.
So unless I'm doing something wrong, it appears that the request is immutable even to the pre-request scripts.
So my question is this:
Is there a way to modify the url params of a request prior to making the request?
BTW: I know that is might seem odd to have multiple params with the same key in a query, but that's the way this API works and hard coding multiple ip addresses in the query works just fine.
You could just assign a new value to pm.request.url.
Here I had some query params already in the URL, which I had to edit:
const urlSplit = request.url.split('?');
const paramsString = urlSplit[1]; // the second part actually represents the query string we need to modify
const eachParamArray = paramsString.split('&');
let params = {};
eachParamArray.forEach((param) => {
const key = param.split('=')[0];
const value = param.split('=')[1];
Object.assign(params, {[key]: value});
});
params.bla = params.bla + 'foobar';
newQueryString = Object.keys(params).map(key => key + '=' + params[key]).join('&');
pm.request.url = urlSplit[0] + '?' + newQueryString;
In the end, I just constructed a new URL, using the first part of the previous one & the query string with the edited bla parameter.
This seemed to work for me--it didn't change what the UI shows the query string is, but it changed what the actual request was (looking at the console log)
pm.request.url.addQueryParams(["a=1", "b=2"])
pm.request.url.query.remove("b")
I have some parameters called "script_loginAs" etc... named such that people on my team know the parameter is evaluated and not sent.
I am trying to retrieve an object out of my MongoDB instance. I am using the JsonCPP library.
Currently, what I am doing is:
system(("mongo --host " + host_name + " --port " + std::to_string(port) + " " + database_name + " --eval 'db." + collection_name + ".find({},{_id:0})' | tee -a return_from_db.json").c_str());
And parsing it later on using:
Json::Value json_object;
Json::Reader jsonreader.parse(ifstream_from_return_from_db_json, json_object, false);
As soon as I am not suppressing the _id field in my query, I'll get null values everywhere. The reason for this is as follows:
{
"_id": ObjectId("any_id")
}
The object ID is not in double quotes.
Now my question: How can I extract the ID of a document using the jsoncpp library? Can I change something in the settings of my MongoDB instance to get syntactically correct id key-value mappings?
I know, there is the MongoDB driver for CPP, but I cannot use it (for a couple of reasons...). Any help appreciated.
The MongoDB shell only looks like JSON. It provides a custom, extended form to preserve type information not available in pure JSON, so your approach won't work for any document projection that includes such types.
You can read more about it in the Extended JSON docs (see "Shell mode").
If you can't use a driver, you might want to explore a third party REST interface instead.
I have integrated oAuth2 (Facebook, LinkedIn, etc) with my XPages app to allow for authentication to easily add comments (response docs). When a user authenticates, it has to redirect to the facebook/linkedin page, then return to complete the document creation. I use the state variable to do this, and pass it in the querystring of the url. When the page reloads and sees the state variable, it calls a "beforePageLoad" event and creates the response document if the user authenticated and has the correct state document.
My problem is when there is already a state parameter in the querystring. I want to replace the value, not add it to the end. I use a solution here from stackOverflow by ellemayo called updateQueryStringParameter. When I call it from my beforePageLoads it runs, but never replaces the parameter, it only appends it to the end. I end up with ...&state=E5A&state=E5F
I have a feeling that it is in the line,
return uri.replace(re, '$1' + key + "=" + value + '$2');
I can write the code using #ReplaceSubstring(), etc, but want to know if there are problems running regex in XPages SSJS. I read on Lotus.com that
A Regular Expression can be specified as Server-side, which uses the
Java (java.util.regex) API or Client-side, which uses the browser
JavaScript Regular Expression Engine. Client-side and Server-side
Regular Expression syntax is similar, but there are differences that a
user must be aware of.
Should I avoid regex in XPages SSJS ? I have it working extensively in client and in some field validations on the XPage itself.
Here is the call to the function:
if(#Contains( qString,"state=")){
qString=updateQueryStringParameter(qString, "state", linkDoc.getNoteID() );
}else{
qString="?"+qString+"&state=" + linkDoc.getNoteID()
}
the function:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
// I also tried --> if (re.test(uri)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
It was not an XPage or Regex problem. I was using the querystring provided by Domino the excludes the "?" as part of the querystring. when I send "?" + qString to the function, it works. Regex needed to know where to start looking, thus it never found the start of the query string.
I'm a new User of POCO and could get HTTP response after HTTP::Request.
By the way, How do I create HTTP request with some parameters? For example, I want to set URI, http://xxxx/index.html?name=hoge&id=fuga&data=foo.
Of course I know it's possible if I set this uri directly. But I want to realize this like below. Does anyone know this way?
URI uri("http://xxx/index.html");
uri.setParam("name", "hoge");
uri.setParam("id", "fuga");
uri.setParam("data", "foo");
If you had looked up the documentation for Poco::URI, you'd see it's done with uri.addQueryParameter("name", "value"):
void addQueryParameter(
const std::string & param,
const std::string & val = ""
);
Adds "param=val" to the query; "param" may not be empty. If val is empty, only '=' is appended to the parameter.
In addition to regular encoding, function also encodes '&' and '=', if found in param or val.
You can also set all the parameters with setQueryParameters.
Unfortunately, Poco doesn't let you set the value of an existing query parameter (or remove it). If you want to do that, you have to clear the query portion of the URI and readd all the parameters you want with their values.
I need to come up with a program that generates an xml file like this:
<?xml version="1.0"?>
<xc:XmlCache xmlns:xc="XmlCache" xc:action="Update">
<xc:XmlCacheArea xc:target="AllSubFields" xc:value="MarketParameters">
<mp:nickName xmlns:mp="mx.MarketParameters" xc:value="MDS">
<mp:date xc:value="TODAY">
<fx:forex xmlns:fx="mx.MarketParameters.Forex">
<fxsp:spot xmlns:fxsp="mx.MarketParameters.Forex.Spot">
<fxsp:pair type="Fields" value="USD/BRL">
<mp:ask xc:type="Field" xc:keyFormat="N">1.890</mp:ask>
<mp:bid xc:type="Field" xc:keyFormat="N">1.800</mp:bid>
</fxsp:pair>
</fxsp:spot>
</fx:forex>
</mp:date>
</mp:nickName>
</xc:XmlCacheArea>
</xc:XmlCache>
with the values in the nodes mp:ask and mp:bid randomly generated but between two predefined values (1.65 and 1.99).
After the xml is generated in the same directory of the program, the program should run a command in the cmd command line that states:
cachetool.bat -i cacheBody.xml -u REALTIME
where cachetool.bat is an already done bash script that cannot be changed and that is also place in the same directory of the program, and where cacheBody.xml is that previously generated xml.
The trick here is that this should run repeatedly overwriting the xml file with new values each time and then running the command again calling the xml with the new values.
There should be a way to easy interrupt the loop, but besides that, this should run indefinitely.
Note: there isn't a strict rule to use c or c++, if it isn't feasible in these languages or if there other ways to do it easily, please feel free to suggest. My initial proposal is in these languages because these are the two that I'm a little used to deal with.
I'm learning how to use javascript for Windows local scripting, so here's a solution in javascript.
It looks like you don't really need to generate the XML dynamically, but rather the XML structure is static and only a couple data fields are dynamic. With that in mind, I approached the problem with search-and-replace using a template file.
The template file (template.xml) contains xml content with some variables to search and replace. The format variable format is $RANDOM_X_Y$, where X and Y are the lower and upper bounds for the random number. To help the example, I generated the ask and bid prices slightly differently in the template file:
<?xml version="1.0"?>
<xc:XmlCache xmlns:xc="XmlCache" xc:action="Update">
<xc:XmlCacheArea xc:target="AllSubFields" xc:value="MarketParameters">
<mp:nickName xmlns:mp="mx.MarketParameters" xc:value="MDS">
<mp:date xc:value="TODAY">
<fx:forex xmlns:fx="mx.MarketParameters.Forex">
<fxsp:spot xmlns:fxsp="mx.MarketParameters.Forex.Spot">
<fxsp:pair type="Fields" value="USD/BRL">
<mp:ask xc:type="Field" xc:keyFormat="N">1.$RANDOM_65_99$0</mp:ask>
<mp:bid xc:type="Field" xc:keyFormat="N">1.$RANDOM_650_990$</mp:bid>
</fxsp:pair>
</fxsp:spot>
</fx:forex>
</mp:date>
</mp:nickName>
</xc:XmlCacheArea>
</xc:XmlCache>
The javascript file is called replace.js. All versions of Windows should be able to execute it natively without installing any extra components.
if( WScript.Arguments.Count() != 2 || WScript.Arguments.Item(0) == WScript.Arguments.Item(1) )
{
WScript.Echo("Usage: replace.js <template> <output filename>");
WScript.Quit();
}
var template_filename = WScript.Arguments.Item(0);
var output_filename = WScript.Arguments.Item(1);
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ForReading = 1;
var file, file_contents, lower, upper;
var var_regex = /\$RANDOM_(\d+)_(\d+)\$/g;
if( fso.FileExists(template_filename) )
{
file = fso.OpenTextFile(template_filename, ForReading, false);
file_contents = file.ReadAll().replace(var_regex,
function(str, lower, upper) {
return Math.floor(
Math.random() * (+upper - +lower + 1)) + +lower;
});
file.Close();
file = fso.CreateTextFile(output_filename, true);
file.Write(file_contents);
file.Close();
}
else
{
WScript.Echo("Template does not exist: " + template_filename);
}
Now to run your scripts indefinitely, just create a batch file called run.bat or whatever and have it run the javascript and batch files in a loop. CTRL-C will exit the script.
#echo off
echo Starting. Press CTRL-C to exit.
:loop
replace.js template.xml cacheBody.xml
cachetool.bat -i cacheBody.xml -u REALTIME
goto loop
Well, to create the random value, you can use the rand() function, and just scale it so it's between the two values you want.
To call the command line, try system("cachetool.bat -i cacheBody.xml -u REALTIME");
And for the xml, if it's all the same except for the numbers, you can just hardcode it. If not, you'll need an xml library.