Why does CSP block my own source even though I set it so self? - https

I'm currenty learning and setting up CSP and I'm not sure what the problem is here.
I have set my CSP like this (Caddy):
(content_policy) {
header {
# For older browser, newer ones use frame ancestors
# SAMEORIGIN = self, DENY = none
X-Frame-Options DENY
Content-Security-Policy "
default-src 'self';
style-src 'self';
script-src 'self';
font-src 'self';
img-src 'self';
form-action 'self';
connect-src 'self';
frame-ancestors 'none';
object-src 'none';"
}
}
But two sources from a selhosted AdGuard instance are blocked even though they are from "self":
Does someone know why or what I did wrong here?

Related

Remove Content-Length using AWS Lambda#Edge

I Have the following CloudFront setup via a AWS CloudFormation template:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
DependsOn:
- LoggingBucket
- LambdaEdgeFunction
Properties:
DistributionConfig:
Comment: 'Route to multiple origins with CloudFront'
Enabled: true
IPV6Enabled: !Ref 'IPV6Enabled'
Logging:
Bucket: !Sub '${LoggingBucket}.s3.amazonaws.com'
HttpVersion: http2
Comment: !Join [ '', [!Ref 'AWS::StackName', ' Cloud Front']]
Aliases:
- !Ref 'AlternateDomainNames'
ViewerCertificate:
AcmCertificateArn: !Ref ACMCertificateArn
SslSupportMethod: !Ref 'SslSupportMethod' #sni-only
MinimumProtocolVersion: !Ref 'MinimumProtocolVersion' #TLSv1.1_2016
Origins:
- Id: APIGOrigin
DomainName: !Sub ${ApiGatewayId}.execute-api.eu-west-1.amazonaws.com
OriginPath: !Sub /${ApiStage}
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: 'X-From-CDN'
HeaderValue: !Ref VerifyFromCfHeaderVal
DefaultCacheBehavior:
AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
CachedMethods: ["GET", "HEAD", "OPTIONS"]
ForwardedValues:
Headers:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
- Authorization
- Accept
# - Host APIG needs to use SNI
QueryString: !Ref 'QueryString'
Cookies:
Forward: !Ref 'ForwardCookies'
TargetOriginId: APIGOrigin
ViewerProtocolPolicy: https-only
Compress: !Ref 'Compress'
DefaultTTL: !Ref 'DefaultTTL'
MaxTTL: !Ref 'MaxTTL'
MinTTL: !Ref 'MinTTL'
SmoothStreaming: 'false'
# Lambda
LambdaFunctionAssociations:
- EventType: !Ref 'LambdaEventType'
LambdaFunctionARN: !Ref 'LambdaEdgeVersion'
CustomErrorResponses:
- ErrorCachingMinTTL: 0
ErrorCode: 400
- ErrorCachingMinTTL: 1
ErrorCode: 403
- ErrorCachingMinTTL: 5
ErrorCode: 500
So every time, the API Gateway origin responds, it will trigger the Lambda#Edge, which currently I have as:
# LAMBDA#EDGE FUNCTION
LambdaEdgeFunction:
Type: 'AWS::Lambda::Function'
Properties:
Description: !Sub 'A custom Lambda#Edge function for serving custom headers from CloudFront Distribution'
FunctionName: !Sub '${AppName}-lambda-edge-${Environment}'
Handler: index.handler
Role: !GetAtt 'LambdaEdgeIAMRole.Arn'
MemorySize: 128
Timeout: 5
Code:
ZipFile: !Sub |
'use strict';
exports.handler = (event, context, callback) => {
console.log('Adding additional headers to CloudFront response.');
const response = event.Records[0].cf.response;
console.log("Response received:\n", JSON.stringify(response));
response.headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=86400; includeSubdomains; preload',
}];
response.headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff',
}];
response.headers['x-frame-options'] = [{
key: 'X-Frame-Options',
value: "DENY"
}];
response.headers['content-security-policy'] = [{
key: 'Content-Security-Policy',
value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"
}];
response.headers['x-xss-protection'] = [{
key: 'X-XSS-Protection',
value: "1; mode=block"
}];
response.headers['referrer-policy'] = [{
key: 'Referrer-Policy',
value: "same-origin"
}];
console.log('Remove Content-Length headers from CloudFront response..');
delete response.headers["Content-Length"]
callback(null, response);
};
Runtime: nodejs12.x
When I send a request to my endpoint, I can still see the Content-Length in the response:
curl -i --http1.1 \
--url https://cdn.domain.tld/s/94163e58494
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Content-Length: 316
Connection: keep-alive
Server: CloudFront
Date: Thu, 30 Apr 2020 17:54:54 GMT
Referrer-Policy: same-origin
X-Frame-Options: DENY
x-amz-apigw-id: Lz-VPFnLDoEFbig=
Cache-Control: max-age=0, no-cache, private
Location: http://google.com
Via: 1.1 15c672a1a9***.cloudfront.net (CloudFront), 1.1 0b7c0b1558a4*****.cloudfront.net (CloudFront)
Strict-Transport-Security: max-age=86400; includeSubdomains; preload
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'
X-XSS-Protection: 1; mode=block
x-amzn-RequestId: 0a29a0a9-c14f-4c14-b773-d57813cf91c3
X-Amzn-Trace-Id: Root=1-5eab10ee-50d2c5e08498c8689ad025e0;Sampled=0
X-Amz-Cf-Pop: LHR52-C1
X-Cache: Miss from cloudfront
X-Amz-Cf-Pop: LHR52-C1
X-Amz-Cf-Id: c1KMNm2DOHzfzsIYLBeShWVlxVyaN8yO33hZ3aAAjVIR03x2gx49sw==
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://google.com'" />
<title>Redirecting to http://google.com</title>
</head>
<body>
Redirecting to http://google.com.
</body>
</html>
I have followed https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/ guide, but I am still not able to see how to remove the Content-Length from the response - is this possible?
Any advice is much appreciated
What's LambdaEventType? It should be viewer-response to edit CloudFront's response.
Your function should delete content-length and not Content-Length as the header names are expected to be lower case in the headers array.
delete response.headers["content-length"]
Documentation says:
The keys in the headers object are lowercase versions of standard HTTP header names. Using lowercase keys gives you case-insensitive access to the header values.
It seems you can't modify a read-only header as you get this error:
The Lambda function result failed validation: The function tried to add, delete, or change a read-only header.

