xAPI Security Issues

497 views
Skip to first unread message

Sam Ellis

unread,
Oct 27, 2016, 12:21:33 PM10/27/16
to xAPI-Specification
Hi all,

I've been reading through the xAPI spec and truly believe it's a brilliant idea.  However, as I see it, there's a big security hole: the credentials used in the request will (in some cases) be placed in Javascript and are therefore easy to steal.  There are 2 issues with this:
1. Data integrity - anyone with the credentials can fabricate statements, and abuse the system.
2. Data privacy - my biggest concern - anyone with the credentials can get all statements from the system, see all users, activities and potentially very personal information.  Huge data privacy implications.

An extreme example - a standalone Javascript course embedded on a public web page that reports back to an LRS.  A user could steal these credentials and submit their own GET request to [LRS]/xAPI/statements to retrieve a list of statements (including actors) within the system.  

The only viable solution I can see is to create a new user/client on the LRS for each user of the course, and ensure strict permissions so they cannot access statements of any other agent.  But does this go against the xAPI spec, where the LRS is simply a data store, and not concerned with user management?  There's a good chance I'm overlooking something here...

I've seen some thread around this, including this one, but nothing that comes to a conclusion.  Does anyone have any thoughts?

Thanks in advance,

Sam

Dennis Hall

unread,
Oct 27, 2016, 12:27:09 PM10/27/16
to Sam Ellis, xAPI-Specification

The spec. does not describe where to obtain your credentials from, nor in what format to store your credentials (beyond encoding).

 

If you hard code credentials in a file, shame on you. When we authored the spec, we did not task ourselves with tell programmers how to do their job.

Any JS file you see on the internet that has credentials hardcoded are only doing this to provide an example of a set of credentials, not to instruct people to hard code credentials.

--
You received this message because you are subscribed to the Google Groups "xAPI-Specification" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xapi-spec+...@adlnet.gov.

Andrew

unread,
Oct 27, 2016, 1:11:40 PM10/27/16
to xAPI-Specification, sam.geor...@gmail.com
Hi Sam, 

Take a look at this Stack Overflow question i answered a while back. It got a few up votes so hopefully you'll find it helpful too: http://stackoverflow.com/a/28296859/4214694

Andrew

Sam Ellis

unread,
Oct 28, 2016, 10:27:24 AM10/28/16
to xAPI-Specification, sam.geor...@gmail.com
Thanks Andrew, that gives me something to go on.  As you say, any client side code will be vulnerable (even SCORM) so it's all about how important security is to you.  Ultimately the data privacy issue is a big concern for us, but I guess the solution here lies in restricting statement retrieval for exposed credentials.  The downside of this is that the course will not have access to the learner's history (apart from what is stored in the state API)...

Dennis: hardcoded or not, the LRS credentials are very easily compromised in client side code/communication.  There's no way to overcome this, but as Andrew's post points out, there are ways to limit the damage.  My worst case scenario of a standalone course embedded on a public web page is something that xAPI makes possible, and will happen, so it's not unreasonable to expect some sort of guidelines or best practices around damage limitation with xAPI.

Rustici's own TinCanJS Library suggests hardcoding credentials in Javascript.  Of course we can do things like obfuscation or fetching credentials from some secure service - but at the end of the day it will never be secure in Javascript.

Regards,
Sam

Dennis Hall

unread,
Oct 28, 2016, 11:04:26 AM10/28/16
to Sam Ellis, xAPI-Specification

I agree Sam:

 

Using JavaScript will not be secure (hardcoding-or-not).

I use PHP scripting to generate all dynamic transmitted data.

 

To follow up on your “Rustici's own TinCanJS Library suggests hardcoding credentials in Javascript.”

From Rustici: “TinCanJS doesn't have opinion on how you get your credentials in”.

 

Best Regards,

Dennis Hall

--

J. Pablo Caballero

unread,
Oct 29, 2016, 5:52:40 AM10/29/16
to xAPI-Specification
Hello Sam,

Security and privacy are indeed very important, and as a European, it's something that I keep in the forefront of my mind for myself and my clients (I say that because all this is somewhat more strictly regulated here in Europe)

