Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Send battery level to JS #48

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Krisell
Copy link
Contributor

@Krisell Krisell commented Jan 20, 2020

I know you are working on a JS API, and I'm not expecting this to be merged. I'm simply proposing that receiving battery level information will be part of this API, and this PR is one way of fetching this.

To read the battery-level, the used web page need to define a window.SEB = {}, and then poll window.SEB.battery with a reasonable interval to see if battery data has been received.

I know you are working on a JS API, and I'm not expecting this to be merged. I'm simply proposing that receiving battery level information is part of this API, and this PR is one way of fetching this.

To read the battery-level, the used web page need to define a `window.SEB = {}`, and then poll window.SEB.battery with a reasonable interval to see if battery data has been received.
@Krisell Krisell closed this Jan 8, 2021
@danschlet
Copy link
Member

Hi Martin,
I now revisited your proposal and I actually implemented experimentally the first functionality of the new Javascript API in the iOS beta version (as there I have WKWebView mostly integrated). I started with an alternative for transmitting the Browser Exam and Config Key (BEK/CK), as in WKWebView it isn't possible to modify headers of all HTTP requests. What do you think about this first try for the API and especially the method for the BEK and CK? (Btw. there's now also a public TestFlight link to get iOS beta versions: https://testflight.apple.com/join/egxLmc4j).

