Shared machine PII leakage



  • Not sure how far I can go with this one, but I can certainly duplicate it with 2 users on the same machine.

    Steps to duplicate:

    • Have 2 users, let's call them @X and @Y
    • Log in as @X
    • Do a quick "view source", note that near the top of the page there is a JSON.parse statement containing, amongst other things, @X's email address in plaintext
    • Log out
    • Do a quick "view source", note that near the top of the page there is a JSON.parse statement, correctly blanked out
    • Log in as @Y
    • Do a quick "view source", note that near the top of the page there is a JSON.parse statement containing, amongst other things, @Y's email address in plaintext

    So far so good.

    • Log out.
    • Do a quick "view source", note that near the top of the page there is a JSON.parse statement, correctly blanked out
    • Log in as @X
    • Click on a "user page" icon from the displayed topics list
    • Do a quick "view source", note that near the top of the page there is a JSON.parse statement containing, amongst other things, @Y's email address in plaintext

  • :belt_onion:

    @tufty Uh...

    Caching?

    That's the only thing I can think of that might cause that?



  • @sloosecannon Or a variable which wasn't correctly changed / unset upon logout.


  • :belt_onion:

    @Rhywden said in Shared machine PII leakage:

    @sloosecannon Or a variable which wasn't correctly changed / unset upon logout.

    But the next logon should've overwritten that...


  • :belt_onion:

    @sloosecannon said in Shared machine PII leakage:

    @Rhywden said in Shared machine PII leakage:

    @sloosecannon Or a variable which wasn't correctly changed / unset upon logout.

    But the next logon should've overwritten that...

    Unless there's something funky going on with the multi-server configuration.

    cc @administrators, @TDWTF-NodeBB-Development - any ideas on what might cause it?


  • Trolleybus Mechanic

    @sloosecannon said in Shared machine PII leakage:

    But the next logon should've overwritten that...

    It should have.

    But it didn't, because logging out and logging in doesn't actually take you to a different page.

    because this is a Single Page App.

    Web 3.0!


  • :belt_onion:

    @Lorne-Kates said in Shared machine PII leakage:

    @sloosecannon said in Shared machine PII leakage:

    But the next logon should've overwritten that...

    It should have.

    But it didn't, because logging out and logging in doesn't actually take you to a different page.

    because this is a Single Page App.

    Web 3.0!

    Err... I don't think that has anything to do with it?


  • Trolleybus Mechanic

    @sloosecannon said in Shared machine PII leakage:

    Err... I don't think that has anything to do with it?

    Sure it does. The ParseJSON thing is because rather than just rendering HTML and sending it to the browser, Web 3.0 instead sends a bunch of data to the browser so it can render the HTML. This is probably being used to build the Preference menu or something stupid.

    On a normal, non-SPA site, that might be fine. On each new page, it sends a new chunk of data, retrieved fresh from the server. So just by happenstance, when you log out and log in again, since those are all completely different, distinct browser requests, the data is different.

    But this is an SPA. So when you log out and log in, it's all done via AJAX. There's no browser navigation. So that data that was sitting there is still sitting there.

    Now, I would doubt if that's compounded by some server-side idiocy that goes like this:

    @X logs in-- cache @X data for this session.  First time for this session. Must fill that ParseJSON. Send fresh data.
    @X logs out-- lolwhat is clear cache
    @Y logs in-- cache @Y data for this session.  First time for this session. Must fill that ParseJSON. Send fresh data.  
    @Y logs out-- lolwhat is clear cache
    @X logs in-- this user has logged in from this session before, so there's no need to re-fill that ParseJSON.  Or just use the most recent Cached data (@Y).
    

    And all that "smart" caching is needed because it's a SPA.

    I don't feel like doing a code review I'm not being paid for, but I'd bet that's it.


  • :belt_onion:

    @Lorne-Kates said in Shared machine PII leakage:

    So that data that was sitting there is still sitting there.

    But it's not, because it's gone after he logs out...



  • @tufty I have followed your steps multiple times and cannot reproduce the problem.

    If what you said was actually happening, user Y's avatar should show up instead of user X's avatar due to the way the page is generated. Which means you accidentally logged in as user Y the last time.


  • :belt_onion:

    @ben_lubar Both loud, and presumptuous (the forum software is perfect?). Give him a chance to revise his minimal test case if need be. Also God knows with the nature of Node.js it could be a race condition of some kind or another oddity related to the asynchronous execution.



  • I think it may be a cacheing issue as suggested by @sloosecannon actually.

    Far as I can tell, what's happening is this (I was investigating ways to get at other users' data)

    • Logged in as X, I load, for example, https://what.thedailywtf.com/user/ben_lubar
    • I hit "view source"
    • The browser shows me the source it just loaded, as it's not cached
    • Then I log in as Y, and load, again for example, https://what.thedailywtf.com/user/ben_lubar
    • I hit "view source"
    • The browser sees that it already has a non-expired cached version (of the static page source - when rendering the page it shows me Y's avatar etc as that's presumably loaded dynamically via ajax) and shows me that, including X's PII.

    Looking at the page via the developer tools, I think (but will check in a minute) shows me the currently displayed source, as opposed to any cached static version.

    [edit] Confirm that developer tools inspector gives me the source for the currently displayed page

    This may be a browser issue, but I suspect there's something being missed on logout WRT invalidating caches.

    [edit edit]

    Also get PII when logged /out/ for pages I've already viewed source for.



  • @tufty If two users use the same account on your local computer, you'll have serious security problems, and I wouldn't even try to make it safe for this use case. Just forgetting to log out would already expose you.

    Said that, at the University I went for, they were using accounts like this. They replaced the windows account with whatever their network stack thing was. And I happened to open gmail, and it show me as logged in as the previous user. They would probably be affected by this.



  • @fbmac said in Shared machine PII leakage:

    If two users use the same account on your local computer, you'll have serious security problems

    Oh, quite. Still, it's a potential security hole, and I'm pretty damn sure it's not the browser's fault.


  • :belt_onion:

    @tufty said in Shared machine PII leakage:

    @fbmac said in Shared machine PII leakage:

    If two users use the same account on your local computer, you'll have serious security problems

    Oh, quite. Still, it's a potential security hole, and I'm pretty damn sure it's not the browser's fault.

    I suggested caching because it's the most likely thing to cause that kind of nondeterministic weird behavior. :)

    @ben_lubar - what's the nginx caching config? Is it set to aggressively cache anything? If not, maybe we need to play with headers to make sure dynamic stuff like that isn't cached.



  • @sloosecannon said in Shared machine PII leakage:

    what's the nginx [...] config

    /etc/nginx/sites-enabled/what.thedailywtf.com

    include /etc/nginx/nodebb-upstream.conf;
    
    server {
    	listen 80 default_server;
    	listen [::]:80 default_server ipv6only=on;
    
    	server_name what.thedailywtf.com;
    	return 301 https://what.thedailywtf.com$request_uri;
    }
    
    server {
    	ssl_certificate /usr/share/nginx/ssl/ssl.crt;
    	ssl_certificate_key /usr/share/nginx/ssl/ssl.key;
    	ssl_dhparam /usr/share/nginx/ssl/dhparams.pem;
    	ssl_session_cache shared:SSL:10m; # roughly 40k cached sessions
    
    	ssl_protocols TLSv1.2 TLSv1.1 TLSv1; # disable SSLv3 due to the POODLE
    
    	# enable Perfect Forward Secrecy
    	ssl_prefer_server_ciphers on;
    	ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    
    	listen 443 default_server ssl;
    	listen [::]:443 default_server ssl ipv6only=on;
    
    	server_name what.thedailywtf.com;
    
    	add_header Strict-Transport-Security "max-age=31536000";
    	merge_slashes off;
    
    	client_max_body_size 25m;
    
    	location @nodebb_ratelimit {
    		limit_req zone=bots_ip burst=2;
    		limit_req zone=bots_ua burst=2;
    
    		add_header X-Upstream $upstream_addr;
    		add_header Strict-Transport-Security "max-age=31536000";
    
    		proxy_pass http://nodebb$request_uri;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header Host $http_host;
    		proxy_set_header X-NginX-Proxy true;
    		proxy_set_header X-Forwarded-Proto $scheme;
    		proxy_set_header Upgrade $http_upgrade;
    		proxy_set_header Connection "upgrade";
    		proxy_http_version 1.1;
    	}
    
    	location @nodebb {
    		# PICNIC
    		error_page 429 = @nodebb_ratelimit;
    		if ($http_user_agent ~* ^sockbot/) {
    			set $should_rate_limit "sock";
    		}
    		if ($http_user_agent ~* (bot|spider|slurp|crawler)) {
    			set $should_rate_limit "${should_rate_limit}bot";
    		}
    		if ($should_rate_limit = bot) {
    			return 429;
    		}
    
    		add_header X-Upstream $upstream_addr;
    		add_header Strict-Transport-Security "max-age=31536000";
    
    		proxy_pass http://nodebb$request_uri;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header Host $http_host;
    		proxy_set_header X-NginX-Proxy true;
    		proxy_set_header X-Forwarded-Proto $scheme;
    		proxy_set_header Upgrade $http_upgrade;
    		proxy_set_header Connection "upgrade";
    		proxy_http_version 1.1;
    		proxy_connect_timeout 1;
    	}
    
    	location /uploads {
    		include /etc/nginx/bad-bots.conf;
    
    		alias /usr/share/nginx/wtdwtf-nodebb.uploads;
    		default_type image/png;
    		expires max;
    		add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; img-src *; media-src *; object-src 'self'";
    		add_header Strict-Transport-Security "max-age=31536000";
    		try_files $uri =404;
    	}
    
    	location = /robots.txt {
    		alias /usr/share/nginx/html;
    		expires 14d;
    		try_files /robots.txt =404;
    	}
    
    	location ~ ^/forums(/[0-9]+)/PostAttachment\.aspx$ {
    		alias /usr/share/nginx/wtdwtf-nodebb.uploads/community-server-attachments;
    		expires max;
    		try_files $1.8phones $1.explorer $1.gif $1.htm $1.jpg $1.png $1.vsi $1.zip =404;
    	}
    
    	location /message-bus/ {
    		deny all;
    	}
    
    	location /logs/report_js_error {
    		deny all;
    	}
    
    	location /topics/timings {
    		deny all;
    	}
    
    	location /robots.txt {
    		try_files /nonexistent @nodebb;
    	}
    
    	location = /topic/14468/til-%EF%BD%81%EF%BD%82%EF%BD%8F%EF%BD%95%EF%BD%94-%EF%BD%94%EF%BD%88%EF%BD%85-%EF%BD%84%EF%BD%81%EF%BD%E2%80%99%EF%BD%8B-%EF%BD%81%EF%BD%E2%80%99%EF%BD%94%EF%BD%93-%EF%BD%8F%EF%BD%86-%EF%BD%88%EF%BD%94%EF%BD%8D%EF%BD%8C {
    		deny all;
    	}
    
    	location / {
    		include /etc/nginx/bad-bots.conf;
    
    		# fix some 404s found by GoogleBot
    		#rewrite ^/users/([a-z0-9_]+)$ /user/$1 permanent;
    		rewrite ^/c/([a-z0-9_\-]+)/l/latest$ /c/$1 permanent;
    		rewrite ^/login\.aspx$ /login permanent;
    		rewrite ^/t//([0-9]+)(/.*)?$ /t/topic/$1$2 permanent;
    		rewrite ^/t/([0-9]+/[0-9]+)$ /t/topic/$1 permanent;
    		rewrite ^/topic/([0-9]+)//(.*)$ /topic/$1/topic/$2 permanent;
    
    		# redirect article topics
    		rewrite ^/topic/11550(/|$) http://thedailywtf.com/Articles/Double-Seekrit-Discourse-Test.aspx permanent;
    		rewrite ^/topic/11551(/|$) http://thedailywtf.com/Articles/Bonecrusher-Loves-His-Cat-Food.aspx permanent;
    		rewrite ^/topic/11597(/|$) http://thedailywtf.com/Articles/Half-Credit.aspx permanent;
    		rewrite ^/topic/11634(/|$) http://thedailywtf.com/Articles/Get-Message-Error!.aspx permanent;
    # snip 396 lines
    		rewrite ^/topic/19104(/|$) http://thedailywtf.com/articles/admin-from-hell permanent;
    		rewrite ^/topic/19105(/|$) http://thedailywtf.com/articles/back-away-slowly permanent;
    		rewrite ^/topic/19109(/|$) http://thedailywtf.com/articles/code-changes-over-time permanent;
    		rewrite ^/topic/19129(/|$) http://thedailywtf.com/articles/encryption-by-analogy permanent;
    		rewrite ^/topic/19153(/|$) http://thedailywtf.com/articles/string-cheese permanent;
    		rewrite ^/topic/19172(/|$) http://thedailywtf.com/articles/adequate-enough permanent;
    
    		try_files /nonexistent @nodebb;
    	}
    }
    
    server {
    	ssl_certificate /usr/share/nginx/ssl/ssl.crt;
    	ssl_certificate_key /usr/share/nginx/ssl/ssl.key;
    	ssl_dhparam /usr/share/nginx/ssl/dhparams.pem;
    	ssl_session_cache shared:SSL:10m; # roughly 40k cached sessions
    
    	ssl_protocols TLSv1.2 TLSv1.1 TLSv1; # disable SSLv3 due to the POODLE
    
    	# enable Perfect Forward Secrecy
    	ssl_prefer_server_ciphers on;
    	ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    
    	listen 8061 ssl;
    	listen [::]:8061 ssl ipv6only=on;
    
    	server_name what.thedailywtf.com;
    
    	add_header Strict-Transport-Security "max-age=31536000";
    
    	location @iframely {
    		proxy_pass http://unix:/usr/share/nginx/wtdwtf-nodebb.sock/iframely:$request_uri;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header Host $http_host;
    		proxy_set_header X-NginX-Proxy true;
    		proxy_set_header Upgrade $http_upgrade;
    		proxy_set_header Connection "upgrade";
    		proxy_http_version 1.1;
    	}
    
    	location / {
    		include /etc/nginx/bad-bots.conf;
    		try_files /nonexistent @iframely;
    	}
    }
    

    /etc/nginx/sites-enabled/forums.thedailywtf.com

    server {
            listen 80;
            listen [::]:80;
    
            server_name forums.thedailywtf.com;
    
            include /etc/nginx/bad-bots.conf;
    
            return 301 https://what.thedailywtf.com$request_uri;
    }
    

    /etc/nginx/bad-bots.conf

    if ($http_user_agent ~* (linkdexbot|AhrefsBot|BLEXBot|Sogou|Mail\.RU_Bot)) {
            return 503;
    }
    

    /etc/nginx/nodebb-upstream.conf

    upstream nodebb {
            ip_hash;
    
            server 172.18.0.253:4567;
            server 172.18.0.253:4568;
            server 172.18.0.254:4567 down;
            server 172.18.0.254:4568 down;
    
            keepalive 16;
    }
    

    /etc/nginx/conf.d/rate-limit.conf

    limit_req_zone $binary_remote_addr zone=bots_ip:10m rate=6r/m;
    limit_req_zone $http_user_agent zone=bots_ua:10m rate=6r/m;
    
    # limit_req is in @nodebb_ratelimit
    

    (all other config files are nginx 1.4.6-1ubuntu3 defaults)

    (yes, I've double-checked to make sure there isn't anything I shouldn't be sharing in there)


  • Considered Harmful

    @ben_lubar said in Shared machine PII leakage:

      if ($http_user_agent ~* ^sockbot/) {
      	set $should_rate_limit "sock";
      }
      if ($http_user_agent ~* (bot|spider|slurp|crawler)) {
      	set $should_rate_limit "${should_rate_limit}bot";
      }
    

    Preferential bot treatment? :wtf:



  • @error said in Shared machine PII leakage:

    @ben_lubar said in Shared machine PII leakage:

      if ($http_user_agent ~* ^sockbot/) {
      	set $should_rate_limit "sock";
      }
      if ($http_user_agent ~* (bot|spider|slurp|crawler)) {
      	set $should_rate_limit "${should_rate_limit}bot";
      }
    

    Preferential bot treatment? :wtf:

    We had some trouble with search engine indexing taking the site down.


Log in to reply