KNOX-1211 - Admin UI XSS/XSRF Protection

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/2a8d8661
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/2a8d8661
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/2a8d8661

Branch: refs/heads/master
Commit: 2a8d86617e2b9109f6a366dd4f6bdc20fbd25050
Parents: 76df40b
Author: Phil Zampino <[email protected]>
Authored: Thu Mar 15 15:56:51 2018 -0400
Committer: Phil Zampino <[email protected]>
Committed: Fri Mar 16 16:27:52 2018 -0400

----------------------------------------------------------------------
 gateway-admin-ui/src/app/app.module.ts          |   3 +-
 .../src/app/gateway-version.service.ts          |   3 +-
 .../src/app/resource/resource.service.ts        |  23 +--
 gateway-admin-ui/src/app/topology.service.ts    |  13 +-
 .../applications/admin-ui/app/index.html        |   2 +-
 .../app/inline.85938ebdfc746c97e676.bundle.js   |   1 +
 .../app/inline.a7f3e89f1023e555e44a.bundle.js   |   1 -
 .../app/main.0261e7c80254eec2d83c.bundle.js     |   1 +
 .../app/main.743b2fb8ac3467eb4d6e.bundle.js     |   1 -
 .../topology/discovery/ambari/RESTInvoker.java  |   3 +
 .../webappsec/deploy/WebAppSecContributor.java  |  13 +-
 .../webappsec/filter/StrictTranportFilter.java  | 137 ----------------
 .../webappsec/filter/StrictTransportFilter.java | 137 ++++++++++++++++
 .../webappsec/filter/XFrameOptionsFilter.java   |   4 +-
 .../webappsec/filter/XSSProtectionFilter.java   | 132 +++++++++++++++
 .../webappsec/StrictTranportFilterTest.java     | 164 -------------------
 .../webappsec/StrictTransportFilterTest.java    | 164 +++++++++++++++++++
 .../webappsec/XSSProtectionFilterTest.java      | 149 +++++++++++++++++
 .../home/conf/topologies/manager.xml            |   1 +
 19 files changed, 619 insertions(+), 333 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-admin-ui/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.module.ts 
b/gateway-admin-ui/src/app/app.module.ts
index 19e4347..0810786 100644
--- a/gateway-admin-ui/src/app/app.module.ts
+++ b/gateway-admin-ui/src/app/app.module.ts
@@ -16,7 +16,7 @@
  */
 import { NgModule }      from '@angular/core';
 import { BrowserModule } from '@angular/platform-browser';
-import { HttpClientModule } from "@angular/common/http";
+import { HttpClientModule, HttpClientXsrfModule } from "@angular/common/http";
 import { FormsModule } from '@angular/forms';
 import { CustomFormsModule } from 'ng2-validation';
 
