1

salut

j'ai un utilitaire qui dumpe une base de donnée redis
mon framework web utilise lui aussi redis et sauve le cache des pages dedans, une des première version sauvais en cache toutes les pages, même les 404

un cron sauve toute les nuit un dump de mes bases, et je viens de me rendre compte que ca ne dumpe plus depuis qq temps
je teste manuellement et la horreur, segfault trilove

après masse de debug, je me rend compte que des nom de clef chelou sont dans redis, un type avais du tester de hacker et ses tests sont restés dans le cache de la vieille version
une des clef depuis redis-cli :
redis 127.0.0.1:6379> keys "*?clone"
1) "fastIce:designCache:en:/../../../../../../../../../../../../../../../../../../../../../../../..//tmp/kulo\x0000?clone"

la même dans mon utilitaire de dump :
[mk@hightland rdd]$ rdd "*?clone"
fastIce:designCache:en:/../../../../../../../../../../../../../../../../../../../../../../../..//tmp/kulo Erreur de segmentation (core dumped)

cette ligne la fait le crash dans mon utilitaire
redisAppendCommand(rd,redisGetCmd[ktype[n]],keys->element[n]->str); // get data


pour faire simple mon util récupère une liste de clef matchant la requête, pour chaque clef ensuite il récupère le type de clef, puis ensuite les data

la clef récupéré ne contient pas le \x0000 ou alors ce que j’utilise ne marche pas avec, printf(" name %s\n",keys->element[n]->str); ne m'affiche pas le \x0000
et keys->element[n]->str est créé et remplis par le client C officiel

quant je demande le type de clef, j'envois un nom inexistant car sans le \x0000, ça me répond donc 255 (unknow)
et 255 est un peu trop pour
const char * const redisGetCmd[ 5] = { "GET %s", "LRANGE %s 0 -1", "SMEMBERS %s", "ZRANGE %s 0 -1 WITHSCORES", "HGETALL %s" };
qui provoque le crash

bref, à votre avis est ce un soucis de redis lui même, de son client C, ou de mon code ?
une idée de chose à faire pour y remédier ?

à noter que dans le binaire du client officiel,
redis 127.0.0.1:6379> hgetall "fastIce:designCache:en:/../../../../../../../../../../../../../../../../../../../../../../../..//tmp/kulo\x0000?clone"
fonctionne
et sans les quotes
redis 127.0.0.1:6379> hgetall fastIce:designCache:en:/../../../../../../../../../../../../../../../../../../../../../../../..//tmp/kulo\x0000?clone (empty list or set)
ca ne marche pas

je devrais plutôt poster ca sur la mailling list de redis je pense ^^
et la le mec il le pécho par le bras et il lui dit '

2

bon les noms de clef ont l'air "binary safe"
printf("key len : %u, strlen : %u\n",keys->element[n]->len,strlen(keys->element[n]->str));
=>
key len : 114, strlen : 105

char*name = keys->element[n]->str;redisAppendCommand(rd,"TYPE %s",name); // get key type
je vais tester de faire du memcpy au lieu d'utiliser le sprintf du C :- /
et la le mec il le pécho par le bras et il lui dit '

3

mmm hiredis utilise son propre parser de va list et sa propre lib de chaines de char, https://github.com/redis/hiredis/blob/master/hiredis.c#L686
char*name = keys->element[n]->str;
u32 len = keys->element[n]->len;
redisAppendCommand(rd,"TYPE %b",name,len); // get key typeredisAppendCommand(rd,"TTL %b",name,len); // get ttl
la ça marche ! :- )
et la le mec il le pécho par le bras et il lui dit '

4

pour info, il ne faut jamais faire printf(chaine) mais printf("%s",chaine)

idem pour toute la série des vasnprintf et consorts.

5

Pour compléter la réponse de squalyl, le bug de ton soft en C est simplement qu'il est injectable (donc on peut lui faire exécuter ce qu'on veut comme code, en mettant les bonnes clés dans la table reddis). Tout comme tu n'exécutes jamais une requête SQL qui contient des données utilisateur non nettoyées, il ne faut jamais utiliser une chaîne que tu ne maîtrises pas comme 1er argument de printf, puisque ce premier argument va déterminer combien doivent être lus ensuite (et comment ils doivent être lus), donnant un contrôle à peu près total à celui qui t'injecte la clé pour faire ce qu'il veut avec ton code.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

6

ben justement je fait toujours %s ou vous voyez l'inverse ? cheeky

c'est pas ma faute si c'est récursif sur les char spéciaux échappés

le vrai soucis c'est que je ne savais pas que les noms de clef pouvaient eux aussi être binary safe (les data des clefs le sont), ce détail n'est indiqué nulle part :/

un peu con pour mon outils je vais devoir tout revoir pour sauver la taille des noms de clef aussi, et donc repenser aussi le format de fichier que j'ai créé pour :/
et la le mec il le pécho par le bras et il lui dit '

7

c'est bien que les clés de test aient fait apparaitre le problème, sinon tu l'aurais jamais su, en laissant passer des trous de gruyère dans la sauce smile

8

robinHood (./6) :
c'est pas ma faute si c'est récursif sur les char spéciaux échappés

Ça ne l'est pas, justement.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

9

ce n'est justement pas des clef de test chapo

#point-r043v# trilove

mais en fait le vrai réel soucis du cron de save n’étais pas ca, je dumpe la base de 2 manières différentes
le véritable blème est qu'online ai subitement décidé qu'il fallait se connecter dorénavant sur les ftp de save en mode passif, le mode actif se faisant refouler, et ce sans rien dire à personne -______-

pour la peine je leur met aussi un #point-r043v#

> Ça ne l'est pas, justement.
ben visiblement si, enfin pas vraiment récursif mais ça doit faire une passe finale histoire de remplacer tout ce qui est échappé juste avant de rendre la main et non juste sur le pattern de départ
et la le mec il le pécho par le bras et il lui dit '

10

tout ca me tracasse, j'aime avoir le contrôle et ici, un bout de code me transforme à la volée mon \ en ce qui lui "chante"

bordel, même strlen
pour moi strlen c'est simplement
char *p = ptr; while(*p++); return (p-ptr)-1;
qu'est ce qu'une vérif d'un char hexa viens foutre la dedans ?
et la le mec il le pécho par le bras et il lui dit '

11

Mais il ne le fait pas (bis), essaie dans un bout de code à part, aussi bien printf que strlen ou quoi que ce soit d'autres ne touchent absolument pas aux séquences d'échappement.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

12

lu en survolant mais... ya 2 octets a 0 dans ta chaine quoi... et c'est sans doute ce qui est utilise pour l'afficher qui convertit ces octets a 0 en "\x0000"

en gros la string est pas "juste" null-terminated. il faut prendre en compte le 'len' pour l'afficher, vu qu'apparemment il peut y avoir des 0 et valeurs quelconques qui ne sont pas des caracteres affichables en plein milieu.
fais une boucle de 0 a len en affichant chaque caractere un a un avec %c et tu verra sans doute ta chaine complete et ses octets a 0 au milieu

et c'est _certainement pas_ printf qui re-escape ses arguments en "%s" et encore moins strlen... strlen trouve juste un null-character donc il s'arrete tout betement.
avatar
HURRRR !

13

oui c'est bien le cas

c'est le programme qui à écrit dans la base qui est lui injectable, voir même directement php :- /

pour l'instant mon code qui dumpe la base évince simplement ces chaînes ou la taille ne correspond pas à "len", à voir si plus tard je rend les noms de clef binarie safe ou non
et la le mec il le pécho par le bras et il lui dit '