最近看到一个有趣的网页: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
脚本藏在图片中,并能后期执行,那就有意思了;而且本身是一个图片文件,可以避过一些安全软件的检查。
网络安全入门学习路线
其实入门网络安全要学的东西不算多,也就是网络基础+操作系统+中间件+数据库,四个流程下来就差不多了。
1.网络安全法和了解电脑基础
其中包括操作系统Windows基础和Linux基础,标记语言HTML基础和代码JS基础,以及网络基础、数据库基础和虚拟机使用等...
别被这些看上去很多的东西给吓到了,其实都是很简单的基础知识,同学们看完基本上都能掌握。计算机专业的同学都应该接触了解过,这部分可以直接略过。没学过的同学也不要慌,可以去B站搜索相关视频,你搜关键词网络安全工程师会出现很多相关的视频教程,我粗略的看了一下,排名第一的视频就讲的很详细。 当然你也可以看下面这个视频教程仅展示部分截图: 学到http和https抓包后能读懂它在说什么就行。
2.网络基础和编程语言
3.入手Web安全
web是对外开放的,自然成了的重点关照对象,有事没事就来入侵一波,你说不管能行吗! 想学好Web安全,咱首先得先弄清web是怎么搭建的,知道它的构造才能精准打击。所以web前端和web后端的知识多少要了解点,然后再学点python,起码得看懂部分代码吧。
最后网站开发知识多少也要了解点,不过别紧张,只是学习基础知识。
等你用几周的时间学完这些,基本上算是具备了入门合格渗透工程师的资格,记得上述的重点要重点关注哦! 再就是,要正式进入web安全领域,得学会web渗透,OWASP TOP 10等常见Web漏洞原理与利用方式需要掌握,像SQL注入/XSS跨站脚本攻击/Webshell木马编写/命令执行等。
这个过程并不枯燥,一边打怪刷级一边成长岂不美哉,每个攻击手段都能让你玩得不亦乐乎,而且总有更猥琐的方法等着你去实践。
学完web渗透还不算完,还得掌握相关系统层面漏洞,像ms17-010永恒之蓝等各种微软ms漏洞,所以要学习后渗透。可能到这里大家已经不知所云了,不过不要紧,等你学会了web渗透再来看会发现很简单。
其实学会了这几步,你就正式从新手小白晋升为入门学员了,真的不算难,你上你也行。
4.安全体系
不过我们这个水平也就算个渗透测试工程师,也就只能做个基础的安全服务,而这个领域还有很多业务,像攻防演练、等保测评、风险评估等,我们的能力根本不够看。
所以想要成为一名合格的网络工程师,想要拿到安全公司的offer,还得再掌握更多的网络安全知识,能力再更上一层楼才行。即便以后进入企业,也需要学习很多新知识,不充实自己的技能就会被淘汰。
从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。
尾言
因为入门学习阶段知识点比较杂,所以我讲得比较笼统,最后联合CSDN整理了一套【282G】网络安全从入门到精通资料包,需要的小伙伴可以点击链接领取哦! 网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!