Profiling Jodel™ users with image (meta)data

follow @h43z
"Jodel instantly connects you with the people around you. It's a live social feed of your community's hottest news, questions, events, stories, and jokes."

how jodel works

Users can can start discussion threads by posting a so called "jodel" which consists of a text message or an image. Others within a 10km radius can comment on it as well with text or image content.

Within every thread a commenting user gets assigned a ascending number (starting from 0 - OP gets 0 by default) that won't change for all his comments and is publicly visible. This way you can mention someone specific and don't loose track of who says what. Quite practical because comments are in a flat hierarchy and not threaded.

In a single thread users are thereby pseudonymous though across the overall app they are anonymous to everyone else.

Users of the app like this advantage of anonymity to express themselves in a much more open way and share personal, intimate and often embarrassing content.


I'm interested to see if users can nonetheless be somehow tracked and profiled across threads. If possible this would break the basic assumption held by all users that content is only strictly coupled to the thread it was posted in and in no way connected to other threads.

There are a few ways one could start exploring such an attack e.g. analyzing language, words and phrases used, posting time patterns, content patterns, triangulation of positions (the app shows terms like "far", "near" or "here" to indicate distance of others related to your own position) or maybe even behavioral habits.

I decide to look into the uploaded photos by users for now. Jodel does not allow to choose from the gallery when sharing but only taken directly from the camera.

First I need to get my hands on some images.

off-topic

This can be done by intercepting the network traffic to see the payloads the app and the jodel server exchange. Like many services jodel uses and http api that feeds the app with information to display.

Taking that approach you will have to ssl unpin the app first.

Another way would be to act like an fake client and get the payloads this way.

I start by downloading some random image I know exists.
% domain="http://img.jodel.com/"
% file="5b9466bfec02b67c7e09889e_ChrvVB8OpM9c1Ubr_image.jpeg"
% curl -O "$domain$file"
    
And run the exiv2 command to look for interesting exif tags.
% exiv2 5b9466bfec02b67c7e09889e_ChrvVB8OpM9c1Ubr_image.jpeg
File name       : 5b9466bfec02b67c7e09889e_ChrvVB8OpM9c1Ubr_image.jpeg
File size       : 107092 Bytes
MIME type       : image/jpeg
Image size      : 640 x 1100
Camera make     : 
Camera model    : 
Image timestamp : 
Image number    : 
Exposure time   : 
Aperture        : 
Exposure bias   : 
Flash           : 
Flash bias      : 
Focal length    : 
Subject distance: 
ISO speed       : 
Exposure mode   : 
Metering mode   : 
Macro mode      : 
Image quality   : 
Exif Resolution : 1080 x 1857
White balance   : 
Thumbnail       : None
Copyright       : 
Exif comment    : 
    
Is there anything that could indicate that there is some uniqueness within one users image metadata that possibly is common across all his uploads?

In theory there are many tags that could make a more or less unique profile.

Just to make sure I run another program, identify of the imagemagick tool suite.
% identify -format "%[EXIF:*]" $file
exif:DateTime=2018:09:09 02:17:55
exif:ExifOffset=94
exif:ImageLength=1857
exif:ImageWidth=1080
exif:LightSource=0
exif:Orientation=0
    
The tags lightsource and orientation pop up. It looks like there is some discrepancy between tools when it comes to extracting exif tags from files.

First insight. There is definitely meta information in those images.

I run another tool named exif.
% exif $file
EXIF tags in '5b9466bfec02b67c7e09889e_ChrvVB8OpM9c1Ubr_image.jpeg'
('Motorola' byte order):
--------------------+-------------------------------
Tag                 |Value
--------------------+-------------------------------
Image Width         |1080
Image Length        |1857
Orientation         |Unknown value 0
Date and Time       |2018:09:09 02:17:55
X-Resolution        |72
Y-Resolution        |72
Resolution Unit     |Inch
Corrupt data
The data provided does not follow the specification.
ExifEntry: The tag 'LightSource' contains data of an 
invalid format ('Long', expected 'Short').
Light Source        |%    
    
Again new tags appear. X-resolution, y-resolution and resolution unit.

