网络安全:图片隐藏攻击

我们知道网络无时无刻不在受着威胁。当一些恶意脚本被上传到服务器上时,网站就会面临被侵入的威胁。然而上传恶意脚本并不容易,因为文本形式的东西,我们很好设置过滤条件,把认为有威胁的文本过滤掉,不让它上传到服务器上,这样就能有效的避免很多不必要的麻烦。

 

举个例子,看眼前。

 

我写了这篇文章,编辑,保存,发布。这篇文章就被保存进了CSDN的数据库里。当你们想查看这篇文,去请求服务器时,服务器就会从数据库里调这篇文章发给你。

 

试想我在文章里写了这么一句话:

<script>alert("This is a joke")</script>

 

如果服务器不加处理的就把它保存进了数据库,会怎样?

 

你们每个点开的人的页面上都会弹出“This is a joke”的消息框。那不就乱了套了!

 

那浏览器是怎样把上面的那句话解释成文本显示出来,而没有把它理解成标签去执行呢?

 

你现在就可以右键查看源码,看看源码里面,那句脚本被表示成了什么样子。(快捷键ctrl + u)

 

这其实就算一种对文本的过滤,服务器不会把你的东西原封不动的保存在数据库里,要把你的文本过滤过滤,把可能有问题的东西修改掉,或者直接丢弃。因为,你不值得信任,无论是因为蠢,写错了;还是太聪明,故意的。都不会!

 

下面的评论也是一样,服务器不会把内容原封不动的存起来。

 

接下来的这篇文章就来谈另一种上传漏洞。

 

文本你过滤,那我换图片喽!攻防的交换就是如此,在斗争中不停地进步。

 

我拿这张图片做测试。

 

这是张jpg格式的图片,我先把它转成了bmp格式。倒没有什么特殊的原因,bmp的文件结构相对其他的来说比较简单。如果你对其他图片格式的文件结构了解颇深的话,不需要做多余的操作。往下走就行,原理都是一样的。

 

你可以通过mspaint另存为bmp格式,或者通过python的PIL库,亦干脆用工具转换都可以。

 

我没办法把处理好的图片上传上来,原因你懂得。因为它有问题,服务器检测出来了。

 

先来分析下图片,用二进制形式读取图片输出一部分看看:

                  

 

