Details
Description
If a request for the topkeys stat is made when a bucket hasn't been selected, memcached crashes when trying to access the (non-existent) TopKeys struct.
Steps to reproduce
There are different methods needed, depending on version and if a default bucket exists.
Pre-Spock
Requires that either the default bucket does not exist, or the default bucket exists without a password. Issue a request for the topkeys stats, without specifying any credentials:
/opt/couchbase/bin/cbstats localhost:11210 raw topkeys
|
Spock
Issue a request for the topkeys stats, without specifying any bucket:
mcstat -h localhost:11210 -u Administrator -P asdasd topkeys
|
In both instances the memcached process will terminate (and be restarted by babysitter) - this can be verified by running pgrep memcached before and after and nothing the pid changes.
Impact
Pre-Spock: Any user who can connect to the cluster can trigger this crash.
Spock: Any user with the "SimpleStats" privilege who authenticates successfully can trigger this crash. Note that SimpleStats is granted to all user roles from "Data Monitor" upwards - in other words, pretty much any user who has at least read access to any bucket on the cluster could crash memcached.
It doesn't appear possible to exploit this bug to perform privilege escalation or similar - the crash due to dereferencing a null (and always null) pointer - which will trigger a segfault and cause memcached to restart.
Mitigation
Pre-Spock: Create a default bucket with no password and of memcache type (minimal 64MB quota). This will prevent this issue from occurring - when a user connects they will automatically be associated with that bucket (and a valid set of topkeys). This does allow anyone with network access to read/write to a caching bucket (and use cluster resources); however that is arguably better than crashing memcached.
Details
memcached attempts to dereference null pointer if the user isn't connected to a specific bucket (and it still in associated with the meta "empty" bucket):
* frame #5: 0x000000010a5ff99b memcached` TopKeys::stats(this=0x0000000000000000, cookie=0x0000000110077758, current_time=58, add_stat=<cut>) + 155 at topkeys.cc:254
|
frame #6: 0x000000010a5854d4 memcached` stat_topkeys_executor(arg="", connection=0x0000000110077400) + 324 at stats_context.cc:641
|
frame #7: 0x000000010a583c5d memcached` StatsCommandContext::step(this=0x000000010c2dc460) + 9213 at stats_context.cc:883
|
frame #8: 0x000000010a591377 memcached` SteppableCommandContext::drive(this=0x000000010c2dc460) + 135 at steppable_command_context.cc:33
|
frame #9: 0x000000010a517fc1 memcached` stat_executor(c=0x0000000110077400, packet=0x000000011007e800) + 49 at mcbp_executors.cc:797
|
frame #10: 0x000000010a51a2a6 memcached` execute_request_packet(c=0x0000000110077400) + 1078 at mcbp_executors.cc:1357
|
frame #11: 0x000000010a519da9 memcached` mcbp_complete_packet(c=0x0000000110077400) + 57 at mcbp_executors.cc:1470
|
frame #12: 0x000000010a5d9629 memcached` conn_execute(c=0x0000000110077400) + 905 at statemachine_mcbp.cc:306
|
frame #13: 0x000000010a4d0fdd memcached` McbpStateMachine::execute(this=0x000000010c2160c0, connection=0x0000000110077400) + 29 at statemachine_mcbp.h:43
|