In Chrome, you can just do as the author says, right click and "Save Image As".
Then just go to the folder where it is being downloaded, and copy/paste the file "lisa.jpeg.crdownload" to "lisa.jpeg.crdownload copy".
Rename to "lisa.jpeg" and cancel the download. You now have the image. What's interesting is that you ARE actually downloading this image. It's just that they don't terminate the connection.
We have a security proxy at work that gives you the bits, but then holds the connection open while it does a scan, then resets the connection if it doesn't like something inside. Both Chrome and Firefox [haven't tried IE/Edge, but I assume that they'll do something that the proxy vendor would want] infer [or are told?] that the connection broke and delete the interim file. Unfortunately, with zip files, the header is at the end; so it can't do scanning until the whole file is down.
For me, the easiest way to mitigate it turned out to be to use wget [with an appropriate user-agent... say, the same as my desktop browser]. wget Gets the bits, but doesn't in any way molest the "partial" download when the connection resets. Then it tries to download the rest using the "Range" HTTP header, and the server says "oh, dude, you already got the whole thing"; wget declares success, and all the bits are in my download folder.
I believe that we pay, like, a lot for this proxy, which is annoying on two counts: 1) If I can get past it trivially, then presumably competent attackers can, too, and 2) Sometimes it takes a dislike to legitimate stuff, which is how I was forced to learn how to get around it.
Those controls on a proxy are to protect against the careless and the clueless. No competent security team will rely on them to prevent ingress/egress of data or malicious code by skilled individuals.
Correct - this is an attack on the other side of the airtight hatchway (i.e., you must persuade the user to run wget in a certain fashion and run the resulting exe, and if you don't need to persuade the user you could have done something simpler).
That's not how these proxies usually work. They only give you enough bytes so the browser doesn't feel stuck while downloading everything and scanning it. The download then suddenly continues at 100 or even 1000 Mbit/s.
Indeed that's what I've experienced in the past. But I'm telling you this, for sure, based on my experience downloading a 200M tensorflow wheel the other day.
I don't understand what this website is supposed to be demonstrating. Some sort of genius version of disabling right click I suppose. But I did download the image, because its contents were transferred to my computer's memory and displayed on my screen. I can see it clear as day.
If Web 3 is just willfully misunderstanding how computers work, I don't see a very bright future for it.
(Most) browsers actually start displaying an image before it's fully downloaded. In fact, many image formats/renderers are specifically designed with this property in mind, like jpeg which will render progressively less blurry versions of an image as the browser receives progressively higher-frequency components of the Fourier transform.
While the bytes are there temporarily, just like with all the other methods discussed, chrome at least eventually give up on downloading the "whole" image and displays a broken image sign in place of the Mona Lisa (and presumably prevents it from being cached and deletes what was there)
it would be interesting if the download stopped after the second to last progressive layer but before the last byte; then the .crdownload renaming workaround wouldn't work.
The problem with leaving connections open is that there's a limit on how many you can have on the server... I think the author has committed self-DoS :)
It would be possible to really close the connection but hack something to don't inform the client. (maybe just doing close() with SO_LINGER=0 and dropping outgoing RST in iptables would be enough)
Yes, browsers probably have their own relatively short timeouts. (curiously enough, system TCP stack will never close idle connections by default, and even if application requests SO_KEEPALIVE, default intervals are usually in hours range)
1000… pft.. just holding open a connection and sending on average a few bytes a second hardly costs anything and the memory requirements on eg Linux are minimal. You can easily do 100k or more with python and a few hundred megs of memory. Millions are doable with something a little less memory hungry or throwing more memory at it.
In fairness to them, a lot of programmers didn't come up the way (we presumably) did - if you started using computers/programming in the 80's and building computers in the 90's your worldview is going to be fundamentally different to someone who started in 2018.
We came from a world where bytes mattered they come from a world where Gigabytes matter.
In some ways caring about that stuff can be detrimental, at the back of my mind there is always that little niggle - you could do this in 1/10th the runtime/memory cost but it'll take twice as long to write and you'll be the only one who understands it.
These days we don't optimise for the machine but instead for the human time and honestly, that's an acceptable trade off in many (but not all) cases.
It can be frustrating when you remember how much of an upgrade getting a 286 was over what you had, that I now routinely throw thousands of those (in equivalence) at a problem inefficiently and still get it done in under a second.
When you usually try to download an image, your browser opens a connection to the server and sends a GET request asking for the image.
I'm not a web designer, but that seems rather ass-backwards. I'm already looking at the image, therefore the image is already residing either in my cache or in my RAM. Why it is downloaded a second time instead of just being copied onto my drive?
Okay? So we still seem to have an accurate representation of the image we want. Why can't I just download that and what's the point of the rest of the data. If we already are seeing the image, the rest of the data is pointless no?
You can totally "download" the image in your RAM by right clicking / long pressing -> "copy image" or equivalent in most browsers. It's just not going to be a byte by byte identical file, and may be in a different format, e.g. you get a public.tiff on the clipboard when you copy an image from Chrome or Safari on macOS, even if the source image is an image/svg+xml.
As far as I remember from a previous project from a few years ago, the browser doesn't include a referrer for the download request, which can be used for a distinction. (You'll have to disable caching and E-Tags for this to work.)
However, this is easily defeated by the use of the console: Select the sources tab, locate the image and simply drag-and-drop the image from there, which will use the local cache instance for the source. Works also with this site, at least with Safari.
I guess, this is for historical reasons. Mind that there is no such thing as a single, cached image. There's the downloaded content, a decoded bitmap derived from this, a buffer for any instance of the image, which may be clipped or distorted (and may have local color management applied, e.g., converted to 8-bit color range). (At least, it used to be that way. I faintly remember that this used to be a 4-step process.) When memory wasn't ample, any of these, but the instance buffer(s), may have been purged, and an instance buffer doesn't represent the original image anymore. So it makes sense to get a new clean image in the original encoding.
They don’t already have the image. They have part of the image. Because the connection hasn’t closed, as far as the browser is concerned, it’s still in the process of downloading it.
I have problem understanding what problem is this solving?
When the image is on my screen I can just screenshot it.
This is a common problem, using something in insecure environment, thats why companies are going into such extents to encrypt movies on whole train from source to the display and even those are regularly dumped.
And even if they figured out some DRM method to prevent screenshotting/screen recording, I can still point my phone camera at my monitor and capture it that way, if I really want to. There is always a way around whatever they try to do.
> I can still point my phone camera at my monitor and capture it that way
Back in the late 1990s/early 2000s (this was so long ago that I cannot quickly find a reference), there were proposals to require all non-professional audio and video recorders to detect a watermark and disable recording when one was found. Needless to say this was a terrible idea, for several reasons.
I don't know about browser internals, but I would guess that the browser decodes the image once into a format that can be shown on the page (so from PNG/JPG/WEBP into a RGBA buffer) and then discards the original file. This saves a bit of memory in 99.99% of cases when the image is not immediately saved afterwards.
More likely the original file is saved in the browser cache. That's why it loads faster when you reload the page, and slower when you do a full reload by holding down shift. In Firefox you can see the files with about:cache, and find them in ~/.cache/mozilla/firefox/e1wkkyx3.default/cache2/entries/ or similar (they have weird names with no extension, but the file command will identify them, in their original format). In Chrome they're packed into files with metadata like the URL at the start. You can extract the original file by looking at a file in the cache folder [1] and snipping the header off (you can guess where it is by looking at the file contents with xxd or a hex editor).
Interesting if that is the explanation. I wonder if any browsers offer a "privacy mode" where the original images are saved, thereby preventing the server from knowing which specific images you chose to save and were therefore interested in. I wonder how often that information is logged, and whether those logs, if they exist, have ever been put to a purpose such as in a court case.
I'm pretty sure it only discards the original after x number of other (new) images have been decoded. (Or perhaps it's memory footprint based?)
I ran into a Chrome performance bug years ago with animations, because the animation had more frames than the decoded cache size. Everything ground to a halt on the machine when it happened. Meanwhile older unoptimized browsers ran it just fine.
One cool related thing is that (I believe) modern graphics cards (even Intel) can store and use JPG blocks directly from GPU memory, so it's not necessarily beneficial in the long term to convert to RGBA in advance. Though I think no modern browser actually does this, especially given how power-cheap decoding jpeg (with SIMD) already is and how likely it is that gpu bugs would interfere.
I don't think they can use jpg directly, that would be a waste of transistors given that the graphics world use other compression formats like etc1, bc, astc and so on.
It is however perfectly possible to decode blocks of JPG on a GPU by using shader code.
I'm pretty sure that Safari (and probably most browsers) on MacOS renders JPEGs via CoreImage, and I have seen hints that CoreImage has various GPU-accelerated pathways, though I don't know whether those include DCT or JFIF on the GPU.
There's another way to achieve this in a more malicious way. Granted I haven't tried it in years, but it was possible back in 2017 when I tested it.
The idea is to fake the image that's being displayed in the IMG element by forcing it to show a `background-image` using `height: 0;` and `padding-top`.
In theory, you could make an IMG element show a photo of puppies and if the person chose to Right-click > Save Image As then instead of the dog photo it could be something else.
For some reason I can't Oauth into Codepen so for now I can't recreate it publicly.
You could also just do like we did for years and check the refer for the image request, and if it wasn't your web server you redirect the file to whatever you want, the end user has know what of knowing. and because the trick is done on the server side then viewing your source won't get around it.
This is the same method used to prevent hot linking to images back in the day.
The shortest route yes, but I'd rather whitelist check, because depending on your infra, there might be a lot more things that make request for the content.
But the concept is the same, server side check the ip of the request, and take action based on that check.
Not very new, the technique's probably been around since the 2000's... e.g. you can't right click, save as on the web version of Instagram because all the images are background-images attached to DIVs. In the "old days" there'd be a 1x1 transparent GIF above the image, so any downloader would download that instead.
This does create a self inflicted Slowloris attack on the server hosting the image, so this site is probably more susceptible to the hug of death than most
It always baffled me browsers even try to download an image (or a page or whatever) I asked them to save despite fact they have already downloaded and displayed it. What I would want them to do instead is just dump it from the memory.
And this sounds particularly important in case it's about a web page which has been altered in runtime by JavaScript - I want the actual DOM dumped so I can then loaded it to display exactly what I see now.
If there was a standard checksum request within HTTP, sure. Otherwise you're going to break some workflows with this kind of aggressive caching. Maybe it should be an opt-in setting (and maybe it already is).
Add
-N, --no-buffer
Disables the buffering of the output stream. In normal work situations, curl will use a standard buffered output stream that will have the effect that it will output the
data in chunks, not necessarily exactly when the data arrives. Using this option will disable that buffering.
I hate it when people do that. You can wonder for hours why something obvious doesn't work as it should and in the end discover someone decided to implement something substandard, often for no good reason.
Well, Windows too. I recently had to set up something simple on a Windows 10 machine, I quickly checked by tab-completion if a python binary is available so I copied by setup script only to discover someone smart decided to redirect the binary to the Windows Store. Yes, I know the rationale behind this, but still. Just like hijacking nxdomain.
Same for me, but the webpage gave the impression that it was still downloading, because after it download completely, at least in firefox on iPhone, it’s still showing that it was downloading.
This is a perfect (if maybe unintentional) example of how to get help from otherwise disinterested technical folk: Make an obviously technically-incorrect claim as fact, and watch as an entire army comes out of the woodwork giving you technical evaluations :)
I’m aware of this phenomenon, but have never tested it (confidently posting something incorrect to get responses with the real answer). Has anyone here actually tried this? How did it work?
Anthony Bourdain used to find the best local cuisine by going onto message boards (anonymously I assume) and saying X is the best restaurant, only to receive a flood of recommendations
If it happened in the worlds most used client OS 20 years ago, it's clearly not impossible it can happen again. Not that much has happened with computers since then.
I remember being like you, believing no virus could come from an image or other data. I have been proven wrong enough times since then. We keep assuming things as programmers and sometimes we get it wrong and then there is a new wulnerability.
using "filename" within the "Content-Disposition" header, you could theoretically trick a user into downloading a non-image file despite the url containing lisa.jpg
I think certain browsers have security limits on the file-extensions you download, which may include when image->"save as" is used.
Don't forget that you can literally concatenate jpegs and zipfiles [header at start of jpeg, but at end of zipfile], so the valid jpeg can also be a valid zipfile.
Combine that with something like Safari's insistence at automatically exploding zipfiles on download, and you got yourself a party.
No, they DoS'd themselves with their "viewable but not save-as-able" technique. Leaving connections open will do that. The image is visible right now but the browser can't save what appears to be an incomplete file.
In Chromium based browsers the quickest method I've found is "right click -> Inspect" the image then click the sources tab in the dev tools window. From here you can drag or save the image shown without issue. My guess as to why this works is the sources view seems to pull from the loaded content of the page rather than fetch the content based on the lack of packets trying this with a packet capture running.
In Firefox, beside that, you can press Ctrl + I, open the "Media" tab, and pick any of the graphics that were already downloaded to display the page. Then you can save the picture(s) you're interested in. I suppose the source of it is the local cache.
Does not work in this particular case, of course, because the whole image is not yet in the cache.
It also works in this case, too: at some point the connection does close (if it doesn't, just hit escape) and you can save the image as usual, now from the cache.
Great! Just what we need these days: more tricks to screw around with the simple, straightforward implementation of the HTTP protocol! And just in time for Christmas.
I thought this is what it was going to be! Another method would be to generate a plane with the same number of vertices as pixels, store the pixel color values as an attribute, and then render the mesh to a canvas.
Email clients generally don't load external images. The majority should still display images that are sent as part of a multipart/mixed message though, and those should take up significantly less space than thousands of divs/tds and color attributes.
(Or see https://www.masswerk.at/demospace/relayWeb_en/welcome.htm and select "charts". Total time for calculations and rendering was then in the about 1 sec range. The real problem for using this in production was that these charts could be printed on Windows with Postscript printers only. I think, this was eventually fixed in Windows 98 SE.)
This sure seems like a weakness of the so-called "modern" web browser. Simpler, safer clients and proxies have no trouble dealing with a server that is (deliberately) too slow.
On Google Pixel there is a new feature where I can go to the recent app screen and it defects images to click on them to do Google lense or save images or share image. I was able to save the image of size 506kb with 841x1252 1.1MP pic.
Works fine with wget it just keeps hanging but if you CTRL+C it and open the file it'll look fine.
The trick is to have nginx never timeout and just indefinitely hang after the image is sent. The browser renders whatever image data it has received as soon as possible even though the request is never finished. However, when saving the image the browser never finalizes writing to the temp file so it thinks there is more data coming and never renames the temp file to the final file name.
My usual way of downloading images is to click and drag the image into my downloads folder on my Mac. Worked fine for me from Safari. Am I missing something?
Aside from all the folks who can download the image one way or another, I'm pretty disappointed that the technique here is simply using a web-server that doesn't work like clients expect. People have broken links or incorrect redirects all the time, but we don't generally make a fuss over them.
Yeah, I couldn't figure what the fuzz is about at first, as I simply right-clicked, copied and pasted into mspaint. I rarely need to save an image, more often than not I just paste it into some other application.
An interesting workaround for Android 12 users: go to the app switcher and there will be a badge over the image which you can click to get "copy", "share" and "save" buttons. Save it from that panel and it works just fine.
that's a great idea. * i also thought could just load a jsonp file with the string in it but no matter what, maybe can't get around it, when i put the string as image.src = '' it puts it into chrome network under media
No one seems to mention that Chrome keeps spinning on the HTML load as well and eventually kills the image. This means the webpage itself is broken and fails to work. Not just the download. Soo.. this just does not work for anything..
This is basically a carefully targeted reverse slow lorris and involves right clicking an image why do I fear that use case and that level of madcap solution will all lead back to NFT bros...
This one is pretty easy but a friend recently showed me one (gallery of some sort) I couldn't figure out quickly which was downloading chunks in nonstandard ways and piecing them together with uglified js.
Somehow right clicking + saving worked fine on Safari (desktop). I tried it a couple of times and it worked in all cases; sometimes it took a second, sometimes more. Perhaps the server dropped the connection?
On webkit based browsers at least you can just drag the image out, it doesn’t bother trying to redownload it just reconstructs the image file from memory, this also applies to copy/paste on ios
There's a multitude of ways to workaround this hack. You can easily grab the screen area via the OS if need be. Seems pointless to try to restrict access if it's viewable in a browser.
what, sure if initiating the save as.. triggers this endless download thing
but the initial load is the image and opening up dev tools and finding it in the sources/cache and saving it from there, chrome knows it's 56.1kb or whatever and just saves it out of cache, done.
Interesting but what was the point they're trying to make?
Did you even try this before posting? These steps are no different than just right-clicking the image and choosing "Save image as". It still results in a download that never finishes.
I posted the same snarky comment too. Seems the headline should be “You can’t download this exact image, but you can copy the presentation image via other means.”
More of a play on words for how copy and download often times mean the same thing even though technically they’re different.
Then just go to the folder where it is being downloaded, and copy/paste the file "lisa.jpeg.crdownload" to "lisa.jpeg.crdownload copy".
Rename to "lisa.jpeg" and cancel the download. You now have the image. What's interesting is that you ARE actually downloading this image. It's just that they don't terminate the connection.