I get another random image to compare the tags.
% file1="5b9465620364771c9b10f371_d4hHV76HTg78qcKK_image.jpeg"
% file2="5c300e17197bf2002352e3d5_HvM993OoqjyEKBn2_image.jpeg"
% vimdiff <(identify -format "%[EXIF:*]" $file1) \
          <(identify -format "%[EXIF:*]" $file2)
    


There a visual diff.

Second insight. Different files different tags.

Jodel is not removing any or at least not all meta information from user uploads.

It is also very intresting that even the image sizes (dimensions) are different.
% identify -format '%w %h\n' $file1 $file2 
640 1095
640 1136
These two values are not metadata but fundamental information about the image itself.

I fetch two of my own uploads to jodel and compare exif tags once again.



Other than the DateTime they are the same. I do some more sampling with images I can reliable assign to specific users and recognize every one of them has the same exif tags overall his uploads. The same can be said about image dimensions.

Third insight. A user has identical tags plus width and height on all his uploads.

The question arises how unique are these exif tags and dimension combinations. I suspect these are identical for phone models. But maybe os version, app version or even os settings?

Instead of searching for the origin why these exif profiles differ I decide to find how many unique tag combinations there are.

This is run after a download of many more images from my area.
% identify -format "%[EXIF:*]" *.jpeg \
| grep -v "DateTime" \
| cut -d"=" -f1 \
| sort \
| uniq -c \
| sort -n

    3 exif:SceneCaptureType
    6 exif:InteroperabilityIndex
   19 exif:InteroperabilityOffset
   19 exif:thumbnail:InteroperabilityIndex
   19 exif:thumbnail:InteroperabilityVersion
   99 exif:thumbnail:JPEGInterchangeFormat
   99 exif:thumbnail:JPEGInterchangeFormatLength
  380 exif:JPEGInterchangeFormat
  380 exif:JPEGInterchangeFormatLength
  498 exif:MeteringMode
 6148 exif:ColorSpace
 6148 exif:PixelXDimension
 6148 exif:PixelYDimension
 6148 exif:ResolutionUnit
 6148 exif:XResolution
 6148 exif:YResolution
 9112 exif:ImageWidth
 9118 exif:ImageLength
 9211 exif:LightSource
15359 exif:ExifOffset
15359 exif:Orientation
    
Not too many tags actually. But some tags are rare others like orientation occur all over the place.

Here the same stats for image dimensions width and height which again are not part of the exif data.
% identify -format "%w %h\n" *.jpeg \
| sort \
| uniq -c \
| sort -n \

   1 542 1136
   1 621 1136
   1 640 1051
   1 640 1096
   1 640 1105
   1 640 1134
   1 640 647
   1 640 666
   1 640 698
   1 640 923
   2 617 1136
   2 624 1136
   2 640 1012
   2 640 1013
   2 640 1030
   2 640 1036
   2 640 1038
   2 640 541
   2 640 567
   2 640 569
   3 575 1136
   3 640 1032
   3 640 1088
   3 640 606
   3 640 630
   4 640 1027
   4 640 1042
   4 640 1099
   4 640 1106
   4 640 1132
   5 574 1136
   5 640 1091
   5 640 1104
   6 558 1136
   6 634 1136
   6 640 1040
   6 640 1101
   7 577 1136
   8 640 1097
   9 583 1136
   9 588 1136
   9 599 1136
  12 626 1136
  13 592 1136
  13 640 1018
  14 625 1136
  17 585 1136
  17 622 1136
  20 606 1136
  29 633 1136
  36 640 1017
  37 640 1016
  43 602 1136
  45 631 1136
  48 640 1026
  53 635 1136
  60 572 1136
  65 640 1102
  77 616 1136
  78 640 960
  83 640 1007
  85 618 1136
  87 568 1136
  88 586 1136
  96 640 1019
 135 640 1008
 154 596 1136
 212 640 1093
 224 569 1136
 231 640 1029
 269 571 1136
 342 623 1136
 353 612 1136
 455 640 1100
 463 604 1136
 488 640 1010
 539 640 1020
 710 525 1136
1240 640 1031
1428 640 1136
3046 640 1095
3935 639 1136
82 rows of output therefore 82 unique width height combinations.
More precisely that means of all 15359 images I got my hands on only 5 (0.03%) have the dimensions 574 width and 1136 height.

