Abuse Curl to Communicate with Redis

Abuse cURL to communicate with Redis

When you want to use curl, you need REST over RESP, like webdis, tinywebdis or turbowebdis. See https://github.com/markuman/tinywebdis#turbowebdis-tinywebdis--cherrywebdis

$ curl -w '\n' http://127.0.0.1:8888/ping
{"ping":"PONG"}

Without a REST interface for redis, you can use netcat for example.

$ (printf "PING\r\n";) | nc <redis-host> 6379 
+PONG

For password protected redis you can use netcat like this:

$ (printf "AUTH <password>\r\n";) | nc <redis-host> 6379
+PONG

With netcat you have to build the RESP protocol by your self. See http://redis.io/topics/protocol

update 2018-01-09

I've build a powerfull bash function which pings the redis instance at any cost over tcp

    function redis-ping() {
# ping a redis server at any cost
redis-cli -h $1 ping 2>/dev/null || \
echo $((printf "PING\r\n";) | nc $1 6379 2>/dev/null || \
exec 3<>/dev/tcp/$1/6379 && echo -e "PING\r\n" >&3 && head -c 7 <&3)
}

usage redis-ping localhost

How can I ping a password protected Redis server using netcat in an initContainer?

You could always send in your AUTH command as part of your probe, like:

`"AUTH ....\r\nPING\r\n"`

Unless you're getting INFO from the server, you don't seem to care about the nature of the response, so no auth is required, just test for NOAUTH.

Redis script for memory flush

I would use a Lua script as it will perform faster, atomically, and it would be easy to use both from redis-cli and any application code.

Here a Lua script to get memory used and maxmemory, the percent, and an action placeholder. It uses both MEMORY STATS and INFO memory to illustrate.

MEMORY STATS brings structured information, but doesn't include maxmemory or total_system_memory, as INFO memory does. CONFIG GET is not allowed from Lua scripts.

local stats = redis.call('MEMORY', 'STATS')
local memused = 0
for i = 1,table.getn(stats),2 do
if stats[i] == 'total.allocated' then
memused = stats[i+1]
break
end
end
local meminfo = redis.call('INFO', 'memory')
local maxmemory = 0
for s in meminfo:gmatch('[^\\r\\n]+') do
if string.sub(s,1,10) == 'maxmemory:' then
maxmemory = tonumber(string.sub(s,11))
end
end
local mempercent = memused/maxmemory
local action = 'No action'
if mempercent > tonumber(ARGV[1]) then
action = 'Flush here'
end
return {memused, maxmemory, tostring(mempercent), action}

Use as:

> EVAL "local stats = redis.call('MEMORY', 'STATS') \n local memused = 0 \n for i = 1,table.getn(stats),2 do \n     if stats[i] == 'total.allocated' then \n     memused = stats[i+1] \n break \n end \n end \n local meminfo = redis.call('INFO', 'memory') \n local maxmemory = 0 \n for s in meminfo:gmatch('[^\\r\\n]+') do \n     if string.sub(s,1,10) == 'maxmemory:' then \n     maxmemory = tonumber(string.sub(s,11)) \n end \n end \n local mempercent = memused/maxmemory \n local action = 'No action' \n if mempercent > tonumber(ARGV[1]) then \n     action = 'Flush here' \n end \n return {memused, maxmemory, tostring(mempercent), action}" 0 0.9
1) (integer) 860264
2) (integer) 100000000
3) "0.00860264"
4) "No action"

How do I delete everything in Redis?

With redis-cli:

  • FLUSHDB – Deletes all keys from the connection's current database.
  • FLUSHALL – Deletes all keys from all databases.

For example, in your shell:

redis-cli flushall

Finding Redis data by last update

Keep another key with the data about employees (key names) and the update's timestamp - the best candidate for that is a Sorted Set. To maintain that key's data integrity, you'll have update it with pertinent changes whenever you update one the employees' keys.

With that data structure in place, you can easily get the keys names of the recently-updated employees with the ZRANGE command.

Filtering the Windows message queue

You can use the range parameters in PeekMessage to restrict to the WM_CHAR message only, and PM_NOREMOVE to leave the message queue intact if the character isn't ESC; if the message needs to be removed, repeat the process with the PM_REMOVE flag. Unfortunately there's no way to look past the first WM_CHAR in the queue.

current directory notation not working


Writing "./constants.inc.php" gives this error, but "constants.inc.php" doesn't (PHP seems to find the file just fine). Can someone tell me why the ./ notation doesn't work in this particular case? Perhaps it's something very simple I'm missing?

The only explanation I have is that PHP seems to be finding the constants.inc.php file in one of the directories in the include path - most likely C:\xampp\htdocs\websites\mathverse\includes.

Loading a large dictionary using python pickle

Try the protocol argument when using cPickle.dump/cPickle.dumps. From cPickle.Pickler.__doc__:

Pickler(file, protocol=0) -- Create a pickler.

This takes a file-like object for writing a pickle data stream.
The optional proto argument tells the pickler to use the given
protocol; supported protocols are 0, 1, 2. The default
protocol is 0, to be backwards compatible. (Protocol 0 is the
only protocol that can be written to a file opened in text
mode and read back successfully. When using a protocol higher
than 0, make sure the file is opened in binary mode, both when
pickling and unpickling.)

Protocol 1 is more efficient than protocol 0; protocol 2 is
more efficient than protocol 1.

Specifying a negative protocol version selects the highest
protocol version supported. The higher the protocol used, the
more recent the version of Python needed to read the pickle
produced.

The file parameter must have a write() method that accepts a single
string argument. It can thus be an open file object, a StringIO
object, or any other custom object that meets this interface.

Converting JSON or YAML will probably take longer than pickling most of the time - pickle stores native Python types.

How to implement a secure REST API with node.js

I've had the same problem you describe. The web site I'm building can be accessed from a mobile phone and from the browser so I need an api to allow users to signup, login and do some specific tasks. Furthermore, I need to support scalability, the same code running on different processes/machines.

Because users can CREATE resources (aka POST/PUT actions) you need to secure your api. You can use oauth or you can build your own solution but keep in mind that all the solutions can be broken if the password it's really easy to discover. The basic idea is to authenticate users using the username, password and a token, aka the apitoken. This apitoken can be generated using node-uuid and the password can be hashed using pbkdf2

Then, you need to save the session somewhere. If you save it in memory in a plain object, if you kill the server and reboot it again the session will be destroyed. Also, this is not scalable. If you use haproxy to load balance between machines or if you simply use workers, this session state will be stored in a single process so if the same user is redirected to another process/machine it will need to authenticate again. Therefore you need to store the session in a common place. This is typically done using redis.

When the user is authenticated (username+password+apitoken) generate another token for the session, aka accesstoken. Again, with node-uuid. Send to the user the accesstoken and the userid. The userid (key) and the accesstoken (value) are stored in redis with and expire time, e.g. 1h.

Now, every time the user does any operation using the rest api it will need to send the userid and the accesstoken.

If you allow the users to signup using the rest api, you'll need to create an admin account with an admin apitoken and store them in the mobile app (encrypt username+password+apitoken) because new users won't have an apitoken when they sign up.

The web also uses this api but you don't need to use apitokens. You can use express with a redis store or use the same technique described above but bypassing the apitoken check and returning to the user the userid+accesstoken in a cookie.

If you have private areas compare the username with the allowed users when they authenticate. You can also apply roles to the users.

Summary:

sequence diagram

An alternative without apitoken would be to use HTTPS and to send the username and password in the Authorization header and cache the username in redis.



Related Topics



Leave a reply



Submit