@@ -46,6 +46,7 @@ import { ProviderConfigWizardComponent } from 
'./provider-config-wizard/provider
 @NgModule({
   imports: [ BrowserModule,
              HttpClientModule,
+             HttpClientXsrfModule,
              FormsModule,
              CustomFormsModule,
              BsModalModule,

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-admin-ui/src/app/gateway-version.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/gateway-version.service.ts 
b/gateway-admin-ui/src/app/gateway-version.service.ts
index 38b247c..810e669 100644
--- a/gateway-admin-ui/src/app/gateway-version.service.ts
+++ b/gateway-admin-ui/src/app/gateway-version.service.ts
@@ -41,7 +41,8 @@ export class GatewayVersionService {
 
     addHeaders(headers: HttpHeaders) {
         return headers.append('Accept', 'application/json')
-                      .append('Content-Type', 'application/json');
+                      .append('Content-Type', 'application/json')
+                      .append('X-XSRF-Header', 'admin-ui');
     }
 
     private handleError(error: any): Promise<any> {

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-admin-ui/src/app/resource/resource.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/resource/resource.service.ts 
b/gateway-admin-ui/src/app/resource/resource.service.ts
index 88b8de5..b709dab 100644
--- a/gateway-admin-ui/src/app/resource/resource.service.ts
+++ b/gateway-admin-ui/src/app/resource/resource.service.ts
@@ -61,7 +61,6 @@ export class ResourceService {
 
     getProviderConfigResources(): Promise<Resource[]> {
         let headers = this.addJsonHeaders(new HttpHeaders());
-        //this.logHeaders(headers);
         return this.http.get(this.providersUrl, { headers: headers })
                         .toPromise()
                         .then(response => response['items'] as Resource[])
@@ -73,7 +72,6 @@ export class ResourceService {
 
     getDescriptorResources(): Promise<Resource[]> {
         let headers = this.addJsonHeaders(new HttpHeaders());
-        //this.logHeaders(headers);
         return this.http.get(this.descriptorsUrl, { headers: headers })
                         .toPromise()
                         .then(response => response['items'] as Resource[])
@@ -85,7 +83,6 @@ export class ResourceService {
 
     getTopologyResources(): Promise<Resource[]> {
         let headers = this.addJsonHeaders(new HttpHeaders());
-        //this.logHeaders(headers);
         return this.http.get(this.topologiesUrl, { headers: headers })
                         .toPromise()
                         .then(response => response['topologies'].topology as 
Resource[])
@@ -99,7 +96,6 @@ export class ResourceService {
         if (res) {
             let headers = new HttpHeaders();
             headers = (resType === 'Topologies') ? this.addXmlHeaders(headers) 
: this.addHeaders(headers, res.name);
-            //this.logHeaders(headers);
 
             return this.http.get(res.href, {headers: headers, responseType: 
'text'})
                 .toPromise()
@@ -118,8 +114,6 @@ export class ResourceService {
 
     saveResource(resource: Resource, content: string): Promise<string> {
         let headers = this.addHeaders(new HttpHeaders(), resource.name);
-        headers = this.addCsrfHeaders(headers);
-        //this.logHeaders(headers);
 
         console.debug('ResourceService --> Persisting ' + resource.name + '\n' 
+ content);
 
@@ -134,8 +128,6 @@ export class ResourceService {
 
     createResource(resType: string, resource: Resource, content : string): 
Promise<string> {
         let headers = this.addHeaders(new HttpHeaders(), resource.name);
-        headers = this.addCsrfHeaders(headers);
-        //this.logHeaders(headers);
 
         let url = ((resType === 'Descriptors') ? this.descriptorsUrl : 
this.providersUrl) + '/' + resource.name;
         return this.http.put(url, content, {headers: headers})
@@ -149,8 +141,6 @@ export class ResourceService {
 
     deleteResource(href: string): Promise<string> {
         let headers = this.addJsonHeaders(new HttpHeaders());
-        headers = this.addCsrfHeaders(headers);
-        //this.logHeaders(headers);
 
         return this.http.delete(href, { headers: headers } )
                         .toPromise()
@@ -255,22 +245,23 @@ export class ResourceService {
               break;
           }
         }
+        this.logHeaders(headers); // TODO: PJZ: DELETE ME
         return headers;
     }
 
     addTextPlainHeaders(headers: HttpHeaders) {
-        return headers.append('Accept', 'text/plain')
-                      .append('Content-Type', 'text/plain');
+        return this.addCsrfHeaders(headers.append('Accept', 'text/plain')
+                                          .append('Content-Type', 
'text/plain'));
     }
 
     addJsonHeaders(headers: HttpHeaders): HttpHeaders {
-        return headers.append('Accept', 'application/json')
-                      .append('Content-Type', 'application/json');
+        return this.addCsrfHeaders(headers.append('Accept', 'application/json')
+                                          .append('Content-Type', 
'application/json'));
     }
 
     addXmlHeaders(headers: HttpHeaders): HttpHeaders {
-        return headers.append('Accept', 'application/xml')
-                      .append('Content-Type', 'application/xml');
+        return this.addCsrfHeaders(headers.append('Accept', 'application/xml')
+                                          .append('Content-Type', 
'application/xml'));
     }
 
     addCsrfHeaders(headers: HttpHeaders): HttpHeaders {

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-admin-ui/src/app/topology.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/topology.service.ts 
b/gateway-admin-ui/src/app/topology.service.ts
index dc2559f..c71225b 100644
--- a/gateway-admin-ui/src/app/topology.service.ts
+++ b/gateway-admin-ui/src/app/topology.service.ts
@@ -35,7 +35,7 @@ export class TopologyService {
 
     getTopologies(): Promise<Topology[]> {
         let headers = new HttpHeaders();
-        this.addJsonHeaders(headers);
+        headers = this.addJsonHeaders(headers);
         return this.http.get(this.topologiesUrl, {
             headers: headers
         } )
@@ -59,7 +59,6 @@ export class TopologyService {
     saveTopology(url: string, xml : string): Promise<string> {
         let xheaders = new HttpHeaders();
         xheaders = this.addXmlHeaders(xheaders);
-        xheaders = this.addCsrfHeaders(xheaders);
         return this.http
             .put(url, xml, { headers: xheaders, responseType: 'text' })
             .toPromise()
@@ -71,7 +70,6 @@ export class TopologyService {
     createTopology(name: string, xml : string): Promise<string> {
         let xheaders = new HttpHeaders();
         xheaders = this.addXmlHeaders(xheaders);
-        xheaders = this.addCsrfHeaders(xheaders);
         let url = this.topologiesUrl + "/" + name;
         return this.http
             .put(url, xml, { headers: xheaders, responseType: 'text' })
@@ -83,7 +81,6 @@ export class TopologyService {
     deleteTopology(href: string): Promise<string> {
         let headers = new HttpHeaders();
         headers = this.addJsonHeaders(headers);
-        headers = this.addCsrfHeaders(headers);
         return this.http.delete(href, {
             headers: headers, responseType: 'text'
         } )
@@ -93,13 +90,13 @@ export class TopologyService {
     }
 
     addJsonHeaders(headers: HttpHeaders): HttpHeaders {
-        return headers.append('Accept', 'application/json')
-                      .append('Content-Type', 'application/json');
+        return this.addCsrfHeaders(headers.append('Accept', 'application/json')
+                                          .append('Content-Type', 
'application/json'));
     }
 
     addXmlHeaders(headers: HttpHeaders): HttpHeaders {
-        return headers.append('Accept', 'application/xml')
-                      .append('Content-Type', 'application/xml');
+        return this.addCsrfHeaders(headers.append('Accept', 'application/xml')
+                                          .append('Content-Type', 
'application/xml'));
     }
 
     addCsrfHeaders(headers: HttpHeaders): HttpHeaders {

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
----------------------------------------------------------------------
diff --git 
a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html 
b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
index e7a9514..02c0b54 100644
--- 
a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
+++ 
b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
@@ -11,4 +11,4 @@
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
---><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox 
Manager</title><meta name="viewport" 
content="width=device-width,initial-scale=1"><link rel="icon" 
type="image/x-icon" href="favicon.ico"><meta name="viewport" 
content="width=device-width,initial-scale=1"><!-- Latest compiled and minified 
CSS --><link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"; 
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
 crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css";
 
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
 crossorigin="anonymous"><!-- Custom styles for this template --><link 
href="assets/sticky-footer.css" rel="stylesheet"><script 
src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js";></script><!--
 Latest compiled and minified JavaScript --><scr
 ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"; 
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
 crossorigin="anonymous"></script><script 
src="assets/vkbeautify.js"></script><link 
href="styles.2ee5b7f4cd59a6cf015e.bundle.css" 
rel="stylesheet"/></head><body><div class="navbar-wrapper"><div 
class="container-fluid"><nav class="navbar navbar-inverse 
navbar-static-top"><div class="container-fluid"><div 
class="navbar-header"><button type="button" class="navbar-toggle collapsed" 
data-toggle="collapse" data-target="#navbar" aria-expanded="false" 
aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span 
class="icon-bar"></span> <span class="icon-bar"></span> <span 
class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img 
style="max-width:200px; margin-top: -9px;" 
src="assets/knox-logo-transparent.gif" alt="Apache Knox 
Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
 ource-management><footer class="footer"><div class="container-fluid"><div>Knox 
Manager Version 
0.1.0</div><gateway-version></gateway-version></div></footer><script 
type="text/javascript" 
src="inline.a7f3e89f1023e555e44a.bundle.js"></script><script 
type="text/javascript" 
src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script 
type="text/javascript" 
src="main.743b2fb8ac3467eb4d6e.bundle.js"></script></div></body></html>
\ No newline at end of file
+--><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox 
Manager</title><meta name="viewport" 
content="width=device-width,initial-scale=1"><link rel="icon" 
type="image/x-icon" href="favicon.ico"><meta name="viewport" 
content="width=device-width,initial-scale=1"><!-- Latest compiled and minified 
CSS --><link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"; 
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
 crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css";
 
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
 crossorigin="anonymous"><!-- Custom styles for this template --><link 
href="assets/sticky-footer.css" rel="stylesheet"><script 
src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js";></script><!--
 Latest compiled and minified JavaScript --><scr
 ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"; 
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
 crossorigin="anonymous"></script><script 
src="assets/vkbeautify.js"></script><link 
href="styles.2ee5b7f4cd59a6cf015e.bundle.css" 
rel="stylesheet"/></head><body><div class="navbar-wrapper"><div 
class="container-fluid"><nav class="navbar navbar-inverse 
navbar-static-top"><div class="container-fluid"><div 
class="navbar-header"><button type="button" class="navbar-toggle collapsed" 
data-toggle="collapse" data-target="#navbar" aria-expanded="false" 
aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span 
class="icon-bar"></span> <span class="icon-bar"></span> <span 
class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img 
style="max-width:200px; margin-top: -9px;" 
src="assets/knox-logo-transparent.gif" alt="Apache Knox 
Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
 ource-management><footer class="footer"><div class="container-fluid"><div>Knox 
Manager Version 
0.1.0</div><gateway-version></gateway-version></div></footer><script 
type="text/javascript" 
src="inline.85938ebdfc746c97e676.bundle.js"></script><script 
type="text/javascript" 
src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script 
type="text/javascript" 
src="main.0261e7c80254eec2d83c.bundle.js"></script></div></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-applications/src/main/resources/applications/admin-ui/app/inline.85938ebdfc746c97e676.bundle.js
----------------------------------------------------------------------
diff --git 
a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.85938ebdfc746c97e676.bundle.js
 
b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.85938ebdfc746c97e676.bundle.js
new file mode 100644
index 0000000..af22844
--- /dev/null
+++ 
b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.85938ebdfc746c97e676.bundle.js
@@ -0,0 +1 @@
+!function(e){var 
n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var 
a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in 
c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return
 f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var 
t=r[n]={i:n,l:!1,exports:{}};return 
e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var 
n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new 
Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var 
c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"0261e7c80254eec2d83c",1:"aed76669724804835353"}[e]+".chunk.js";var
 a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var 
n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
 nk "+e+" failed.")),t[e]=void 0)}return 
u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
o.d(n,"a",n),n},o.o=function(e,n){return 
Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw 
console.error(e),e}}([]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/2a8d8661/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
----------------------------------------------------------------------
diff --git 
a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
 
b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
deleted file mode 100644
index a852b61..0000000
--- 
a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.a7f3e89f1023e555e44a.bundle.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e){var 
n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var 
a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in 
c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return
 f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var 
t=r[n]={i:n,l:!1,exports:{}};return 
e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var 
n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new 
Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var 
c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"743b2fb8ac3467eb4d6e",1:"aed76669724804835353"}[e]+".chunk.js";var
 a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var 
n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
 nk "+e+" failed.")),t[e]=void 0)}return 
u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
o.d(n,"a",n),n},o.o=function(e,n){return 
Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw 
console.error(e),e}}([]);
\ No newline at end of file

Reply via email to