If my assumptions so far are correct this is either the same person or different users with super rare width height values. Compare that to width 639 height 1136 which 25.6% of all images have.

To make my life easier when investigating all the images I write a small program that iterates over every image and stores its exif data, width and height into an sqlite database.
The final table layout looks like this.
CREATE TABLE images(
  ...
  width INTEGER,
  height INTEGER,
  exif JSON
);
    
Let's check the exif data for those 5 images (0.03%) mentioned above.
sqlite> select json_remove(exif,"$.DateTime") from images 
   ...> where width = 574 and height = 1136;

{"ImageWidth":1080,"ImageHeight":2138,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
{"ImageWidth":1080,"ImageHeight":2138,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
{"ImageWidth":1080,"ImageHeight":2138,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
{"ImageWidth":1080,"ImageHeight":2138,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
{"ImageWidth":1080,"ImageHeight":2139,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
{"ImageWidth":1080,"ImageHeight":2139,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
    
The query reveals that the first 5 images have a different exif ImageHeight then the last two respectively 2138 and 2139.

Judging by what the images actually show - early in the morning walk home after new years eve party, beer, beer and inside wall of an restaurant - I think this is one and the same person.

The last two images just show #foodporn. This must be someone else.

NEWSFLASH I later contacted the beer guy and he was kind enough to confirm my guess. All ImageHeight 2138 were his uploads but not the 1239 ones. His phone is an Xiaomi Mi 8 and according to him not very popular in Europe.


Correlating the images of this guy was easy. His group was very small. This would not have been possible with the combination of width 639 and height 1136 because there are 3935 other images that have the same sizes. There are probably many separate users within this group that all have the same popular phone, OS or settings. It's also possible some huge groups form because of power users with many uploads but I doubt that.

The goal should be to increase the number of groups that way the images per group go down.

Therefore the next step is to check for unique exif tag combinations.
The first number shows how many times the exact combination of the exif metadata was counted.
sqlite> select count(*) as c,
json_remove(exif, "$.DateTime") 
from images group by json_remove(exif, "$.DateTime")
order by c;

1|{"ExifIFDPointer":94,"ImageHeight":406,"Orientation":0,"ImageWidth":480,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1092,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1140,"ImageWidth":720,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1144,"ImageWidth":720,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1178,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1296,"ImageWidth":720,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1836,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1851,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1854,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1855,"ImageWidth":1080,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2272,"ImageWidth":1440,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":638,"ImageWidth":720,"SubExif":{"LightSource":0}}
1|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":762,"ImageWidth":480,"SubExif":{"LightSource":0}}
1|{"ImageHeight":1230}
1|{"ImageHeight":1845,"Orientation":0,"ImageWidth":1080,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"ImageHeight":406,"Orientation":0,"ImageWidth":480,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"ImageHeight":562,"Orientation":0,"ImageWidth":540,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"ImageWidth":1080,"ImageHeight":1748,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":1911,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":1918,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":1937,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":1966,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":1977,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":2088,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":2156,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1080,"ImageHeight":2265,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1440,"ImageHeight":2478,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1440,"ImageHeight":2580,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1440,"ImageHeight":2582,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":1440,"ImageHeight":2672,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"ImageWidth":720,"ImageHeight":1291,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
1|{"LightSource":0,"Orientation":0,"ImageHeight":1136,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"LightSource":0,"Orientation":0,"ImageHeight":1704,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"LightSource":0,"Orientation":0,"ImageHeight":1857,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"LightSource":0,"Orientation":0,"ImageHeight":816,"MeteringMode":65535,"ImageWidth":480,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
1|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":640,"PixelYDimension":1096}}
2|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1134,"ImageWidth":720,"SubExif":{"LightSource":0}}
2|{"ImageWidth":1440,"ImageHeight":2784,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
2|{"LightSource":0,"Orientation":0,"ImageHeight":1138,"SceneCaptureType":0,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":130,"SubExif":{"JPEGInterchangeFormat":160,"JPEGInterchangeFormatLength":0}}
2|{"LightSource":0,"Orientation":0,"ImageHeight":960,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
3|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1023,"ImageWidth":1080,"SubExif":{"LightSource":0}}
3|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1063,"ImageWidth":1080,"SubExif":{"LightSource":0}}
3|{"ImageHeight":2296}
3|{"ImageWidth":1080,"ImageHeight":1742,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":1080,"ImageHeight":2134,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":1080,"ImageHeight":2145,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":1080,"ImageHeight":2200,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":1440,"ImageHeight":2614,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":720,"ImageHeight":1296,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":720,"ImageHeight":1308,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"ImageWidth":720,"ImageHeight":1354,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
3|{"LightSource":0,"Orientation":0,"ImageHeight":1740,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
3|{"LightSource":0,"Orientation":0,"ImageHeight":1848,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
4|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1244,"ImageWidth":720,"SubExif":{"LightSource":0}}
4|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1336,"ImageWidth":720,"SubExif":{"LightSource":0}}
4|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1733,"ImageWidth":1080,"SubExif":{"LightSource":0}}
4|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2296,"ImageWidth":1440,"SubExif":{"LightSource":0}}
4|{"ImageWidth":1080,"ImageHeight":1984,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
4|{"ImageWidth":1080,"ImageHeight":2138,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
4|{"ImageWidth":1080,"ImageHeight":2146,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
5|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1932,"ImageWidth":1080,"SubExif":{"LightSource":0}}
5|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1968,"ImageWidth":1080,"SubExif":{"LightSource":0}}
5|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2478,"ImageWidth":1440,"SubExif":{"LightSource":0}}
5|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2864,"ImageWidth":1440,"SubExif":{"LightSource":0}}
5|{"LightSource":0,"Orientation":0,"ImageHeight":1160,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
5|{"LightSource":0,"Orientation":0,"ImageHeight":818,"MeteringMode":65535,"ImageWidth":480,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
5|{"Orientation":1,"XResolution":[0],"YResolution":[0],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":1242,"PixelYDimension":2208}}
5|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":750,"PixelYDimension":1624}}
6|{"ExifIFDPointer":94,"ImageHeight":762,"Orientation":0,"ImageWidth":480,"SubExif":{"LightSource":0}}
6|{"ImageWidth":1080,"ImageHeight":1737,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
6|{"ImageWidth":1440,"ImageHeight":2876,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
6|{"ImageWidth":720,"ImageHeight":1440,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
7|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2469,"ImageWidth":1440,"SubExif":{"LightSource":0}}
7|{"ImageHeight":762,"Orientation":0,"ImageWidth":480,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
7|{"ImageWidth":1080,"ImageHeight":1860,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
7|{"ImageWidth":1080,"ImageHeight":2128,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
7|{"ImageWidth":1440,"ImageHeight":2576,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
8|{"ImageHeight":922,"Orientation":0,"ImageWidth":540,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
8|{"ImageWidth":1080,"ImageHeight":1960,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
8|{"ImageWidth":720,"ImageHeight":1148,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
8|{"LightSource":0,"Orientation":0,"ImageHeight":2296,"MeteringMode":65535,"ImageWidth":1440,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
8|{"LightSource":0,"Orientation":0,"ImageHeight":764,"MeteringMode":65535,"ImageWidth":480,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
8|{"Orientation":1,"XResolution":[216],"YResolution":[216],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":1242,"PixelYDimension":2688}}
9|{"ImageWidth":1080,"ImageHeight":2103,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
10|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1145,"ImageWidth":720,"SubExif":{"LightSource":0}}
10|{"ImageWidth":1080,"ImageHeight":1964,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
11|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1860,"ImageWidth":1080,"SubExif":{"LightSource":0}}
11|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2148,"ImageWidth":1080,"SubExif":{"LightSource":0}}
12|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":924,"ImageWidth":540,"SubExif":{"LightSource":0}}
12|{"LightSource":0,"Orientation":0,"ImageHeight":1134,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
13|{"ImageWidth":1080,"ImageHeight":2074,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
13|{"LightSource":0,"Orientation":0,"ImageHeight":1860,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
13|{"Orientation":1,"XResolution":[216],"YResolution":[216],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":1125,"PixelYDimension":2001}}
14|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2576,"ImageWidth":1440,"SubExif":{"LightSource":0}}
15|{"ImageHeight":1230,"Orientation":0,"ImageWidth":720,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
15|{"ImageWidth":1080,"ImageHeight":1971,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
16|{"ImageWidth":1080,"ImageHeight":1859,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
16|{"ImageWidth":1080,"ImageHeight":2097,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
18|{"ImageHeight":762,"Orientation":0,"ImageWidth":480,"ExifIFDPointer":94,"SubExif":{"LightSource":0,"MeteringMode":65535,"InteroperabilityIFDPointer":136}}
19|{"ImageWidth":1080,"ImageHeight":1932,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
20|{"ImageWidth":1080,"ImageHeight":2026,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
20|{"LightSource":0,"Orientation":0,"ImageHeight":1701,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
21|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2031,"ImageWidth":1080,"SubExif":{"LightSource":0}}
23|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1716,"ImageWidth":1080,"SubExif":{"LightSource":0}}
23|{"LightSource":0,"Orientation":0,"ImageHeight":922,"MeteringMode":65535,"ImageWidth":540,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
24|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1701,"ImageWidth":1080,"SubExif":{"LightSource":0}}
27|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1230,"ImageWidth":720,"SubExif":{"LightSource":0}}
27|{"ImageWidth":720,"ImageHeight":1432,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
28|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1432,"ImageWidth":720,"SubExif":{"LightSource":0}}
28|{"ImageWidth":1080,"ImageHeight":1939,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
29|{"LightSource":0,"Orientation":0,"ImageHeight":1845,"MeteringMode":65535,"ImageWidth":1080,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
30|{"ImageWidth":1080,"ImageHeight":2037,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
31|{"ImageWidth":1080,"ImageHeight":1720,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
33|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1845,"ImageWidth":1080,"SubExif":{"LightSource":0}}
37|{"ImageWidth":1440,"ImageHeight":2864,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
37|{"LightSource":0,"Orientation":0,"ImageHeight":1230,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
37|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":828,"PixelYDimension":1792}}
38|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2157,"ImageWidth":1080,"SubExif":{"LightSource":0}}
38|{"ImageWidth":1080,"ImageHeight":1731,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
38|{"LightSource":0,"Orientation":0,"ImageHeight":1232,"MeteringMode":65535,"ImageWidth":720,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
39|{"ImageWidth":1080,"ImageHeight":1944,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
42|{"ImageWidth":720,"ImageHeight":1336,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
44|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":764,"ImageWidth":480,"SubExif":{"LightSource":0}}
44|{"ImageWidth":720,"ImageHeight":1232,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
45|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2004,"ImageWidth":1080,"SubExif":{"LightSource":0}}
49|{"ImageWidth":720,"ImageHeight":1136,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
53|{"ImageWidth":1440,"ImageHeight":2858,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
62|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2476,"ImageWidth":1440,"SubExif":{"LightSource":0}}
64|{"ImageHeight":1701,"Orientation":0,"ImageWidth":1080,"LightSource":0,"MeteringMode":65535,"ExifIFDPointer":118,"SubExif":{"JPEGInterchangeFormat":148,"JPEGInterchangeFormatLength":0}}
71|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2708,"ImageWidth":1440,"SubExif":{"LightSource":0}}
74|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1238,"ImageWidth":720,"SubExif":{"LightSource":0}}
76|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1136,"ImageWidth":720,"SubExif":{"LightSource":0}}
76|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1328,"ImageWidth":720,"SubExif":{"LightSource":0}}
76|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":640,"PixelYDimension":960}}
80|{"ImageWidth":1080,"ImageHeight":1704,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
80|{"ImageWidth":1080,"ImageHeight":2159,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
81|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1984,"ImageWidth":1080,"SubExif":{"LightSource":0}}
88|{"ImageWidth":1080,"ImageHeight":2094,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
93|{"Orientation":0,"ExifIFDPointer":70,"SubExif":{"MeteringMode":65535,"LightSource":0}}
98|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1857,"ImageWidth":1080,"SubExif":{"LightSource":0}}
114|{}
132|{"ImageWidth":1440,"ImageHeight":2464,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
137|{"ImageWidth":1440,"ImageHeight":2708,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
141|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1704,"ImageWidth":1080,"SubExif":{"LightSource":0}}
142|{"ImageWidth":1080,"ImageHeight":2060,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
143|{"Orientation":1,"XResolution":[0],"YResolution":[0],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":640,"PixelYDimension":1136}}
145|{"ImageWidth":1080,"ImageHeight":2148,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
152|{"ImageWidth":1080,"ImageHeight":1857,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
167|{"ImageWidth":1080,"ImageHeight":2157,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
198|{"ImageWidth":1080,"ImageHeight":1722,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
201|{"ImageWidth":1080,"ImageHeight":2004,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
202|{"ImageWidth":1080,"ImageHeight":2031,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
222|{"ImageWidth":1080,"ImageHeight":1736,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
260|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1722,"ImageWidth":1080,"SubExif":{"LightSource":0}}
280|{"Orientation":1,"XResolution":[0],"YResolution":[0],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":750,"PixelYDimension":1334}}
318|{"ImageWidth":1080,"ImageHeight":1968,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
328|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1160,"ImageWidth":720,"SubExif":{"LightSource":0}}
396|{"Orientation":1,"XResolution":[216],"YResolution":[216],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":1242,"PixelYDimension":2208}}
447|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":2464,"ImageWidth":1440,"SubExif":{"LightSource":0}}
476|{"ImageWidth":1080,"ImageHeight":1848,"ExifIFDPointer":94,"Orientation":0,"SubExif":{"LightSource":0}}
508|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1848,"ImageWidth":1080,"SubExif":{"LightSource":0}}
575|{"Orientation":1,"XResolution":[216],"YResolution":[216],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":1125,"PixelYDimension":2436}}
757|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1740,"ImageWidth":1080,"SubExif":{"LightSource":0}}
873|{"ExifIFDPointer":94,"Orientation":0,"ImageHeight":1232,"ImageWidth":720,"SubExif":{"LightSource":0}}
1048|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":640,"PixelYDimension":1136}}
2379|{"Orientation":1,"XResolution":[144],"YResolution":[144],"ResolutionUnit":2,"ExifIFDPointer":90,"SubExif":{"ColorSpace":1,"PixelXDimension":750,"PixelYDimension":1334}}
    
That is a total of 166 rows that sqlite returns. A nice increase in groups.

How much more will it be if I combine exif and width and height?
sqlite> select count(*) from ( 
  select * from images 
  group by json_remove(exif, "$.DateTime"), width, height
);

173
    
Just a small jump in group count.

Fourth insight. There are 173 unique combinations of exif, width and height in my area

So what does this mean for a users anonymity and untraceable content across threads?

It all comes down to how rare your smartphone is. If you fall into huge group you are probably safe. Just by looking at meta data it will be hard to identify which images are yours.

In case you decided to go with an unusual phone you run danger your images can be grouped into a profile by an outside analyst.

The rarer your phone the higher is the risk falling victim to a successful profiling.

*that graph ist just for the lulz If you ask me, I would say every user that falls into a group which consists of less than 20 images is under the highest risk. It wouldn't be hard to go over that many images and assign them manually to a person either by just looking at them or doing covert interrogation of the poster.
sqlite> select count(*) from (
  select count(*) as c 
  from images 
  group by json_remove(exif, "$.DateTime") 
) where c < 20;

100

These are at minimum 100 users in my area from which all the probed images are.

I cannot say what percentage of overall users within my town are affected because there is not really a way to know for an outsider how many users the app has.

What I can tell is there are on average 3000 user interactions (comments or posts) daily. The highest count of unique users commenting a post was 109 in recent times. Only 5.2 unique users interact with a post on average by creating 10.7 comments.

Other than throwing your phone away and getting a popular iPhone to hide in the masses there is not much one can do. Jodel needs to change the app so their camera implementation does not set exif tags or immediately delete them. As well they can simply strip all meta data from the images after uploading.

If that would happen their still would be 82 - some big and some frightening small - groups to categorize an upload. And this all by just looking at the width and height of the image itself.

I have no idea how it is that some images have such uncommon dimension. Is it the camera unit itself or some strange cropping logic of the Jodel app?

If you know more. Tweet at me :)