comparison src/http/ngx_http_file_cache.c @ 6243:4821fc788c12

Cache: check the whole cache key in addition to hashes. This prevents a potential attack that discloses cached data if an attacker will be able to craft a hash collision between some cache key the attacker is allowed to access and another cache key with protected data. See http://mailman.nginx.org/pipermail/nginx-devel/2015-September/007288.html. Thanks to Gena Makhomed and Sergey Brester.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 11 Sep 2015 17:03:56 +0300
parents d698c300b9ff
children 9fd738b85fad
comparison
equal deleted inserted replaced
6242:0e3a45ec2a3a 6243:4821fc788c12
519 519
520 520
521 static ngx_int_t 521 static ngx_int_t
522 ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) 522 ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
523 { 523 {
524 u_char *p;
524 time_t now; 525 time_t now;
525 ssize_t n; 526 ssize_t n;
527 ngx_str_t *key;
526 ngx_int_t rc; 528 ngx_int_t rc;
529 ngx_uint_t i;
527 ngx_http_file_cache_t *cache; 530 ngx_http_file_cache_t *cache;
528 ngx_http_file_cache_header_t *h; 531 ngx_http_file_cache_header_t *h;
529 532
530 n = ngx_http_file_cache_aio_read(r, c); 533 n = ngx_http_file_cache_aio_read(r, c);
531 534
545 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 548 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
546 "cache file \"%s\" version mismatch", c->file.name.data); 549 "cache file \"%s\" version mismatch", c->file.name.data);
547 return NGX_DECLINED; 550 return NGX_DECLINED;
548 } 551 }
549 552
550 if (h->crc32 != c->crc32) { 553 if (h->crc32 != c->crc32 || h->header_start != c->header_start) {
551 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, 554 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
552 "cache file \"%s\" has md5 collision", c->file.name.data); 555 "cache file \"%s\" has md5 collision", c->file.name.data);
553 return NGX_DECLINED; 556 return NGX_DECLINED;
557 }
558
559 p = c->buf->pos + sizeof(ngx_http_file_cache_header_t)
560 + sizeof(ngx_http_file_cache_key);
561
562 key = c->keys.elts;
563 for (i = 0; i < c->keys.nelts; i++) {
564 if (ngx_memcmp(p, key[i].data, key[i].len) != 0) {
565 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
566 "cache file \"%s\" has md5 collision",
567 c->file.name.data);
568 return NGX_DECLINED;
569 }
570
571 p += key[i].len;
554 } 572 }
555 573
556 if ((size_t) h->body_start > c->body_start) { 574 if ((size_t) h->body_start > c->body_start) {
557 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, 575 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
558 "cache file \"%s\" has too long header", 576 "cache file \"%s\" has too long header",
581 599
582 c->valid_sec = h->valid_sec; 600 c->valid_sec = h->valid_sec;
583 c->last_modified = h->last_modified; 601 c->last_modified = h->last_modified;
584 c->date = h->date; 602 c->date = h->date;
585 c->valid_msec = h->valid_msec; 603 c->valid_msec = h->valid_msec;
586 c->header_start = h->header_start;
587 c->body_start = h->body_start; 604 c->body_start = h->body_start;
588 c->etag.len = h->etag_len; 605 c->etag.len = h->etag_len;
589 c->etag.data = h->etag; 606 c->etag.data = h->etag;
590 607
591 r->cached = 1; 608 r->cached = 1;