Web安全概览

前言

介绍一下 Web 端相关的攻击手法及原理,包括但不限于 前端 后端 运维javascript

本文后端语言将使用PHP,由于通过对比,PHP做为后端代码演示,是最显而易见的。php

以及本文介绍的全部攻击手法都将提供Docker 靶场,方便后续你们自行研究、测试。html

此篇文章是由我以前写的安全文章进行了部分汇总、优化及添加。若是你们比较感兴趣,能够去Freebuf Black-Hole看我以前写的文章。前端

前端

XSS

XSS本质就是在别人的浏览器里执行你的JavaScript代码,其余都是一种辅助手段。java

DOM XSS

利用JavaScript操做DOM的特性,来作到攻击git

常常出现的状况:先后端分离架构github

不少开发者,都知道不到万不得已不要使用eval函数,不使用的缘由其中一点就是不安全,可是难道不使用eval就不会有安全问题么?答案是否认的。web

见下面的代码:sql

<script>
  window.open(new URL(location.hash.slice(1)).href)
</script>复制代码

为了更好的说明,我这里简单的把做用说明一下:docker

假设当前url为 http://baidu.com/#http://360.cn,那么location.hash.slice(1)的结果就是http://360.cn

new URL(url).href则是会对url进行解析,并取出解析后的url。若是你的url不知足它内部的判断,则会报错。

是否是以为这段代码没什么问题。毕竟有new URL()这种浏览器内置函数帮咱们作了过滤。

OK,那咱们就要去攻破这个函数的判断。下图为URL接口规范中的列表:

咱们能够看到hello:world是符合规范的。并且hello:正好又是JavaScript里的标记,相似于C语言中的goto。那咱们更改url为: http://baidu.com/#javascript:alert(1)。则会成功触发漏洞。

Docker 靶场

后端

反射XSS

DOM XSS也属于反射型 XSS,通常而言统称都叫反射 XSS,只有当须要划分比较细时,才会分开来。

由于前/后端没有作好相对应的过滤,致使的问题

常常出现的状况:MVC架构

由于像MVC这种架构,实际上是在后端语言中编写前端代码,在访问url的时候,会先由后端根据请求去构造前端页面,再返回前端源码到浏览器端,而这个过程当中,若是出现了XSS漏洞,又由于后端参与其中,因此咱们通常认为这是反射型XSS

见下面的 PHP 代码:

<?php
  // 关闭浏览器的XSS检测机制
  header("X-XSS-Protection: 0;");

  $bg = $_GET['bg'];
  if (empty($bg)) {
    $bg = '999';
  }
  echo "<div style='width: 120px; height: 120px; background-color:#$bg'>我是一只小方块</div>";
?>复制代码

能够看到,这段代码将会获取url参数中的bg来获取背景颜色。乍一看,好像没什么问题。可是要知道其中$bg是可控的。那咱们只须要把里面的标签闭合掉就行。见下面:

http://127.0.0.1:8082/?bg=123' onclick='alert(1)

上面的代码放在bg参数里,那代码就变成了

<div style='width: 120px; height: 120px; background-color:#123' onclick='alert(1)'>我是一只小方块</div>

Docker 靶场

存储型XSS

在反射XSS的基础上,作了一步 入库的操做

见下面的代码:

// 获取客户端的IP地址
// 此段代码来之:https://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php
$ipaddress = 'UNKNOWN';
$keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
foreach($keys as $k) {
  if (isset($_SERVER[$k]) && !empty($_SERVER[$k])) {
    $ipaddress = $_SERVER[$k];
    break;
  }
}

// 获取内容,并对内容作编码过滤
$content = htmlspecialchars($_POST['content'], ENT_QUOTES);

$sql = "INSERT INTO xss.message (content, ip) VALUES ('$content', '$ipaddress')";
$conn->query($sql);复制代码

这段代码看起来是没有任何问题的,由于咱们已经对content参数作了进一步的编码过滤。

htmlspecialchars(string,ENT_QUOTES) 此方法的编码规则为:

& 编码为 &amp;

" 编码为 &quot;

' 编码为 &#039;

< 编码为 &lt;

> 编码为 &gt;

那即便咱们写入了HTML标签等代码,也会被转码,假如咱们提交的内容为<script>alert(1)</script>那在数据库的里表现就会变成: &lt;script&gt;alert(1)&lt;/script&gt;

那难道没有办法绕过去么?答案固然是能够。

能够看到,这段代码不止把内容入库了,还把用户的IP也入库了。那问题就出现了,CLIENT-IPX_FORWARDED_FOR是用户可控的。只须要安装 ModHeader 这个浏览器插件便可如图:

Imgur

修改后,再去从新提交一次,就会发现已经成功入库了,如图:

Imgur

