Re: Malicious EPUBs, reading-system integrity (content sandboxing) epubtestuite #160

117 views
Skip to first unread message

Daniel Weck

unread,
Feb 10, 2014, 10:34:27 AM2/10/14
to readi...@googlegroups.com, epub-testsu...@googlegroups.com
I wrote an additional test for epub-testsuite (#160), comments welcome.
This is work in progress, in separate GitFlow "feature" branch:

https://github.com/mgylling/epub-testsuite/tree/feature/RS_integrity/content/30/epub30-test-0160

Notes:

Both ReadiumJS viewer and Chrome-extension fail.

Readium-Launcher_OSX passes (I think that Readium-Launcher_iOS passes as well, but I need to double-check). iBooksX passes (not tried iBooks-iOS yet).

Regards, Daniel

On Wednesday, February 5, 2014 12:54:08 PM UTC, Daniel Weck wrote:
Dear all,

in the case of Readium-JS-viewer (i.e. the cloud reader, I have not
checked the Chrome extension yet), the content-iframes reference EPUB
documents that have the same origin as the host application. In other
words, the HTML wrapper that provides the "page" layout for one or two
iframes side-by-side (+ app "chrome" / UI menus, etc.) is exposed to
potential security threats. For example, an EPUB can easily access and
modify the host/shell HTML markup, invoke Javascript code, corrupt the
e-book library, steal sensitive user data, etc.


window.parent.document.body.innerHTML = "HACKED !!";


HTML5 provides the iframe@sandbox attribute, so we could easily
restrict our content iframes with:

<iframe sandbox="allow-scripts">

(and perhaps "allow-forms" as well)

We should obviously disable "allow-top-navigation" (by omission in the
@sandbox attribute).

We do not want "allow-same-origin", as that's the problem we are
trying to fix in the first place.


...Unfortunately, the Readium framework NEEDS "allow-same-origin" in
order to (1) inject the window.navigator.epubReadingSystem, (2) apply
the installHookFunction, and (3) access iframe.contentDocument from
various places in our code.

Worth noting: the iframe@sandbox attribute values are taken into
account by the web-browser when the iframe@src is SET (i.e. when the
hosted document is loaded), so we cannot temporarily change the
sandboxing conditions just to execute (1) (2) and (3). At least,
that's the behaviour I observed when I experimented with Safari.


So, another option is to serve the EPUB content documents from a
different origin than the HTML that hosts the iframes. As it turns
out, that's typically what a native ReadiumSDK launcher does (e.g. OSX
app-bundle file:// URL for reader.html, or special readium-sdk:// URL
scheme, versus the http://127.0.0.1 content URLs). The problem is that
the aforementioned requirements (1) (2) and (3) may not be functioning
properly, I have not checked yet (baring in mind the possible
inconsistencies between regular web browsers and UIWebView / embedded
WebKit control).


I'm not sure how high this issue is on the priority list, but I
thought I'd start a conversation on the mailing-list. I hope that a
more web-savvy dev can take ownership ;)


Cheers, Daniel

Daniel Weck

unread,
Feb 10, 2014, 3:37:41 PM2/10/14
to readi...@googlegroups.com, epub-testsu...@googlegroups.com


