最近看到一个有趣的网页:lcamtuf.coredump.cx/squirrel/,或者说一张有趣的图片——因为用网络浏览器打开它看到的是一个网页,用图片浏览器打开它看到的又是一张图片。
在服务端要对同一个请求地址实现不同响应是十分简单的,比如通过请求头Accept
来判断:
Accept=text/html
则返回超文本;Accept=image/*
则返回图片;- ……
可是lcamtuf.coredump.cx/squirrel/这个网页(或者说图片)在脱离服务端的情况下,依然能够呈现出网页和图片两种文件内容,这是怎样实现的呢?
在前端没有秘密,打开网络浏览器的开发者工具查看一下网址的响应内容:
响应内容中有熟悉HTML标签,也有一大堆乱码。这堆乱码应该是图片文件的字符读码,但是为什么在网页上看不到呢? 原来HTML中使用了body { visibility: hidden; }
样式和<!--
注释标签(浏览器自动补全),乱码部分就这样被隐藏了。
HTML内容:
<html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; padding: 0 1ex 0 1ex; margin: 0; top: 0; left: 0; } h1 { margin-top: 0.4ex; margin-bottom: 0.8ex; }</style><div class=n><h1><i>Hello, squirrel fans<img src="http://lcamtuf.coredump.cx/squirrel/">Click here!</a></xmp><xmp><img src="http://lcamtuf.coredump.cx/squirrel/"></xmp><p>No server-side hacks involved - the magic happens in your browser. Let's try embedding the current page as an image right now (INCEPTION!):<p><img src="#" style="border: 1px solid crimson"><p>Pretty radical, eh? Send money to: lcamtuf@coredump.cx<!--" style="margin: auto" />
然而在查看图片的时候,也没看到HTML的内容,又是为什么呢?
JPEG相关
首先可以确定这张图片是JPEG格式,因为内容开头有明显的JFIF
标记(JFIF,是JPEG最常见的文件存储格式,也是标准的JPEG文件转换格式)。 JPEG格式定义了一系列标记码,都是以0xFF开头,常见的有:
0xFFD8
,SOI(Start Of Image),图片开始标记;0xFFD9
,EOI(End Of Image),图片结束标记;0xFFDA
,SOS(Start Of Scan),扫描开始标记;0xFFDB
,DQT(Define Quantization Table),定义量化表;0xFFC4
,DHT(Define Huffman Table),定义哈夫曼表;0xFFEn
,APPn(Application Specific),应用程序信息;0xFFFE
,COM(Comment),注释;- ……
图片的注释内容不会展示,很显然我们可以把HTML隐藏在图片注释中。 用十六进制读取这张图片,可以看到:
这张图片中使用了注释标记0xFFFE
,标记后面跟着0x0372
。0x0372
转成十进制是882
,而HTML内容的长度刚好是880个字节(0x0372
本身占2个字节),所以可以知道,HTML内容就是写在这张图片注释中。
代码实现
下面用PHP代码简单实现一个将HTML内容嵌入JPEG中的函数:
<?php
function embedHtmlInJpeg($jpeg_file, $html_str, $html_file) {$length = strlen($html_str) + 2;if ($length > 256 * 256 - 1) {return false;}$content = '';$reader= fopen($jpeg_file, 'rb');$writer= fopen($html_file, 'wb');$content = fread($reader, 2); // read 0xFFD8fwrite($writer, $content); // write 0xFFD8$header= 'FFFE' . sprintf('%04X', $length);$header= pack('H*', $header);$content = $header . $html_str;fwrite($writer, $content); // write 0xFFFEwhile (!feof($reader)) {$content = fread($reader, 8192);fwrite($writer, $content); // write else}fclose($reader);fclose($writer);return true;
}
// call it
embedHtmlInJpeg('lena.jpg','<html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; padding: 0 1ex 0 1ex; margin: 0; top: 0; left: 0; } h1 { margin-top: 0.4ex; margin-bottom: 0.8ex; }</style><div class=n><h1><i>This image is a page.</i></h1>Just open it in new tab.<p><img src="#" style="border: 1px solid crimson"><!--','lena.html');
这张图片是一个网页,不信你就在新标签页中打开它
点击这里体验。
实际应用
将一段HTML文本嵌入到一张图片中,实际上,还没什么应用,哈哈哈😂。 如果能将JS
或Shell
脚本藏在图片中,并能后期执行,那就有意思了;而且本身是一个图片文件,可以避过一些安全软件的检查。
网络安全成长路线图
这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成hei客大神,这个方向越往后,需要学习和掌握的东西就会越来越多,以下是学习网络安全需要走的方向:
# 网络安全学习方法
上面介绍了技术分类和学习路线,这里来谈一下学习方法:
## 视频学习
无论你是去B站或者是油管上面都有很多网络安全的相关视频可以学习,当然如果你还不知道选择那套学习,我这里也整理了一套和上述成长路线图挂钩的视频教程,完整版的视频已经上传至CSDN官方,朋友们如果需要可以点击这个链接免费领取。网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!