Docker 靶场

CSRF

CSRF能够理解为是一种借刀杀人的手法,通常出如今表单提交里。最多见的是出现的开源项目里,好比各种CMS。

<form method="post" action="addAdminUser.php">
  <div class="input-group">
    <label for="username">要添加的管理员帐号: </label>
    <input type="input" name="username">
  </div>
  <div class="input-group">
    <label for="password">要添加的管理员密码: </label>
    <input type="password" name="password">
  </div>
  <div class="input-group">
    <button type="submit">添加</button>
  </div>
</form>复制代码

见上面代码,此代码存在于管理员后台里。用于添加管理员帐号。而且 addAdminUser.php 里是有对当前用户的 Cookies 作了校验,非管理员帐户不能添加。

可是这个表单里没有 验证码Token ,以及 addAdminUser.php 里没有作 referer 来源校验。

就会出现 CSRF 漏洞。

由于浏览器发现你请求了某个资源后,会自动把你未过时的 Cookies 加入到请求头里。也就是说,即便是在其余网站里,发送了添加管理员的请求,会自动把你登录后的 Cookies 加入到请求里,服务端会认为是你本人触发的(由于 Cookies 校验成功)

至于为何这里 Cors 没有起到做用,是由于这种方式,请求后是拿不到任何返回信息的,因此 Cors 并不会拦截。若是你使用 Ajax来请求,是确定会被拦截掉,由于 Ajax 请求是能够拿到返回信息,全部会被 Cors 拦截掉。

那除了 form 标签,还有什么方法能够进行攻击呢?在 w3c cors 规范中,有这么一句话:

A simple cross-origin request has been defined as congruent with those which may be generated by currently deployed user agents that do not conform to this specification. Simple cross-origin requests generated outside this specification (such as cross-origin form submissions using GET or POST or cross-origin GET requests resulting from script elements) typically include user credentials, so resources conforming to this specification must always be prepared to expect simple cross-origin requests with credentials.

----详情可见 w3c cors

这里没有说的特别细,我补充了一下,大体意思是说,使用 GETPOST 进行表单提交时,亦或者使用一些 HTML 标签引发的 GET 请求,如:aimg 等,基本上都会携带用户凭据(Cookies)

Docker 靶场

SSRF

SSRF 本质其实和 CSRF 相差不大。只是 CSRF 面向的是客户端的用户,而 SSRF面向的是服务端自己。

这种漏洞通常出现于:会访问并返回用户可控的资源的功能上。

例如:在线查看网站源码获取用户发连接的title在线翻译网页

<script>
  // 根据url动态拼接url
  function seeCode() {
    const url = document.getElementsByTagName('input')[0].value;
    location.href = location.origin + location.pathname + '?url=' + url
  }
</script>

<input type="text" placeholder="请输入要查看源代码的网站 URL"/>
<button onclick="seeCode()">查看</button>
<?php
  $url = $_GET['url'];
  if ("" == trim($url)) {
    return;
  }

  // 获取内容
  $websiteCode = file_get_contents($url);

  // 转码后存入 textarea 标签里
  echo "<textarea>".htmlspecialchars($websiteCode, ENT_QUOTES)."</textarea>";
?>复制代码

能够看到,这里没有对用户的输入作任何的过滤,致使用户能够直接输入http://192.168.1.2等url,来访问内网资源,由于访问资源的是服务端自己,而服务端自己也是能够访问同局域网的资源的。

Docker 靶场

JSON Hijacking

JSON Hijacking 其实本质和 CSRF 原理同样

这里的原理指的是,漏洞产生的原理同样,仍是由于标签产生的请求,会携带用户凭证

这个攻击手法和 CSRF 最大的不一样,就是 JSON HijackingCSRF 的基础上,又利用了 JSONP 的特性

<?php
  require 'utils.php';

  // 用户认证、并获取用户信息
  $result = getUserInfo();
  if (count($result) != 3) {
    echo "";
    exit();
  }

  $fnName = $_GET['callback'];
  if ("" == trim($fnName)) {
    echo "";
    exit();
  }

	// 输出为: getInfo({"name": name, "balance": balance });
  echo "$fnName({name: '$result[0]', balance: '$result[2]'})";
?>复制代码
<script>
  function getInfo(data) {
    console.log(data); // {"name": name, "balance": balance}
  }
</script>
<script src="./json.php?callback=getInfo"></script>复制代码

若是有恶意攻击者,写了一个页面,而且也在网页里加入了<script src="http://xxx/json.php?callback=getInfo"></script>

根据上文提到的 w3c cors 规范中,若是用户事先已经登录过了,再打开恶意攻击者发的连接,那么攻击者就能够获取一些本不该该获取的敏感信息。

Docker 靶场

相关文章
相关标签/搜索