CSRF及SSRF漏洞

                       CSRF及SSRF漏洞


前言

       个人观点,若有误请指教


CSRF

原理

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。


例子

①受害者登录a.com,并保留了登录凭证(Cookie)。
②攻击者引诱受害者访问了b.com。
③b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
④a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
⑤a.com以受害者的名义执行了act=xx。
⑥攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。在这里插入图片描述

注:来自https://www.cnblogs.com/-qing-/p/11015075.html


触发条件

  • 没有以防CSRF攻击的安全措施(没有防护必存在该漏洞)或者安全措施不够严密(有些安全措施可进行绕过)
  • 受害者必须登录过被攻击网站
  • 受害者必须点击攻击者精心构造的链接

实操

  • 禁用SameSite(来自https://www.cnblogs.com/huashuiing/p/14339897.html
    访问:chrome://flags/#same-site-by-default-cookies
    在这里插入图片描述
    注:只有这样才可以进行csrf攻击,要不然受害者点击了攻击链接也没用(获得不了cookie),感觉这攻击不咋地,因为本人也用Microsoft Edge浏览器,同时是攻击失败。ヽ(ー_ー)ノ

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:172.16.38.1是攻击者的机器,最后信息成功被修改了!


防御

Referer

  • Referer是代表发出请求的来源。

  • 在url地址栏中直接输入地址则不会出现这个字段,但如果是在其他网页上由用户点击跳转或者网页自动跳转的,则该字段的值就为这些网页的地址。

  • 如www.google.com 里有一个www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:Referer=http://www.google.com。

  • 刚刚实操中的SameSite的检查机制好像就在检查这个字段(这是其他博主的理解,但本人在有SameSite检查机制的情况下进行抓包后,发现只存在referer字段,cookie字段已消失)。
    在这里插入图片描述

  • 无法进行有效的防御,容易被篡改


Token

  • 通过每一次进入修改页面都重新生成一个新的token来进行防御。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 这样导致无法进行修改,因为token是进入修改页面才获得的,而在提交修改请求时携带的。crsf的攻击是直接提交修改请求。

  • token可以有效防御csrf的原理:
    ①用户访问某个表单页面。
    ②服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
    ③在页面表单附带上Token参数。
    ④用户提交请求后, 服务端验证表单中的Token(网页是有个hidden的token值的)是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。
    注:这个Token的值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。


使用地点

  • 个人信息修改页面
  • 用户(管理员)创建页面
    注:攻击者需要知道请求报文的格式,以便于伪造。

SSRF

简介

  • SSRF(Server-Side Request Forgery) :服务器端请求伪造。
  • SSRF攻击的目标是从外网无法访问的内部系统。
  • SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。在这里插入图片描述

SSRF漏洞挖掘

  • ssrf漏洞只出现在远程上传,特殊情况例外。(本地上传是不管用的,本地上传就是把你自己机器上的东西上传到服务器上,然后服务器根据你上传的东西去请求一些东西再回响;而远程上传是你给个url地址,叫服务器自己去请求该url,请求完成后再回响)
    在这里插入图片描述
    在这里插入图片描述
    而远程上传,其url地址可以是恶意的(这也是本地上传不行的根本原因),如http://127.0.0.1:3306。通过这样来获得指定主机的信息。

  • 漏洞出现点:
    ①分享:通过URL地址分享网页内容
    在这里插入图片描述
    注:来自此博客


    ②转码服务:通过URL地址将原地址网页调优,使其更适合浏览
    ③在线翻译:通过URL地址翻译对应的文本内容
    ④图片加载与下载:通过URL地址加载或下载图片
    ⑤图片、文章在线收藏
    ⑥未公开的api实现以及其他调用URL的功能
    ⑦从URL关键字中寻找(其实就是上面功能的url常包含的关键词)

share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain


SSRF用途

  • SSRF可以做以下的功能:
    ①可以对外网服务器所在的内网、本地进行端口扫描,获取一些服务的banner信息 。
    ②攻击运行在内网或者本地的应用程序。
    ③对内网web应用进行指纹识别,通过访问默认文件实现 。
    ④攻击内外网的web应用。sql注入、struct2、redis等。
    ⑤利用file协议读取本地文件等。

SSRF简单代码

  • index.php
<html>
<head>
     <style> div.main {
      
       margin-left:auto; margin-right:auto; width:50%; } body {
      
       background-color:  #f5f5f0; }</style>
     <title>
        Awesome Script!
     </title>
</head>
<body>
    <div class="main">
    <h1>Welcome to the Awesome Script</h1>
    <p>Here you will be able to load any page you want. You won't have to worry about revealing your IP anymore! We use the cURL library in order to perform the HTTP requests. Have fun!</p>
    <br>
    <form method="GET" action="curl.php">
        <input type="text" value="" name="path">
        <input type="submit" value="Submit">
    </form>
</div>
    </body>
</html>
  • curl.php
<?php
    $location=$_GET['path']; 
    $curl = curl_init();
    curl_setopt ($curl, CURLOPT_URL, $location); 
    curl_exec ($curl); 
    curl_close ($curl);
?>

 注:代码来自此博客


漏洞利用

  • 说明:操作都以服务器请求他自己,可以请求与服务器对应的内网主机(但我懒得搭建)。

  • 端口扫描,查看对应端口的开放状态(http协议)。
    在这里插入图片描述
    在这里插入图片描述
    注:可以通过抓包来修改端口,就不用每次都要自己进行修改。

  • 读取服务器本地文件(file协议)
    在这里插入图片描述
    在这里插入图片描述

  • 还有其他协议dict(这个也可以用来进行端口扫描,但主要用途好像不是这个)、ftp等协议的利用,学艺不精,搞得不深,略过先。
    在这里插入图片描述
    在这里插入图片描述


漏洞绕过

  • 该绕过方式都来自网上,本人并没有测试过!
  • 绕过方式有:
    ① @符,对于一个 url 的访问实际上是以 @符后为准的。如[email protected],则实际上访问的是 10.10.10.10 这个地址。
    ②网址后加 xip.io,如10.10.10.10.xip.io 会自动重定向到 10.10.10.10
    ③进制转换,将 ip 转换为八进制十进制十六进制这种,同样也可以正常访问,如将 10.10.10.10 转换为十进制是 168430090,在浏览器访问 http://168430090 就回去访问 10.10.10.10 这个地址。
    注:来自此博客

漏洞防护

  • 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题。
  • 限制请求的端口为http常用的端口,如80,443,8080,8090。
  • 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
  • 设置白名单方式,只要不是指定的地址,就不进行后续操作。
  • 禁止302跳转,或每跳转一次检查新的host是否为内网ip,后禁止。

Cookie验证实例


Session验证实例

Session配置(php.ini)

session.save_handler = “files”;
//默认为files,可选files、memcach、user。如果想要自定义处理器来存取session数据,比如database,就用"user"


session.save_path=‘D:/temp’;
//用文件做介质时,session存储路径; 用memcache做介质时用作服务器连接串:session.save_path = “tcp://127.0.0.1:11211”
//有一种设置是 “N;/path”,这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本


session.name = “PHP_SESSID”
//当做cookie name来使用的session标识名


session.cookie_domain = “a.com”
//cookie有效作用域名


session.use_cookies = 1
//是否使用cookies在客户端保存会话sessionid,默认为采用cookies


session.auto_start = 0
//是否自动启动session,默认不启动。在使用session功能时,在每个php脚本头部都会通过session_start()函数来启动session


session.cookie_lifetime = 0
//传递sessionid的Cookie有效期(秒),0表示仅在浏览器打开期间有效


session.gc_probability = 1
session.gc_divisor = 1000
//定义在每次初始化会话( session_start() )时,启动垃圾回收程序(针对所有的文件)的概率。
//概率是 session.gc_probability/session.gc_divisor 结果 1/1000,


session.gc_maxlifetime = 1440 //过期时间 默认24分钟
//设定保存的session文件生存期,超过此参数设定秒数后,保存的数据将被视为’垃圾’并由垃圾回收程序清理。判断标准是最后访问数据的时间(对于FAT文件系统是最后刷新数据的时间)。如果多个脚本共享同一个session.save_path目录但session.gc_maxlifetime不同,将以所有session.gc_maxlifetime指令中的最小值为准。
//如果在session.save_path选项中设定使用子目录来存储session数据文件(N;/path),垃圾回收程序不会自动启动,必须使用自己编写的shell脚本或者其他办法来执行垃圾搜集。

注:来自此博客

Session_start详解

  • session_start()做了哪些初始化工作
    ①读取名为PHPSESSID(默认值是这个,可以设置php.ini中的session.name)的cookie值,假使为abc123
    ②若读取到PHPSESSID这个COOKIE,创建$_SESSION变量,并从相应的目录中(可以在php.ini中设置session.save_path的值)读取SESS_abc123(默认是这种命名方式)文件,将字符装在入$_SESSION变量中; 若没有读取到PHPSESSID这个COOKIE,也会创建$_SESSION变量(不过好像没啥用),同时创建一个sess_abc321(名称为随机值)的session文件,同时将abc321作为PHPSESSID的cookie值返回给浏览器端。
    注:来自此博客


    通俗来讲,session_start做了两件事,一个是产生了sessionid送给客户端(请求登陆的时候,其他时候将不会再做这件事),另一个是将session文件存储在服务器中,当浏览器请求带有这个sessionid值时,将该文件的内容拿出来使用。


    ④session文件里存放的就是$_SESSION变量里的具体值,格式为:
    变量名 | 变量类型 : [长度] : 值
    test1|s:7:“wzwd123”; test2|i:456;

Session变量销毁

  • session_unset()
    释放当前在内存中已经创建的所有$_SESSION变量,但不删除session文件以及不释放对应的sessionid
  • session_destroy()
    删除当前用户对应的session文件以及释放sessionid,内存中的$_SESSION变量内容依然保留
  • 释放用户的session所有资源,需要顺序执行如下代码:
<?php
session_start();  //让下面的方法知道是销毁那一个,每使用一次都会创一个变量
session_unset();
session_destroy();
?>

Session实例


Token验证实例

验证登录总结

  • 为什么需要这个验证(cookie、session、token)?
    因为http协议是无状态的。如果没有这个验证的话,你登录之后的第一个页面是正确的,但你再去点击其他页面的时候,要么跳到登录页面去让你登录,要么是以游客的身份去访问这些页面,后台压根就不知道你已经登录过了。

  • 这些验证的区别?
    一、session与其他两个区别比较明显。session会在服务器保留一个sess_sessionid的文件,里面保存着一些信息。当前端携带sessionid来访问时,会创建一个session的变量并把sess_sessionid文件的信息填入这个变量中,通过这个变量就可以判断是否已经登录过了(这应该很清楚吧?在文件放x,若session[x]存在且有值就证明登录过了)。根据这个来查询数据库的内容(文件放用户名,session[用户名]来查询个人信息),再将数据库内容和html代码合并发给浏览器。

    弊端:
    ①服务器压力增大:通常session是存储在内存中的,每个用户通过认证之后都会将session数据保存在服务器的内存中,而当用户量增大时,服务器的压力增大。
    ②CSRF跨站伪造请求攻击:session是基于cookie进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
    ③扩展性不强:如果将来搭建了多个服务器,虽然每个服务器都执行的是同样的业务逻辑,但是session数据是保存在内存中的(不是共享的),用户第一次访问的是服务器1,当用户再次请求时可能访问的是另外一台服务器2,服务器2获取不到session信息,就判定用户没有登陆过。



    二、cookie,这个感觉仁者见仁智者见智吧。因为很多时候cookie其实是配合session来使用的,即cookie用来存储sessionid的。不过我上面给出的例子代码是单独使用的(代码没有用加密算法对cookie进行加密,可以进行加密)。原理就是使用$_COOKIE[键]判断其值是否存在且符合已登录的要求,如果再根据其他键值来查询数据库内容,再将数据库内容和html代码合并发给浏览器。

    弊端:
    ①Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
    ②安全性问题。如果cookie被人拦截了,即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
    ③有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。(这一点简单了解一下就好)



    三、token被称为令牌,现在好像主流的是jwt来实现token的验证。token不像cookie一样在发送请求报文的时候会默认携带,它需要自己手动添加到报头上,而jwt是通过ajax或axios来进行添加token。认证流程如下:
    ①客户端使用用户名跟密码请求登录
    ②服务端收到请求,去验证用户名与密码
    ③验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
    ④客户端收到 Token 以后可以把它存储起来,比如放在 Cookie或Session 里
    ⑤客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
    ⑥服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
    在这里插入图片描述
    与session的区别就是,session验证的信息是保存在服务器上的,而token验证的信息就是它本身带着的。通过解密把token分开,对其信息进行验证,看是否已登录。若已登录则再根据其信息来查找数据库内容,再将数据库内容和html代码合并发给浏览器。

    优点:
    ①支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输。
    ②无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息。
    ③去耦: 不需要绑定到一个特定的身份验证方案。(简单了解一下)
    ④应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
    ⑤CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。

    弊端:
    ①占带宽:正常情况下要比 session_id 更大,需要消耗更多流量,挤占更多带宽
    ②无法在服务端注销,因为服务器压根就没有这个token的信息,那么如何在服务器一接收这个token的时候就直接拒收嘞。(当然可以加一个token表来解决这个问题,但这样的话还不是占用了空间?多不多加这个表这个要看场合)

Guess you like

Origin blog.csdn.net/weixin_46962006/article/details/121692663