前两个字节是BM(因为这张图片是处理过的,所以bm后面有/*,先忽略掉它),有的地方把它叫做“魔数”。摘段百度百科的解释:

 

如果你有可以打开图片的编辑器,比如notpad++之类的。你就会看到一堆16进制表示的数字。python解释器用文本的方式解释了二进制文件,所以我们看到了BM(其实就是输出了它的ASCII码对应的字符)。在编辑器里,用十六进制表示的话是42 4D。

 

(拿十六进制的42来说,二进制就是 0100 0010,这里只是拿十六进制的方式显示了出来。)

 

魔数用于识别文件,换句话说只要保留住BM,管它后面是什么东西,都能被识别为bmp图片。

 

而你需要做的是,保留BM,把之后的东西用/* */注释掉,再在图片最后插入脚本。当然所有的插入,都需要以二进制的格式。

 

至于为什么中间注释的东西还要留着而不是去掉呢?嗯......因为它毕竟是张图片,图片显示的时候是一个个的像素点,没有这些东西,图片也就显示不出来了。虽然对你的脚本没什么影响。

 

这里有个问题,比如原来的表示是

BM\x00\x00\x00\x00\x00......,你现在在BM后面插入了/*,十六进制表示是\x2F\x2A。在IDLE里显示一下就可以了:

                                                        

那现在的表示就变成了,BM\x2F\x2A\x00\x00\x00\x00\x00。

 

显示图片时,原来是\x00是第一个像素点,然后显示第二个像素点,再之后是第三个。

 

现在处理完后,所有的像素点显示都向后推了两个点。那图片的显示不就乱套了?

 

的确会有出入,但是整体的图片还是可以显示的。(以上的例子只是说明,其实BM之后的字节并不是显示的像素点,而是文件的大小,这里只是说明问题。)

 

我把原图和处理完的图片贴出来,对比下。

处理完毕的图片显然显示上有些小瑕疵。(PS:第二张图是截图,不是处理后的图片原图。原因说了,服务器不要。)

 

那就来看这张“有料”的图片是怎么做出来的吧(语言:python)。(虽然原理已经讲得很清楚了。)

 

#read data of the picture
with open(fname, 'r+b') as f:
    buff = f.read()

#replace * and \ in buff
buff = buff.replace(b'\x2A', b'\x00').replace(b'\x2F', b'\x00')

 

先把图片以二进制的形式读出来,然后替换。前面说了十六进制的\x2A是*,\x2F是/。

 

为什么要替换掉呢。其实是因为在js里面/*是注释嘛,只是怕图片的像素点表示恰好和它相同了,导致最后文件出错,脚本执行不了。

 

with open(fname, 'w+b') as f:
    f.write(buff)
    f.seek(2, 0)
    f.write(b'\x2F\x2A')

 

之后再次打开图片文件把替换后的内容写进去。(覆盖掉了原文件)

 

seek不需要过多解释了吧,默认你有python基础。因为我们要留下bm来识别图片,所以文件指针后移2字节。没有第二个参数也可以(默认的)。

 

然后填入\x2F\x2A,已经很熟悉了,其实就是/*

 

那我们的脚本写什么呢?

 

新建个文本吧:

 

这里只写一句话,然后把它以二进制形式添加到图片文件后面。

with open('test.txt', 'rb') as f:
    script = f.read()

with open(fname, 'a+b') as f:
    f.write(b'\x2A\x2F\x3D\x31\x3B')
    f.write(script)

写入脚本之前添加了什么东西呢?

当然是要把前面的“  /*  ”闭合掉了,这样中间的数据才能被注释。后面的=1;呢?

 

别忘了,我们前面还有个BM呀。如果忽视掉注释,最后就剩下了:

bm=1;
alert("You are hacked!!!");

=1;只是为了让语法没错误,能够成功执行到alert语句。

( js语言是弱类型语言, 变量无需声明即可直接使用, 默认是作为全局变量使用的。)

 

完整代码:

fname = '1.bmp'

#read data of the picture
with open(fname, 'r+b') as f:
    buff = f.read()

#replace * and \ in buff
buff = buff.replace(b'\x2A', b'\x00').replace(b'\x2F', b'\x00')

#overide the picture and add /* in the end of it
with open(fname, 'w+b') as f:
    f.write(buff)
    f.seek(2, 0)
    f.write(b'\x2F\x2A')

with open('test.txt', 'rb') as f:
    script = f.read()

with open(fname, 'a+b') as f:
    f.write(b'\xFF\x2A\x2F\x3D\x31\x3B')
    f.write(script)

代码上没有任何难度,只是逻辑上理清即可。

 

这张图片算是处理完了。那来试试?

 

简单写个界面吧。

看下图片能否显示出来,再看下脚本能否运行。

 

浏览器看下:

图片能正常显示,脚本也能正常运行。

 

很完美的伪装啊。

 

这里可能有个疑问了,src还能指定二进制文件啊!搞不懂。

 

https://www.cnblogs.com/bibiafa/p/9366505.html

这里引用下,无论你指定的是什么,我都是按照文本形式读的。(也就是把那些十六进制数字转成对应的ASCII码字符。)

 

举个简单的例子,我们用txt打开个二进制文件,会出现什么景象?乱码。

 

你文件的存储方式是二进制,而txt的读取方式是文本,用文本方式读取出来,当然就乱了。有些图片jpg格式换成别的格式就不能显示了,也是这种原因,存储方式和读取方式不匹配。

 

src给script指定的文件,无论是什么,他都会把它当成文本插入到script标签之间。

 

别忘了,我们的脚本是转成二进制之后存进去的,而不是直接放进去。script往外读的时候,那些像素点肯定是不知道啥意思,不过没关系,反正我们也注释了。但是我们后面的脚本读出来就不一样了呀。

 

 

前面我们已经展示了,读出来是什么。

 

而我们插入的时候恰恰反过来,根据文本转成二进制插回去,现在你做的就是再读回来而已。

 

应该解释清楚了吧。

 

换言之,我们的页面等同于:

<img src="1.bmp" />
<script>
BM/* xxxxx */=1;
alert("You are hacked!!!")
</script>

只是我们没有显示的写在网页上,而是隐藏在了图片里。

 

嗯,这就是全部的内容了。

 

这篇文章的意义在于说明图片攻击方式,获得知识的同时,也培养一种安全意识。另一方面,我们博客的服务器还是相当给力的哈。有问题的图片不让你上传。点个赞。

 

(记:文章中许多点,有些我不会解释,有些解释不到位。不妥处评论指出,我会把您的评论帖进来。)

发布了53 篇原创文章 · 获赞 80 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41500251/article/details/91645290