I first should focus on finalizing the WKWebView implementation, releasing the iOS version (as there some other issues addressed) and merging the code into the macOS version. But I will definitely implement such a battery level feature (maybe in addition als a callback function, so polling wouldn't be necessary).

Here the info for the iOS beta (which you probably already got):

New in build 12917:

  • New SEB Javascript API exposes 3 variables:
  1. SafeExamBrowser.security.browserExamKey
  2. SafeExamBrowser.security.configKey
    which are the BEK and CK hashed with the URL of the page. The keys are identical to the ones send in the HTTP request header when UIWebView is used. Use this new JS API in an assessment web app with BEK/CK
    and WKWebView. Also set the key browserWindowWebView to the policy "Prefer Modern" (value 3).
  3. SafeExamBrowser.security.appVersion with format appDisplayName_iOS_versionString_buildNumber_bundleID.

New in build 12865:

  • Added first support for modern WebKit browser engine (WKWebView). The modern WKWebView currently doesn't support URL content filters (Network > URL Filter > Filter Embedded Content), embedded server certificates and certificate pinning (Network > Certificates > Pin Certificates) and sending the Browser Exam and Config Key in HTTP headers (Exam Session > Use Browser & Config Keys). If one of these settings is enabled, the classic WebView is used in the Automatic policy. Prefer Modern ignores the 'Use Browser & Config Keys' option in new tabs on a different server or generally.
  • The default setting for "Select Browser Engine Policy" (key browserWindowWebView), "Prefer Modern in New Tab+Different Host", ensures that you still can use testing systems/LMS like Moodle which use the Browser Exam/Config Key test for SEB connecting to the exam, but webpages opened in new tabs, which have another host than the exam system open in WKWebView.
  • From iOS 14.3, WKWebView supports access to the camera/microphone via WebRTC, which is needed for web-based remote proctoring or video conferencing solutions.

Cheers, Daniel

@Krisell
Copy link
Contributor Author

Krisell commented Apr 9, 2021

Thank you for the feedback and I'm glad to hear of the new additions. I looked quickly at the code and some small questions/comments:

  • It might be safer to add SafeExamBrowser explicitly to the window object, window.SafeExamBrowser = ... than implicitly using var in the global context, but it's probably equivalent.

  • Any web site that already puts a SafeExamBrowser property on the window object will be broken. Chances for this are very low, except perhaps for systems integrating with custom versions of SEB or similar, and it's reasonable that they will have to look out for this, but perhaps it should be mentioned in docs somewhere. Using SafeExamBrowser is much better than the SEB I proposed, although in my original PR I let the web application be responsible for initiating the object.

  • I'm not sure why you define the properties as functions and new these up, instead of just using object literal syntax, but I guess there is a specific reason for this?

  • Am I correct to think that an XSS vulnerability could now steal valid CK and BEK values, which was not possible before (since making an XHR request to a malicious server would send another BEK based on that url)?

@danschlet
Copy link
Member

danschlet commented Apr 9, 2021

I'm really a looser when it comes to JS. I actually did some internet search and trial-and-error to achieve what I wanted (until it worked somehow). But I was inspired by the Smarter Balanced (SB) exam consortium's Secure Browser API (which I would like to support in a later version of SEB as well). I kinda like that they expose a global object SecureBrowser and use such namespaces (or however that would be called in JS) like .security. I would for example imagine to use something like SafeExamBrowser.system.batteryLevel and SafeExamBrowser.system.batteryCharging. I think it might make sense to provide a lot of functionality with this JS API over time. There should also be functions like void SafeExamBrowser.security.lockDown (boolean enable, function onSuccess, function onError) similar to the SB API. I didn't try it yet, but I assumed this would work with how I set up the properties as functions (like in this example).

  • I think I don't mind if a website already using a SafeExamBrowser property would be broken, if they want to be compatible with SEB, they should change that...
  • I also wasn't sure about how secure the keys would still be with this method. The real BEK and CK hashes are still SHA256 hashed with the URL of the page they are being injected into (exactly the same way as the ones in the headers), so it still should be quite complicated to get the real values. But I guess you mean that the XHR request would contain the same hash of the BEK as the originating page URL? I actually think that only the initial page loading request will contain the injected JS properties, as in WKWebView no event handlers are called for XHR requests. That's also why it's impossible to modify all HTTP requests (also not the ones for embedded resources).

Thanks for your input, that's highly appreciated!

@danschlet danschlet reopened this Apr 9, 2021
@Krisell
Copy link
Contributor Author

Krisell commented Apr 9, 2021

There are definitely many different ways to achieve the same thing in JS, and it really doesn't matter except for the developer (only you in this case). The simplest way to achieve what I think you're after is something like the following:

window.SafeExamBrowser = {
  version: 'app-version',
  system: {
    batteryLevel: 'value that is updated, or some callback based solution to avoid polling'
  },
  security: {
    browserExamKey: 'value',
    configKey: 'value',
    lockDown: function (enable, onSuccess, onError) {
      // pass message to SEB and read response, and trigger correct callback
    }
  }
}

Then the web app can call SafeExamBrowser.system.batteryLevel or SafeExamBrowser.security.lockdown(true, successHandler, errorHandler).

But of course, if there is a standard to follow, you should conform to that.

@Krisell
Copy link
Contributor Author

Krisell commented Apr 9, 2021

For the XSS question, XHR doesn't have to be involved. If the exam portal page has an XSS vulnerability (which is of course their responsibility to prevent), then a student could read the BEK and CK and even post to themselves inside of the system (or send away using XHR), but of course if the URL or config file is unique to the session, it probably doesn't do any harm.

@danschlet
Copy link
Member

Your JS code definitely looks cleaner, I will try it like that, although I thought that I tried it similarly and that it didn't work (maybe the injection into the WKWebView behaves differently as if it would be part of the webpage code?).

I guess I didn't understand that XSS attack scenario fully. The thing is: You cannot derive the original BEK/CK values by just getting the hashes which are exposed in a webpage. Those are the hashes of the BEK/CK sha256 with the page URL. You cannot derive the original value of one component of a hashed value even if you have the other component (the URL). You could only generate fake values for SafeExamBrowser.security.browserExamKey and SafeExamBrowser.security.configKey
if you have the original BEK/CK values or if your code is running continuously on every rendered page.

@danschlet
Copy link
Member

I had to change the API methods for reading the Browser Exam and Config Keys, as I wasn't able to inject the hash values into web pages so they could be read reliably while the page is loaded (after some changes it worked on the first load of the page, but not when reloading the page). The reason was that the injection from the native code with evaluateJavaScript() is asynchronous. Therefore now first a function must be called and the values can be read in a callback function (see description below).

I hope that this will work in real web applications. I already found out that it seems to be quite complicated to call JS/read JS objects from PHP code, I will discuss how feasible this is for example in the SEB Moodle plugin.

New in build 12996:

  • Changed method to query the Browser Exam and Config Key (BEK/CK) with the new SEB JavaScript API:
  1. void SafeExamBrowser.security.updateKeys(function callback)
    This function needs to be invoked first (for example in ). You should indicate a callback function (function name without the parentheses ()) as the function callback parameter, which will be called by SEB after updating the BEK/CK variables below (the update is asynchronous, but in the callback function it's safe to read the variables).
  2. SafeExamBrowser.security.browserExamKey
  3. SafeExamBrowser.security.configKey
    which are the BEK and CK hashed with the URL of the page. The keys are identical to the ones send in the HTTP request header when UIWebView is used. Use this new JS API in an assessment web app with BEK/CK
    and WKWebView. Also set the key browserWindowWebView to the policy "Prefer Modern" (value 3).
  4. SafeExamBrowser.version (new) with format appDisplayName_iOS_versionString_buildNumber_bundleID. This variable is set regardless if updateKeys() is called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants