Dieser Untertitel ist noch nicht fertig. Wenn du kannst, bitte unterstütze uns hier und schau den Talk in Amara an für die letzten Korrekturen: https://c3subtitles.de/talk/1448 Danke!
*Wikipaka Intro Musik*
Herald: Welcome to the next talk about free substitution for schools. Yeah. By…
if it was done by Fynn […]. Thank you, for the translators for translating into
German. Let's start.
Fynn: In general, as you know, teachers can't always teach as planned, so students
need to be informed when their lessons are moved in time or space or both, or don't
take place as they should, or they have a different teacher. All that. And for that,
schools create a substitution plan. There's software for that. For example,
Untis. And these substitution plans need to be distributed. And in Germany, a lot
of schools use Digitales Schwarzes Brett or Digital Signage Board or DSB for that.
And it works like this. Um. Oh, yeah. And it works like this that the school uploads
the plan. Pupils can read this substitution plan on these DSB screens, on
their mobile devices using the client software developed by Heinekingmedia and
using the website, once they have the credentials that they acquired from their
school. It's one pair of username and password for all pupils and one for all
teachers. Well. And this costs money, schools buy way to expensive screens from
Heinekingmedia. And then the schools pay extra for this, uh, fantastic web
interface here where you can sign in and view your substitution plans. You can also
use this mobile app. It's not really good, though, as I will explain. Um, this is
what it looks like. Things are tiny, as you can see. It's obviously proprietary
software. It depends on Google Play services. You need to zoom around. You
need to scroll around to see all the information because it's so tiny. So this
is super suboptimal. Um, I don't even know why this is so small. If you look it up on
a Web browser, it zooms fine when you have a small device. And I really don't know
how that… screwed up like that. It has useless push notifications like new
content available. It's not not useful. And you have to click at least one time
too much all the time. And due to these issues, I always wanted something that is
better than DSB mobile. So I began capturing DSB mobiles network traffic.
Surprisingly, in Android, this is really easy. Um, you can use user friendly
software like HTTPCanary, which is this one, or packet capture, which is this one.
It's unfortunately proprietary, but I don't know any non-proprietary software
for this is. If you know any, please tell me. Um, it acts like a VPN provider app
and proxies all the traffic that is going out, uh, through it; installs a
certificate in your system so that apps still think that the net…work connection
is secure, and then this app will decrypt and store and re-encrypt all the traffic
that is going out and in. And so you can read it, then. Uh, this is essentially
like a attacker-in-the-middle attack that you're doing yourself on your own network
traffic. Uh, yeah, except on recent Android versions. Apparently Android
doesn't trust certificates that you install, anymore. So you actually now have
to have root access to move them to this location /systems/etc/security/cacerts so
that they are ultimately trusted. And that is unfortunate because it makes it a
little more difficult. But in all our Android versions, it works really easy.
Um, with more effort, this capturing of network traffic can be circumvented by
implementing a kind of certificate pinnings so that the app checks beforehand
which certificates it trusts, and which it doesn't. With more effort, such a
prevention could also be circumvented. Uh, but DSB Mobile didn't have that, so I
could figure out how this end point works. As you can see, it's called the iPhone
Service. On Android. Using your user ID and password, you can request an auth
token. It has the form of this. Actually, that's what it looks like when you have
invalid credentials. So if it returns this, then your credentials are not valid.
It never changes. So I don't know what the use of this token is. Um, however, DSB
Mobile never stored it, even though it's the same all the time. So it took one
extra round trip time, every log in to fetch this, never changing auth token.
Using this auth token, you can request your substitution plan URL, and then once
you have this substitution plan URL, you can access your substitution plan. OK, so
using this knowledge, I developed a client that allows me to directly have access to
just the relevant information and I call it DSBDirect. Uh, the very first thing it
did better than DSBmobile is that it display things not as tiny. This is a kind
of old screenshot as you can see. These HTML files here can be parsed using a
parser and such that, uh, you can filter it, you can, um, have useful notifications
that I added later on. This is a native list, not a web view. So it has… it feels
better. And uh, yeah, of course it's not proprietary but Free Software. Uh yeah.
Oh, by the way, this logo, it's supposed to represent my school's logo. Uh, this
one. Hmm. Please don't tell me I did, too bad. OK? At least it's different from the
DSB mobile logo. This endpoint is fun in other regards. The first time I
encountered it, it allowed completely unencrypted connections, and the website
did not redirect users to HTTPS. So actually you'd most of the time input your
username and password and transmit it unsecurely. It supported up to TLS version
1.0, which is obsolete. It supported SSLv2, which enables a DROWN attack, which
I didn't quite understand. But apparently those aren't very likely to be exploited
here. But it could allow attackers to read your traffic. I informed the company about
this on August 11th. And I believe this is when I introduced the "not my fault
grumble" tag in the issue tracker… tracker. They were happy to be informed
about this. On August 22nd, they enabled TLS version 1.2, disabled SSLv2, er, still
allowed insecure connections. And I also noticed that they embedded fonts from
Google and this is obviously bad for privacy. So I told them about that. Uh,
Twice. September 19th, the iPhone service 404s if the connection is insecure.
Although Google fonts are still embedded. Anyhow, it's October 4th that the iPhone
service is shut down. So I start focusing on the new endpoint that apparently the
DSB apps have been using for a while, but I didn't notice that. Uh, so I had to
figure out how this data format works. It looks like this. So you can see it has a
JSON body usi– which has a request, which is an object that has data, which is a
string. So I wanted to figure out how to read this. It looks like base64 when I'm
escaping these slashes, of course, because it's quoted in JSON. Um, however, decoding
this JSON string here did not, er, this base64 string did not deliver a nice
result. Uh, so I had to look for clues by decompiling the app. There are online
tools for that. Unfortunately, the app was minified or… which is obfuscated during
compile time, which made the results not very readable, which means that once you
have it decompiled, you will have, the first function that appears is "A", and
the second one is "B" or something. Fortunately, I don't remember how exactly
I did that. So instead we're going to have to look at whether this was legal or not.
Because that's interesting, too, because I think it is. Let's look at § 69e UrhG,
copyright law, Urheberrechtsgesetz, "Dekompilierung". "Die Zustimmung des
Rechteinhabers ist nicht erforderlich, wenn die," und hier steht "Verviefältigung
des Codes oder die Übersetzung der Codeform im Sinne der in § 69c Nr. 1 und
2.," gemeint ist Dekompilierung, "unerlässlich ist, um die erforderlichen
Informationen zur Herstellung der Interoperabilität eines unabhängig
geschaffenen Computerprogramms mit anderen Programmen zu erhalten, sofern folgende
Bestimmungen erfüllt sind." So. It says you may decompile without permission when
it is strictly necessary while trying to create interoperability between two
programs created independently from each other. Under these conditions. And here
are three conditions. Um, "Die Handlungen werden von dem Lizenznehmer oder einer
anderen zur Verwendung eines Vervielfältigungsstückes des Programms
berechtigten Person oder in deren Namen von einer hierzu ermächtigten Person
vorgenommen". It says, you must have permission to use the program. Hey, I
think I'm allowed to use the program. I'm assuming I am. My school paid for it.
Second, "die für die Herstellung der Interoperabilität notwendigen
Informationen sind für die in Nummer 1 genannten Personen noch nicht ohne
weiteres zugänglich gemacht". So the information you want to know is not
already provided. Oh yeah. Actually Heinekingmedia didn't document this
obviously. So yeah. This *indistinguishable*. Third, "Die
Handlungen beschränken sich auf die Teile des ursprünglichen Programms, die zur
Herstellung der Interoperabilität notewndig sind". So you're only planning
the part that contains the information you want to know. Uh, yeah. I don't think this
Android app is divided into parts. So let's just, let's just skip that. The law
text goes on stating three things you may not do with the information you gain from
decompiling. "Bei Handlungen nach Abs. 1 gewonnene Informatione dürfen nicht zu
anderen Zwecken als zur Herstellung der Interoperabilität des unabhängig
geschaffenen Programmes verwendet werden." So don't use it for other purposes than
creating interoperability, interoperability with the independently
created program. Oh yeah, of course. I never did use my knowledge for any other
reasons. Never. "…an Dritte weitergegeben werden, es sei denn, das dies für die
Interoperabilität des unabhängig geschaffenen Programms notwendig ist". So
don't tell third parties about the information unless necessary for
interoperability. Oh, yes, my Free Software implementation couldn't be
interoperable if the information wasn't public. Unless it was Non-Free Software,
which is not obviously. "Für die Entwicklung, Herstellung oder Vermarktung
eines Programms mit im Wesentlichen ähnlicher Ausdrucksform oder für
irgendwelche anderen das Urheberrecht verletzenden Handlungen verwendet werden".
So don't violate the rest of the copyright law. Of course, we're not. Surely,
creating an alternative to something, on its own, doesn't violate copyright law.
Right? So yeah, after doing it, I discovered that I did so legally. So I
found a usage of some class related to gzip. So I tried around a bit and figured
you could use this command to decrypt this string. And guess what it is? It's more
JSON! What an efficient data format. You're hiding our encoded JSON inside more
JSON. Let's look at the data we are sending. Of course, we have a user ID and
a pass. Besides that we have a lot of data, apparently for statistics. You have
the app's version, you have the package ID, the device model, the Android version
and API level, the user's language and the current date. I don't know why you have
the date. I think they know the date that the query arrives at, but, ya, you have
that anyway. You have a… oh sorry, some of this is redundant from the request header
or user agent that is already sent. I don't know why they do that twice. Um, you
have App ID, which is a unique-per- installation ID, which I at first didn't
know how to generate. And you push ID, which is, I'm assuming, an ID generated by
Google Mobile Services now known as Google Play Services to enable push
notifications. So it becomes obvious that they're able to link requests together and
possibly create usage patterns. What are they doing with this data? No clue!
There's no privacy policy anywhere. Which of these fields are required? All of them,
but push ID. But most strings can be left empty. So DSBdirect sent the minimal
amount of requested data, which is everything but with empty strings. And
yeah, actually guess what, this server allows insecure connections again. So, uh,
something happened. Um. On some date, the server side verification of this query was
changed and the field AppVersion suddenly became mandatory. I ran some experiments
and found examples of valid and invalid version names. These are examples of valid
version names. These are examples of invalid version names. Finally,
AppVersions that aren't real versions of Heinekingmedia's apps are accepted anyhow,
like version 7.0.0. We're only at version 2.5.… I don't remember, 6, I think. So,
DSBlight started sending along some AppVersion… its own actually, which was
2.5, and the same as an older DSBmobile release. And because I thought maybe
they'd have more server side changes in the future, I implemented a new system. It
was to prevent server side changes from requiring an update because that would
mean I have to write change logs because after it releases are slow because the one
who was uploading it to Google Play for me also always took a while. And because of
that, there was now a "look for a fix" button that creates the news file, which
is located at the repository's root, which allows me to inform users when they can
expect a fix. It allows me to change this base JSON, that credentials are appended
to which is this without the user ID and user password. So they're added to this
JSON later. And… in case they checked that I added an option to send the real date. I
thought maybe that's what they would do next. They never did that, unfortunately.
This was the same release as the one with the version number fix, this one. Uh, we
have good news elsewhere, though. It was the same day, October 15th, that I
received an email that app.dsbcontrol.de was no longer accessible on Port 80 and
that Google fonts were now being loaded locally. This e-mail contained no usual
"bei Rückfragen können Sie sich gerne direkt an mich wenden", unfortunately,
maybe they didn't want to hear from me anymore. I couldn't verify this at first.
Uh, October 16th, I could verify this. So a friend noted that they have slow deploy
times, apparently. Uh, round 3, it's October 17th, and we're getting an invalid
answer from the server again. And now the App ID has to be set to a UUID and last ID
has to be set to something. It can't be empty. So we are now sending
"zurfrühstückszeit". I wasn't aware of how to generate App IDs yet, so I just took
the one that I had captured from my device. Contributor Pixilon and me learned
this through trial and error. I thought it was very bothersome because the service
sometimes accepted and sometimes rejected the very same query. Uh, so this slow
update cycle we noticed earlier turned out to be really bothersome and frustrating
because you'd, you try something and then it would work and then you'd remove it
again and that wouldn't work anymore. And then you thought this was the cause for
it… actually was just the slow release, deploy cycle. Um, likely, or maybe, they
had just banned this app ID at this point in time, but I didn't realize, I'm not
sure. Rather, I believe the server was generally are struggling and rejecting log
ins because my DSBmobile installation, with this app ID, was also sometimes
rejected. *incomprehensible*. They seem to have reverted some of these changes later,
which reaffirmed my belief that all DSBmobile installations were affected.
Contributor Pixelon figured that device was now mandatory, which meant not empty.
So we sent device "a". I remembered to have at some point in time sent the words
"kartoffel" or "poster" as a device eventually. Now, I thought we were smart.
I added new functionality to this new system I explained earlier. Firstly, as a
precaution, I could remotely activate sending the last date, in case that, I
mean remotely means that it happens when users click on "Look for a fix". Secondly,
I could now set an array of headers to send to the server. And thirdly, we had
discovered some alternative endpoints. To understand this, you first have to know
that they have sold skinned versions of DSB. Uh, so this is the normal DSBmobile.
I showed it earlier already. This is the IHK skinned DSBmobile. It's accessible via
two URLs, that delivers the same data as this website. Uh, it also has a
corresponding skinned Android app. So I configured… so I could configure the
endpoint the client would send the data to because each of these had a different
endpoint and this app used one of these two. However, this was tricky because I
had to prevent myself from giving myself the power to redirect users' queries to my
own server, so I hardcoded four URL endpoints… endpoint URLs, mobile, web, IHK
mobile and app IHK BB into the app so I could switch between them using an integer
and I set it to the IHK mobile endpoint. I believe it was the very next day that IHK
mobile and and app IHK BB endpoints were broken. Actually, they returned invalid
data in a way that crashed my app. Oops. And suddenly the web endpoint from the
normal website was constantly moving to new locations and there was a
configuration.js script that contained where it was, so I hard coded into the app
as a precaution in case I'd need it later a very specific way to to find this
location. And it was like behind this seventh quotation mark or something.
Clearly unreliable, and suddenly the string was moved a line downloads, so it
was now the ninth quotation mark. Interesting. Um, also this App stopped
working. It's still on the Play Store now and it's still not working. This website
is still available and it's not working because they broke their end point. Uh,
this was around the time that this Google Play takedown notice reached us because
apparently DSBdirect infringes the trademark of DSB. I don't feel qualified
to comment on this as I don't understand trademark law. I tried to ask for a
specific clarification as to why they removed my app, three times, but they
never responded. Oh, by the way, that's a nice trick you can do with emails you
don't like. You can just pretend you never received them. So a few days later, the
website JavaScript, including configuration.js, was obfuscated in such a
way that I don't understand how it works, but it constantly evokes the debugger, if
the developer tools are open. You can in theory easily circumvent this by telling
the browser to ignore breakpoints. This doesn't seem to work with Firefox, but it
works in chromium. I don't know why. I'm just going to assume you could have
figured this out somehow. Be it that we could have had a web view running in the
background if we absolutely had to. But fortunately, contributor Pixon had come up
with what is needed to talk to the mobile endpoint now. Because it's more data.
Through decompilation he learned that it was being generated using the default Java
UUID class, UID. … randomUUID.toString. Also device idea was mandatory. So I added
spoof data. I took a random device ID from this list. I took a random OS version from
anything between 4.0.2 and 10.0, I took a random language, mostly German, sometimes
English. And as a BundleId, I took the package ID of DSBmobile. With an option to
disable this via news in case it would get in the way somehow. And that was the end
of that. Apparently they stopped trying to prevent DSBmobile from working. Apparently
after it releases don't count to them and it isn't worth their time. Or maybe they
were just uncreative. I could still think of a few ways to tell DSBlight and
DSBmobile apart, but I'm clearly not going to tell them. However, just this month,
Pixilon asked again why DSBmobile was removed from the Play Store, also because
he believed we didn't violate German trademark law, currently, but, uh,
Jasmich, who, uh, is sitting here, by the way, had uploaded DSBdirect to the Play
Store again and received a rather interesting response. "Sehr geehrter Herr
Zwerger", dear Pixilon, "Vielen Dank für Ihre E-Mail. Leider sehen wir uns
außerstande mit Ihnen einen qualifizierten Diskurs zu diesem Thema zu führen. Uns
sind weder Daten zu Ihnen noch zum Herrn Godau bekannt." This means, unfortunately,
we don't have your address and thus can't send you legally meaningful messages.
Heißt, sie wollen Einwurfeinschreiben machen. "Ebenfalls ist uns nicht klar, in
welcher Rechtsbeziehung Sie zueinander stehen". We don't know about your legal
relationship. This is a bit strange because I don't know either. According to
my father, we might be a "Gesellschaft bürgerlichen Rechts", but it's not exactly
proof of familiarity with Free Software. "Dennoch möchte ich im Folgenden unsere
Position nochmals klar ausdrücken. Es ist weder Ihnen noch anderen Dritten
gestattet, unsere interne DSBmobile-API für eigene Softwareprodukte abzufragen.
Wir untersagen es Ihnen hiermit schriftlich und letztmalig." You may not
use our internal API, I find it questionable whether a publicly facing API
is to be considered internal. One might argue that it is only for communication
between software they control. But I believe I control my device and my client
installation, not them making the API, not internal. "Eine Inverkehrbringung einer
App mit gleichem oder ähnlichen Namen zu DSB ist Ihnen im europäischen Raum
ebenfalls untersagt. Hier liegt Markenschutz durch Heinekingmedia vor." I
don't understand trademark law. There are so many trademarks starting with this or
just consisting of the letters DSB with partially overlapping registered use cases
and their trademark doesn't have distinctive character,
"Unterscheidungskraft", and I just don't understand it. By the way, there are other
trademark "Digitales Schwarzes Brett" which is registered as a different one
from DSB was once rejected as a national trademark just because it didn't have
distinctive character. Why can there be European trademark laws without– European
trademarks, without distinctive character? I do not understand and I'm not qualified
to comment. "Eine App-Bereitstellung im Store ist dabei eine geschäftliche
Tätigkeit, ganz egal welchem wirtschaftlichen Zweck diese folgt, es
besteht Verwechslungsgefahr. Wir untersagen Ihnen hiermit die Benutzung der
geschützten Wortmarke DSB letztmalig." Um, the first part is true. I had gotten lot
wrong. It counts as "geschäftlicher Verkehr" when you provide a service even
for free to the public. Er, there's danger of confusion, this has to be about the
letters DSB, right? Because as I explained earlier our logo is completely unrelated.
Either, I'm not too certain that there really is danger of confusion that
Heinekingmedia is directly affected by or exclusively affected by. After all, one
could also believe that it is an app that provides access to something related to
the Danish railway company. Of course it does not, but it is about recognition
value, which is not something that the DSB has exclusively for sure. "Wir untersagen
Ihnen hiermit die Benutzung der geschützten Wortmarke DSB letztmalig."
*undistinguishable" "Sollten Sie weiterhin gegen unsere deutlichen Aufforderungen
verstoßen, werden wir den Fall an unsere rechtliche Vertretung, Herrn Doktor Selig
übergeben. Dieser ist in dieser E-Mail bereits CC." Scaring us. "Ebenfalls werden
wir weiterhin gegen jede Veröffentlichung einer solchen App vorgehen. Entsprechend
dadurch entstehende Kosten würden wir bei Ihnen als Schadensersatz geltend machen.
Wir bitten um zwingende Beachtung. Mit freundlichen Grüßen, Andreas Noack. Noag,
Norg, Noack. That's the CEO of Heinekingmedia. Yeah, we are famous! We
redirected this email to contributor Jasmich who had DSBdirect up on the Play
Store at this point of time. And he decided to take it down and apologize.
Suddenly, and this was the very next day he received an email that sounded a lot
friendlier. "Hallo. Vielen Dank für Ihr Entgegenkommen. Wir finden Ihren Ansatz
prinzipiell sehr gut. Allerdings hätten wir uns gewünscht, dass Sie uns vor
Veröffentlichungen und Nutzung unserer API um Erlaubnis gebeten hätten." If we had
asked for permission, I'm quite sure we would not have received it. "Dennoch
möchten wir Ihr Engagement gerne würdigen, und würden Sie daher gerne zu uns nach
Hannover einladen. Vielleicht können Sie uns mit Ihren Ideen helfen eine bessere
App zu bauen? Vielleicht finden wir ja sogar einen Weg, dass Sie daran mitbauen?
Gerne fördern wir junge Talente. Wir würden uns freuen, Sie kennenlernen zu
dürfen. Ich freue mich auf Ihre Rückmeldung. Mit freundlichen Grüßen,
Noack." I rather– I'll rather leave this largely uncommented. I don't know exactly
what they want from us, but I guess we'll have to see. And that's the dramatic
cliffhanger that we have to end our talk with. Events are yet to unroll. There's
one thing that I can learn from this. Don't use other people's trademarks.
Because trademark law is too complicated. Apologizing instead of being rebellious
seems to work better, even if the thought of conflict intrigues you and you really
do believe you're in the right, you probably just misunderstood the law.
Alternatively, exclusively do such things anonymously. Decide beforehand what you
want to put your name on. Thank you.
*Applause*
*postroll music*
Subtitles created by c3subtitles.de in the year 2021. Join, and help us!