The fact that the 'Learning Record Provider' is the 'client side' in an xAPI environment (the LRS being the server), doesn't mean that the statement creation and sending has to be done from client-side javascript (the code executed in the browser). In fact, I think that the recommended way (somebody correct me if I'm wrong) is, as Dennis said, to do that from the server side. In most cases, html/js content will be served from a web portal (some site that authenticates users and controls access to the content). In that case, the client side content can interact with the server side in a fairly opaque way (user credentials don't even need to be passed to the client side javascript, and much less the LRS credentials), and the server side component of that LRprovider can generate and send the statements. This protects the LRS credentials from course users.

But let's  look at your worst case scenario and main concerns associated with it:
    • "a standalone Javascript course embedded on a public web page that reports back to an LRS"
    • possibility of statement fabrication (data integrity abuse)
    • access to ALL LRS data (data privacy breach)

    If you had such a course, out in the open... how would you identify users? Maybe:

    1. you don't, because you only want to see general patterns in the usage of the course, but then all reporting is totally anonymous (your client side js makes up the actor). In this case, yes, they could fabricate statements and send them... but it's hard to imagine that someone would take the time to try to do this. In reality, pretty much all the users of such a course will take a look at the content and move on. As for accessing all LRS data... there wouldn't be any Personal Identifiable Information (in terms of European data protection policies, so no data privacy concerns).
    2. users self-identify: your course pops-up a box to ask for their email address. This should NOT be done. Any serious xAPI solution just cannot rely on this. You can assume that many are going to type fake addresses anyway.⋅
    3. there's some mechanism for user identification/authorization: then, you have a server side component somewhere. The code that communicates with the LRS (and the LRS credentials) should be in the server, and never reach the client. Users cannot generate statements directly, and they can't get to the LRS. They might try to trick your server-side component with fake data so it sends fake statements, but you can make it sufficiently hard so it's not worth doing at all. It's all about how you architect your software.

    As for your biggest concern, "anyone with the LRS credentials can get ALL the data", no, that's not necessarily true at all:

    1. An LRS can restrict what can be done with a set of credentials, (e.g. LearningLocker). Maybe the set of credentials allows to send statements into the LRS, but nothing else.
    2. With web server configuration and network configuration, you can restrict HTTP Methods and IPs ... so you can only allow a certain IP of range of IPs to access the LRS to GET things
    3. If you have a server-side component... you can control everything: it would be your server-side component the one who would access the LRS and then filter/restrict/anonimize the data that it sends to the client.

    So, in general, I think that one should avoid at all costs having LRS credentials in client-side javascript, but if there's a particular case where you need to do that... then probably it doesn't  matter that people create fake statements, and it doesn't make sense to let them GET data from the LRS anyway.

    One thing is the xAPI spec, and quite another how a complete solution that uses xAPI is architected, and the whole set of circumstances and scenarios that the solution is expected to contemplate.

    I think that security/privacy concerns are legitimate and important, but I wouldn't say that there's a security hole in the spec.

    Kind regards

        jPablo Caballero
    (@jpablo128)

    Jonathan Kevan

    unread,
    Oct 31, 2016, 8:16:27 PM10/31/16
    to xAPI-Specification
    Hey all,

    I brought this comment up to our technical staff... here is their response regarding our approach to the issue:

    "We struggled with the same security issues during our first big deployment of an LRS--both the potential for individual students to submit phony statements, and the possibility for data leaks exposing FERPA-protected information. Others in this thread have addressed the latter: by making sure the credentials for submitting xAPI statements are not the same as those for viewing or aggregating them. 

    But regarding phony statements, we could not come up with a reasonable method that used the javascript xAPI Wrapper. Ultimately, it comes down to this: if you trust the client's browser to submit xAPI statements, you're implicitly trusting the client. So if you're concerned that the individuals submitting xAPI statements might try to game the system, there isn't a javascript implementation that will work for you.

    In the end, we did a normal install of an LRS (learning locker), but we made that server only available on a private network. Admins and teachers connected to a VPN could interact with the LRS, and the web servers running our public-facing sites could submit xAPI statements on behalf of the users. What this boiled down to was creating a small intermediary that sat on the public web servers and listened for xAPI statements that it would then forward on to the (private) LRS. In practice, this was an AJAX hook in WordPress that would do a permissions check on the active user, make sure it wasn't a duplicate submission, construct the relevant JSON for the xAPI statement, and then submit that via a POST request to the private LRS. The normal WordPress protections on AJAX and form submissions (nonces) prevent students from submitting phony statements."

    I hope that's helpful,

    - Jon

    Shelly Blake-Plock

    unread,
    Oct 31, 2016, 8:20:52 PM10/31/16
    to Jonathan M Kevan, xAPI-Specification
    All,

    Regarding xAPI security, please contribute Q&A / issues to https://github.com/xapisec/xapisec where we’ve been collecting community input in an informal way for the purpose of organizing a best practices document.

    All are welcome to contribute. This effort goes back to work done in the Design Cohort #3.

    Best,
    Shelly



    Sam Ellis

    unread,
    Nov 1, 2016, 2:00:06 PM11/1/16
    to xAPI-Specification
    Thanks for all your responses, this has helped a great deal.  It's clear to me that this is not a security hole and there are sensible precautions to avoid LRS misuse.

    We will certainly implement server side tracking in our project. 

    Regards,
    Sam

    Jason Lewis

    unread,
    Nov 1, 2016, 3:48:02 PM11/1/16
    to Sam Ellis, xAPI-Specification
    In addition, you can sign up for the xAPIsec mailing list and Slack channel here: https://goo.gl/forms/EHKDqSBjHqdwQPKx1

    It's a bit quiet at the moment but I'm working on a survey to separate areas of interest re security and refocus efforts, should be out on the xAPIsec and Spec mailing lists soon.

    --
    You received this message because you are subscribed to the Google Groups "xAPI-Specification" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to xapi-spec+...@adlnet.gov.
    --
    Jason Lewis
    805.5.LAMBDA // decomplecting.org

    My GPG key can be found via: gpg --keyserver pgp.mit.edu --recv-keys 0x4514ddcc3cc725de
    Key fingerprint: F884 6075 3FC3 E993 6862 F589 4514 DDCC 3CC7 25DE
    Reply all
    Reply to author
    Forward
    0 new messages