Heretic86 Posted April 7, 2021 Share Posted April 7, 2021 What I would like to do is to is to have a User Forum that allows Users to upload their own Javascript files that will run on other Users computers. I am aware of how dangerous that is. It can be done IF done properly. The User scripts are intended to be run ONLY inside a Sandboxed Iframe with very restrictive CORS policies in place. I have already done this. CORS and Sandboxing allows preventing all XMLHttpRequests / Fetch requests to external sites so there is much less chance of a Users computer being compromised or trying to download malicious packages. I take that back. There is ONE place they should be allowed to retrieve data from, which is a simple AJAX request to my server, which will be one page that serves up their scripts. I have run into an issue however. I need to be able to pass an HTTPONLY cookie through the AJAX request so that the User is able to use the Sandbox for its intended purposes. On my PHP side where the AJAX request is sent, I am not getting any cookie data sent from the Browser. Im not sure if I should turn off HTTPONLY on it for the CORS request tho. I am not sure where to even begin troubleshooting this. Could one of you very experienced people take a peek at my code and offer any advice as to why I am not able to read cookies on my XML Requests? --- Page where I am having trouble working within CORS Policies and still being able to read Cookies... https://www.webucate.me/cors_csp/ Data URL that I am trying to use AJAX to get data from (test json object, time + cookie with a value of 123456): https://www.webucate.me/cors_csp/jsondata.php Source Code: https://www.webucate.me/cors_csp/cors.zip Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/ Share on other sites More sharing options...
requinix Posted April 7, 2021 Share Posted April 7, 2021 1 hour ago, Heretic86 said: I need to be able to pass an HTTPONLY cookie through the AJAX request so that the User is able to use the Sandbox for its intended purposes. The whole point of an HttpOnly-flagged cookie is that you cannot read or write to it in code. It's right there in the name. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585633 Share on other sites More sharing options...
Heretic86 Posted April 7, 2021 Author Share Posted April 7, 2021 26 minutes ago, requinix said: The whole point of an HttpOnly-flagged cookie is that you cannot read or write to it in code. It's right there in the name. Well, according to the link to the following article, the "withCredentials" flag (XMLHttpRequest, credentials: 'include' in fetch()), you CAN have a cookie set with HTTPONLY and STILL send that cookie without allowing script access. It is an Exception to the HTTPONLY cookie can not be read by scripts rule. https://medium.com/@_graphx/if-httponly-you-could-still-csrf-of-cors-you-can-5d7ee2c7443 Quote Enter XMLHttpRequest XMLHttpRequest is a wonderful function of JavaScript that allows developers to interact with the server and allow for dynamic updates of a page without having to refresh the page. It makes for clean, flashy web apps. Below is the malicious website code with part of the JavaScript used to execute the attack: However, since it’s JavaScript, we should not be allowed via client-side script to access the cookie, according to the OWASP article on the subject. Normally this would be the case, but the XMLHttpRequest has a property called withCredentials. According to the article, the withCredentials property “Is a boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies or authorization headers”. So according to everything we have thus far, we can use session cookies programatically unless the HttpOnly flag is set, right? Wrong. There appears to be an exception to the client-side script access prohibition for XMLHttpRequest that will still allow you to access the session cookie even with the HttpOnly flag set as long as the withCredentials property is set to true. This means that we can still execute CSRF using a victims session cookie that is properly secured with the HttpOnly flag. So it isnt the HTTPONLY flag that is causing my issue. I am just not familiar enough with CORS setups. Anyway, as far as I can tell, it looks like there is an "Origin" header that is supposed to be sent. Obviously I havent set up my request to include the Origin header, and I think that *might* be why this isnt working? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585634 Share on other sites More sharing options...
requinix Posted April 7, 2021 Share Posted April 7, 2021 If you don't need to access the cookie in code and only care that it gets sent through the AJAX request, then yes: withCredentials would do it. Should be pretty easy to figure out whether that solves your problem. Without error messages or a set of failing request and response headers, there's not much else to do but guess at what's wrong... Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585635 Share on other sites More sharing options...
Heretic86 Posted April 7, 2021 Author Share Posted April 7, 2021 Request Headers: OPTIONS /cors_csp/jsondata.php HTTP/1.1 Host: www.webucate.me User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Access-Control-Request-Method: POST Access-Control-Request-Headers: content-type Origin: null DNT: 1 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Response Headers: HTTP/1.1 200 OK Date: Wed, 07 Apr 2021 08:44:44 GMT Server: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.4.11 X-Powered-By: PHP/7.4.11 Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Content-Type, Origin Access-Control-Allow-Methods: Content-Type, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Authorization, Allow, POST, OPTIONS Access-Control-Allow-Origin: https://www.webucate.me Access-Control-Max-Age: 1 Set-Cookie: TestCookie=123456; expires=Thu, 08-Apr-2021 08:44:44 GMT; Max-Age=86400; path=/; domain=www.webucate.me; secure; HttpOnly; SameSite=Strict Content-Length: 40 Keep-Alive: timeout=5, max=99 Connection: Keep-Alive Content-Type: application/json; charset=utf-8 Network Tab: Status - Not Allowed CORS Allow Origin Not Matching Origin Console.log says this: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.webucate.me/cors_csp/jsondata.php. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘https://www.webucate.me’). Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.webucate.me/cors_csp/jsondata.php. (Reason: CORS request did not succeed). --- The origin isnt being sent? How do I set this up to send the Origin? Since I have to now guess, can I blame it on COVID? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585637 Share on other sites More sharing options...
requinix Posted April 7, 2021 Share Posted April 7, 2021 You can't set the Origin, that's protected, so if it's sending "null" then that probably means you're not running from a suitable location. That aside, the cookie is SameSite=Strict, so if you're not running from www.webucate.me then you can't use it. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585649 Share on other sites More sharing options...
Heretic86 Posted April 7, 2021 Author Share Posted April 7, 2021 2 hours ago, requinix said: You can't set the Origin, that's protected, so if it's sending "null" then that probably means you're not running from a suitable location. That aside, the cookie is SameSite=Strict, so if you're not running from www.webucate.me then you can't use it. Even if the Iframe source is the same? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585652 Share on other sites More sharing options...
requinix Posted April 7, 2021 Share Posted April 7, 2021 Now I'm lost because I thought this was a CORS question. The Javascript code that is running and sending AJAX requests. Is it doing so from a document context of www.webucate.me or some other domain? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585653 Share on other sites More sharing options...
Heretic86 Posted April 7, 2021 Author Share Posted April 7, 2021 1 hour ago, requinix said: Now I'm lost because I thought this was a CORS question. The Javascript code that is running and sending AJAX requests. Is it doing so from a document context of www.webucate.me or some other domain? That is the intent. Its Iframed so the content can be posted on other websites. Iframe also allows Sandboxing the code, which if it comes from another domain, should be restricted access to the rest of the window and document content. And visa versa. Iframe keeps it as just a Container to prevent malicious code from compromising other sites too. It should prevent popups, accessing the rest of the document element, keystrokes when not focused, etc. The cookie is needed for connecting to the Users account to "like" or "share" or whatever. So yes. I know I set something up very wrong. I am not sure if it needs to be treated as samesite or none (which I have experimented with) but it doesnt seem to matter what I do, I dont see the Origin header being sent, and I am not sure why I cant get it to send. Even on Kubuntu Firefox running in VMware so totally different browser and machine. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585654 Share on other sites More sharing options...
requinix Posted April 8, 2021 Share Posted April 8, 2021 iframe or not, if your code is running on the same domain you're trying to send a request to then you don't "need" CORS, and the default behavior of browsers and servers should be fine... The same request and response you posted. That's the OPTIONS and, presumably, its reply, right? Because they say that the allowed origin is the exact same thing that the error message is complaining is not present. What are the headers from a failed AJAX request and response? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585655 Share on other sites More sharing options...
Heretic86 Posted April 8, 2021 Author Share Posted April 8, 2021 1 hour ago, requinix said: iframe or not, if your code is running on the same domain you're trying to send a request to then you don't "need" CORS, and the default behavior of browsers and servers should be fine... The same request and response you posted. That's the OPTIONS and, presumably, its reply, right? Because they say that the allowed origin is the exact same thing that the error message is complaining is not present. What are the headers from a failed AJAX request and response? Should be same as above: Console (Firefox): Access to fetch at 'https://www.webucate.me/cors_csp/jsondata.php' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://www.webucate.me' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. iframe.php:59 POST https://www.webucate.me/cors_csp/jsondata.php net::ERR_FAILED Network Request Headers: OPTIONS /cors_csp/jsondata.php HTTP/1.1 Host: www.webucate.me User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Access-Control-Request-Method: POST Access-Control-Request-Headers: content-type Origin: null DNT: 1 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Response Headers: HTTP/1.1 200 OK Date: Thu, 08 Apr 2021 02:03:52 GMT Server: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.4.11 X-Powered-By: PHP/7.4.11 Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Content-Type, Origin Access-Control-Allow-Methods: Content-Type, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Authorization, Allow, POST, OPTIONS Access-Control-Allow-Origin: https://www.webucate.me Access-Control-Max-Age: 1 Set-Cookie: TestCookie=123456; expires=Fri, 09-Apr-2021 02:03:52 GMT; Max-Age=86400; path=/; domain=www.webucate.me; secure; HttpOnly; SameSite=Strict Content-Length: 40 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: application/json; charset=utf-8 And finally, PHP source (simple test): <?php header("Content-Type: application/json; charset=utf-8"); header('Cross-Origin-Resource-Policy: same-site', false); header('Access-Control-Allow-Credentials: true', false); header('Access-Control-Allow-Headers: Content-Type, Origin', false); header('Access-Control-Allow-Methods: Content-Type, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Authorization, Allow, POST, OPTIONS', false); header('Access-Control-Allow-Origin: https://www.webucate.me', false); header('Access-Control-Max-Age: 1', false); header('X-Frame-Options: SAMEORIGIN' ); $cookie = (isset($_COOKIE['TestCookie'])) ? $_COOKIE['TestCookie'] : 'NoCookies'; $time = time(); $msg = array("time" => $time, "cookie" => $cookie); echo json_encode($msg); setcookie('TestCookie','123456', [ 'expires' => time() + 86400, 'path' => '/', 'domain' => 'www.webucate.me', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict', ]); ?> I know the first thing you will look at, Allow Origin header. But when I try to disable that, this is what comes up in the console: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.webucate.me/cors_csp/jsondata.php. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). So its like it requires it but I cant implement it. If you want, all the source code is in the zip file in the first post... Thank you, by the way... Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585656 Share on other sites More sharing options...
requinix Posted April 8, 2021 Share Posted April 8, 2021 I'll ask once again because I'm pretty sure the correct answer is not what you've been saying: Is the Javascript code running from a document context of www.webucate.me or something else? Are you perhaps running it as a local file? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585664 Share on other sites More sharing options...
Heretic86 Posted April 9, 2021 Author Share Posted April 9, 2021 11 hours ago, requinix said: I'll ask once again because I'm pretty sure the correct answer is not what you've been saying: Is the Javascript code running from a document context of www.webucate.me or something else? Are you perhaps running it as a local file? Nope. I am sure. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585672 Share on other sites More sharing options...
requinix Posted April 9, 2021 Share Posted April 9, 2021 7 hours ago, Heretic86 said: Nope. I am sure. I ask because various resources I can find all say that Origin: null means the AJAX request is coming from a file:// location. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585679 Share on other sites More sharing options...
Heretic86 Posted April 9, 2021 Author Share Posted April 9, 2021 2 hours ago, requinix said: I ask because various resources I can find all say that Origin: null means the AJAX request is coming from a file:// location. I saw the same thing, but it is not. Its hosted on a web server. Granted it is a Localhost server, but it still uses an IP, hell, it even has to route through my VPN IP to get back to itself. I have even gone so far as to set up another Domain Name (hosts file) and make my requests that way so the Iframe part of the page is coming from a different domain and it still doesnt work. I just dont have any idea where I am doing it wrong! Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585680 Share on other sites More sharing options...
Heretic86 Posted April 10, 2021 Author Share Posted April 10, 2021 I am close to giving up on this since I feel like no one has even looked at the code... I just dont get why I cant send the cookie even though I am sending what I think is all the proper credentials with the request... const loadLocalXMLCookie = async function(data = { action : 'getDisplayName' } ) { let url = 'jsondata.php'; const response = await fetch(url, { method: 'POST', mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, redirect: 'follow', referrerPolicy: 'same-origin', body: JSON.stringify(data) }) Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585711 Share on other sites More sharing options...
Heretic86 Posted April 11, 2021 Author Share Posted April 11, 2021 (edited) Ok, let me try to explain my goal again. I want users to upload their own scripts that they can run in an iframe. Since that is pretty dangerous to other users, I think the best thing to do is sandbox scripts in an iframe. Perhaps I am wrong. And I can not simply say "never let users run their own scripts" because it directly contradicts my goals. Running user scripts safely is the MAIN GOAL. I think it is a good idea to also use CORS so that those scripts do not try to make calls to anything EXCEPT one specific location on my server where their scripts are loaded from. This includes Inline Scripts. To load those scripts, I need to be able to send an Ajax / Fetch request to that specific page to load their scripts, which requires a cookie to access which scripts are theirs, and ultimately edit and save those scripts. Since other users will run those scripts, the Cookie has to be HTTPONLY so one user can not read another users cookies. But when I send the Ajax / Fetch request to get their data, I cant read their cookie! I think it is something either in CORS or in the way that I making my javascript requests. Is this a better explanation? Edited April 11, 2021 by Heretic86 Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585732 Share on other sites More sharing options...
requinix Posted April 12, 2021 Share Posted April 12, 2021 A better explanation, but that isn't the problem. As I see it, you're trying to walk the line between security and no security, and you keep falling over onto one side or the other. There's only one thing I can think of: a subdomain. Your sensitive cookies are restricted to the main domain, user scripts run out of the subdomain, and the main domain does CORS as needed. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585747 Share on other sites More sharing options...
kicken Posted April 12, 2021 Share Posted April 12, 2021 This may be your issue MDN: <iframe>: The Inline Frame element Quote ... allow-same-origin: If this token is not used, the resource is treated as being from a special origin that always fails the same-origin policy (potentially preventing access to data storage/cookies and some JavaScript APIs). Try adding allow-same-origin to your sandbox attribute. Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585748 Share on other sites More sharing options...
Heretic86 Posted April 12, 2021 Author Share Posted April 12, 2021 3 hours ago, kicken said: This may be your issue MDN: <iframe>: The Inline Frame element Try adding allow-same-origin to your sandbox attribute. I will put it back in. I had it in there initially. And this is posted above, but this is the error Im getting now: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.webucate.me/cors_csp/jsondata.php. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘https://www.webucate.me’). This is my Content Security Policy: <?php header('Cross-Origin-Resource-Policy: same-origin', false); header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); function csp_policy(){ header("Content-Security-Policy: " . "default-src 'none';" . "sandbox allow-scripts;" . "base-uri 'none';" . "img-src 'self';" . "style-src 'self' css/*;" . "navigate-to 'none';" . "form-action 'none';" . "script-src 'report-sample' 'unsafe-inline' 'unsafe-eval' " . "https://" . $_SERVER['SERVER_NAME'] . "/cors_csp/js/video.js " . "https://" . $_SERVER['SERVER_NAME'] . "/cors_csp/jsondata.php " . "data: ;" . "worker-src 'self';" . "media-src https://" . $_SERVER['SERVER_NAME'] . "/cors_csp/playvideo.php;" . "connect-src https://" . $_SERVER['SERVER_NAME'] . ";" . "child-src 'none';" . "report-uri https://" . $_SERVER['SERVER_NAME'] . "/cors_csp/csp_violation/index.php;" . "report-to {\"group\" : \"default\", \"max_age\" : 1800, \"endpoints\" : [{ \"url\" : \"https://" . $_SERVER['SERVER_NAME'] . "/cors_csp/csp_violation/index.php\"}]};" . ""); } ?> What I would really like is a SIMPLE EXAMPLE that WORKS. So, Sandboxed Iframe, XHR or Fetch, and PHP must to read a cookie. I just cant seem to get a handle on the numerous headers that are all involved, and despite all the googling, I cant find any real working examples intended for demonstration purposes. Think you could help with that? Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585753 Share on other sites More sharing options...
Solution kicken Posted April 12, 2021 Solution Share Posted April 12, 2021 I downloaded your code and added that attribute and it seemed to be working fine after that. You need to add it to both the CSP and the iframe's sandbox attribute. 1 Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585755 Share on other sites More sharing options...
Heretic86 Posted April 12, 2021 Author Share Posted April 12, 2021 Hot Dog! (*bark bark*) It works now! Thank you very much! I knew it would be one small thing that I had missed! Ive been banging my head against a wall for weeks on this, and you got it fixed! Quote Link to comment https://forums.phpfreaks.com/topic/312435-cors-and-sandboxing-user-javascript-and-cookies/#findComment-1585781 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.