Author: Chris Lamb --- redis-2.4.14.orig/src/redis.c +++ redis-2.4.14/src/redis.c @@ -192,6 +192,8 @@ struct redisCommand readonlyCommandTable {"unwatch",unwatchCommand,1,0,NULL,0,0,0}, {"object",objectCommand,-2,0,NULL,0,0,0}, {"client",clientCommand,-2,0,NULL,0,0,0}, + {"post",securityWarningCommand,-1,0,NULL,0,0,0}, + {"host:",securityWarningCommand,-1,0,NULL,0,0,0}, {"slowlog",slowlogCommand,-2,0,NULL,0,0,0} }; @@ -1229,6 +1231,27 @@ void echoCommand(redisClient *c) { addReplyBulk(c,c->argv[1]); } +/* This callback is bound to POST and "Host:" command names. Those are not + * really commands, but are used in security attacks in order to talk to + * Redis instances via HTTP, with a technique called "cross protocol scripting" + * which exploits the fact that services like Redis will discard invalid + * HTTP headers and will process what follows. + * + * As a protection against this attack, Redis will terminate the connection + * when a POST or "Host:" header is seen, and will log the event from + * time to time (to avoid creating a DOS as a result of too many logs). */ +void securityWarningCommand(redisClient *c) { + static time_t logged_time; + time_t now = time(NULL); + + if (labs(now-logged_time) > 60) { + redisLog(REDIS_WARNING,"Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted."); + logged_time = now; + } + c->flags |= REDIS_CLOSE_AFTER_REPLY; + addReply(c,createStringObject("",0)); +} + /* Convert an amount of bytes into a human readable string in the form * of 100B, 2G, 100M, 4K, and so forth. */ void bytesToHuman(char *s, unsigned long long n) { --- redis-2.4.14.orig/src/redis.h +++ redis-2.4.14/src/redis.h @@ -955,6 +955,7 @@ char *redisGitDirty(void); void authCommand(redisClient *c); void pingCommand(redisClient *c); void echoCommand(redisClient *c); +void securityWarningCommand(redisClient *c); void setCommand(redisClient *c); void setnxCommand(redisClient *c); void setexCommand(redisClient *c);