On Monday, February 10, 2014 3:34:27 PM UTC, Daniel Weck wrote:
I wrote an additional test for epub-testsuite (#160), comments welcome.
This is work in progress, in separate GitFlow "feature" branch:

https://github.com/mgylling/epub-testsuite/tree/feature/RS_integrity/content/30/epub30-test-0160

Notes:

Both ReadiumJS viewer and Chrome-extension fail.

Readium-Launcher_OSX passes (I think that Readium-Launcher_iOS passes as well, but I need to double-check). iBooksX passes (not tried iBooks-iOS yet).

Unfortunately, ReadiumLauncher-iOS fails the test

ReadiumLauncher-OSX passes the test thanks to the fact that the native application serves the reader.html "bootstrapper" (thin HTML wrapper) from file://APP-BUNDLE, whereas the iframe'd EPUB content is served from a different origin (via the readiumsdk://PACKAGE_UID URI scheme).

ReadiumLauncher-iOS fails the test because both reader.html and the EPUB content documents are served from the same origin: http://127.0.0.1:PORT   This could easily be fixed though (perhaps try a different port for reader.html? or serve it via file://APP-BUNDLE, just like the OSX app?).

I'm on my way to test ReadiumLauncher-Android...

Daniel Weck

unread,
Feb 10, 2014, 4:03:27 PM2/10/14
to readi...@googlegroups.com, epub-testsu...@googlegroups.com
[removed epub-te...@googlegroups.com]

I am afraid that ReadiumLauncher-Android also fails the test.
It seems that the EPUB content documents are served from file:///android_asset/readium-shared-js/PATH/TO/SPINE_ITEM.xhtml
I imagine that reader.html is also served with the file:// URI scheme.

Regards, Daniel

Daniel Weck

unread,
Feb 10, 2014, 7:14:29 PM2/10/14
to readi...@googlegroups.com, epub-testsu...@googlegroups.com


On Monday, February 10, 2014 8:37:41 PM UTC, Daniel Weck wrote:
ReadiumLauncher-OSX passes the test thanks to the fact that the native application serves the reader.html "bootstrapper" (thin HTML wrapper) from file://APP-BUNDLE, whereas the iframe'd EPUB content is served from a different origin (via the readiumsdk://PACKAGE_UID URI scheme).

I made another test to validate my assumption: if reader.html is served with (let's say) readiumsdkreader:// origin (instead of file://), and if the iframe'd EPUB documents are served as usual from (let's say) readiumsdkepub://, then the application's Javascript is not allowed anymore to inject content into the iframe (as I was expecting). The file:// URI scheme therefore appears to confer special _unidirectional_ cross-origin rights, granting the app layer rights to modify the iframe'd DOMs (whatever the source domain), but not vice-versa.

Daniel

Daniel Weck

unread,
Feb 11, 2014, 4:37:18 PM2/11/14
to readi...@googlegroups.com, epub-testsu...@googlegroups.com
There's now a shared Google doc for further brainstorming:


Edit at will.

Daniel Weck

unread,
Mar 11, 2014, 3:13:03 AM3/11/14
to readi...@googlegroups.com, Daniel Weck, epub-testsu...@googlegroups.com
Hello Shane, I have not tried your branch yet, but based on your explanation I suspect that reader.html is not served with high-enough cross-origin privileges compared with the iframe's document. Ideally, you would feed reader.html (+ all directly-associated files) to the UIWebView via file:// (i.e. local filesystem APP-BUNDLE path). Then, serve the EPUB content from http://127.0.0.1:PORT, or via NSURLProtocol, or a combination of both (which is what LauncherOSX does). As a result, the app code (in reader.html) will successfully be able to inject "stuff" into the iframe, and conversely the iframe-hosted document will fail to access its parent context (which is exactly the desired effect).

Note that I also toyed with the idea of using two different readium-sdk:// URI schemes, to no avail. See email discussion here:


Regards, Daniel


On Tuesday, March 11, 2014 12:54:54 AM UTC, Shane Meyer wrote:
I've checked in a feature branch in the iOS launcher to play around with this:

    feature/nsurl-protocol

Instead of serving everything from 127.0.0.1, reader.html and friends (readium-shared-js, etc.) are served via NSURLProtocol (which the app intercepts and provides content for directly), whereas the EPUB contents are served from 127.0.0.1 (where SimpleHTTPServer provides the content).

Things don't work, which I guess is to be expected, although I'm not as familiar with the inner workings of the JavaScript code to know exactly why things are breaking down.  The content is getting fetched and served via NSURLProtocol and SimpleHTTPServer, and the UI displays a toolbar with the correct pagination info (demonstrating JavaScript events correctly bubbling up to the native layer), but the content in the web view is blank.

One change I made in media_overlay_data_injector.js is not checked in, but here's the diff (old on left):


This was to work around $iframe[0].contentDocument being null (just testing simple, non-MO documents)... just a stopgap.

Boris, Daniel, anyone else, please feel free to experiment to see if there might be a way to make this hybrid NSURLProtocol/SimpleHTTPServer work.

- Shane


--
You received this message because you are subscribed to the Google Groups "readium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to readium-dev...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply all
Reply to author
Forward
0 new messages