JMETER ERROR: {"errorcode":9999,"errormessage":"Unexpected token % in JSON at position 0"}

I am running a test and on running it after co-relating sessionid, I am getting the following below error in "response data" tab in "view results tree listener".
Can you please help me fix this error:
Sampler Result:
Thread Name: Xaas_No 1-1
Sample Start: 2018-06-14 14:57:20 IST
Load time: 1731
Connect Time: 1255
Latency: 1730
Size in bytes: 852
Sent bytes:957
Headers size in bytes: 776
Body size in bytes: 76
Sample Count: 1
Error Count: 1
Data type ("text"|"bin"|""): text
Response code: 500
Response message: Internal Server Error
Response headers:
HTTP/1.1 500 Internal Server Error
x-powered-by: Express
content-type: application/json; charset=utf-8
content-length: 76
etag: W/"4c-gdbCiVcDg5gx+63/uawAq4eRIu0"
date: Thu, 14 Jun 2018 09:27:12 GMT
connection: close
Set-Cookie: BIGipServeriapxaasbotbuildertest.accenture.com-443=1932329994.47873.0000;Path=/;Version=1;Secure;Httponly
Content-Security-Policy: default-src 'self' 'unsafe-eval' 'unsafe-inline' *.accenture.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' *.accenture.com data:; connect-src 'self' *.accenture.com *.dialogflow.com
Cache-Control: private; max-age=31536000
Strict-Transport-Security: max-age=31536000;includeSubDomains
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
HTTPSampleResult fields:
ContentType: application/json; charset=utf-8
DataEncoding: utf-8
Request:
POST https://iapxaasbotbuildertest.accenture.com/channelService/channelWeb/619e81efe7
POST data:
%7B%22entry%22%3A%5B%7B%22sessionid%22%3A%22%22%2C%22tenantid%22%3A%22619e81efe7%22%2C%22botid%22%3A%229bb95dfba0%22%2C%22channel%22%3A%22Web%22%2C%22messaging%22%3A%5B%7B%22message%22%3A%7B%22messageId%22%3A123%2C%22text%22%3A%22hi%22%2C%22timestamp%22%3A1528967999992%7D%2C%22sender%22%3A%7B%22id%22%3A%22USR12%22%2C%22name%22%3A%22sylvin%22%7D%7D%5D%7D%5D%7D=
[no cookies]
Request Headers:
Connection: keep-alive
Origin: https://iapxaasbotbuildertest.accenture.com
Accept: application/json, text/plain, */*
Referer: https://iapxaasbotbuildertest.accenture.com/demo/webtest/?tenantID=619e81efe7&botID=9bb95dfba0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36 managedpc (Accenture)
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Content-Length: 362
Host: iapxaasbotbuildertest.accenture.com
Response data:
{ "errorcode": 9999, "errormessage": "Unexpected token % in JSON
at position 0" }
You should not be encoding your JSON payload, it should go as it is
So make sure to uncheck "Encode" box in your HTTP Request sampler
Also make sure to add HTTP Cookie Manager to your Test Plan as you seem to be receiving some cookies but not sending them back.
See REST API Testing - How to Do it Right article for more information if needed.

Angular2 accessing REST via Basic Auth throws "Response for preflight has invalid HTTP status code 401"

We are currently trying to access a REST-Endpoint of a Spring Boot app in an Angular2-App, but despite the fact that the Authorization header works in Postman (Authorization/Basic dXNlcjp1c2Vy, for a basic test user with the password user), it does not work when the app tries to access the REST-Endpoint.
The Spring-Security is configured as such:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication().withUser("user").password("user").roles("USER").and().withUser("admin")
.password("admin").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
http.csrf().disable();
}
}
The angular app asks for credentials before making the first request, like so:
loginTest() {
let headers: Headers = new Headers({'Content-Type': 'application/json', 'Accept': 'application/json'});
headers.append('Authorization', 'Basic ' + window.btoa(this._username + ':' + this._password));
console.log(headers);
return this.http.get('http://localhost:8080/', {headers: headers})
.map((res:any) => res.json);
}
With localhost:8080 being the Spring Boot app.
We already tried adding Content-Policy tags because there were similar problems with an earlier project, like so:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'self';
connect-src 'self' http://localhost:3000/ http://localhost:8080/ ws://localhost:3000/; img-src 'self' data:;
style-src 'unsafe-inline' 'self'; font-src 'self'"/>
but that didn't work either.
The error we get:
XMLHttpRequest cannot load http://localhost:8080/. Response for preflight has invalid HTTP status code 401
When looking at the request via Chrome, this is the Response:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Set-Cookie: JSESSIONID=4659A74A950FE6C99948D8F4CB245E27; Path=/; HttpOnly
WWW-Authenticate: Basic realm="Realm"
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: accept, authorization, content-type
Access-Control-Allow-Credentials: true
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Mon, 04 Jul 2016 07:54:30 GMT
I don't see what the Angular2-App is doing different when compared to PostMan here.
I think that your problem is related to CORS. Postman is a chrome plugin so it has the permission to execute CORS requests. It's not the case of your Angular application: it's more restricted.
See this question:
how Postman send requests? ajax, same origin policy
In the case of Angular, you need to handle CORS. You have a preflighted request (OPTIONS) that is sent before sending the actual request. I think that in your case, credentials aren't sent into this preflighted request so the server can't authenticate it and returns a 401 status code. This prevents from executing the target request.
I see two solutions:
Use the withCredentials parameter to true (available in Angular2 from RC2)
this.http.get('http://...', { withCredentials: true })...
Only check security on target requests and not on preflighted ones. It's a configuration to do on the server side.
See these articles for more details:
http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
http://restlet.com/blog/2016/09/27/how-to-fix-cors-problems/

Spring Session 1.0.0.M1 cookie domain attribute

I have integrated Spring Session with Redis into my SpringBoot app. It seems that all works well except the cookie domain attribute. I just found how to set the cookie session domain attribute for in tomcat i.e. method "setSessionCookieDomain", but that does not work. for example.
I had configured domain attribute in the context of the tomcat for example the domain attribute of the cookie.
#Bean
public TomcatContextCustomizer tomcatContextCustomizer() {
System.out.println("TOMCATCONTEXTCUSTOMIZER INITILIZED");
return new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.addServletContainerInitializer(new WsSci(), null);
context.setUseHttpOnly(true);
context.setPath("/");
context.setSessionCookiePath("/");
context.setSessionCookieDomain(".127.0.0.5");
// context.setSessionCookieDomain(".localhost");
// context.setSessionCookieDomain(".test.blabla.com");
}
};
}
When i open the https trace in wireshark and click follow ssl stream, here is what i get. All other attributes are listed except the domain. So my question is how do I set the domain attribute correctly in Spring Session 1.0.0.M1, Does spring session somehow override the tomcat context?
GET / HTTP/1.1
Host: 127.0.0.5:8888
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Lang: keep-alive
: keep-alive
: keep-alive
: keep-alive
: keep-alive
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-Content-Security-Policy: script-src 'self'; object-src 'self'
Content-Security-Policy: script-src 'self'; object-src 'self'
X-WebKit-CSP: default-src 'self'
X-Application-Context: application:Production
Set-Cookie: SESSION=5d0a738f-f011-4e43-a1ee-d691b8eba94c; Path=/; Secure; HttpOnly
Content-Type: text/html;charset=UTF-8
Conten10:01:27 GMT
10:01:27 GMT
10:01:27 GMT
10:01:27 GMT
10:01:27 GMT
<!DOCTYPE html>
Thanks for bringing this up. Spring Session should allow configuring the domain via the SessionCookieConfig but doesn't. I have created gh-87 to address this.

Can't disable same origin policy on nginx

I need to disable the same origin policy on the server. Just as a background: I have verified that everything is working by starting chrome with the disable web security flag. Everything works as expected.
Here's what I have done on the nginx side:
upstream phpfcgi {
server unix:/var/run/php5-fpm.sock; #for PHP-FPM running on UNIX socket
}
server {
listen 80;
root /var/www/yammi2;
index index.html index.php index.htm;
server_name myserver.ch;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Content-Type,accept,x-wsse,origin';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
# strip app.php/ prefix if it is present
rewrite ^/app\.php/?(.*)$ /$1 permanent;
location / {
index app.php;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass phpfcgi;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
When I then do curl call: curl -I myserver.ch, I get the following result:
HTTP/1.1 302 Found
Server: nginx/1.1.19
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.3.10-1ubuntu3.9
Set-Cookie: PHPSESSID=gvcl3v533ib91l2c6v888gl9d3; path=/
cache-control: no-cache
date: Fri, 10 Jan 2014 07:01:18 GMT
location: http://myserver.ch/admin/restaurant
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type,accept,x-wsse,origin
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
so at least it seems that the headers are set correctly, yet the result when I make the ajax call:
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 500 (Internal Server Error) jquery-2.0.3.js:7845
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 Origin http://localhost is not allowed by Access-Control-Allow-Origin. jquery-2.0.3.js:7845
XMLHttpRequest cannot load http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8. Origin http://localhost is not allowed by Access-Control-Allow-Origin. overview.html:1
I'm a bit confused by the "Internal Server Error", but I figured since it works with the flag, this has to be something to do with same origin.
The server application is a symphony app. I hope I haven't missed anything. Any idea how to fix this? Or even how to debug it?
Maybe one last snipped, here is how I make the call (again, shouldn't be the issue, because with the disable security flag it works as expected):
$.ajax({
url: url,
headers: {"x-wsse": getWsseHeader()},
beforeSend: function (request) {
request.setRequestHeader("x-wsse", getWsseHeader());
},
success: function() {
},
error: function(error) {
console.log(error.statusText);
}
});
Change this line
add_header Access-Control-Allow-Origin *;
as
add_header 'Access-Control-Allow-Origin' '';

Resources