【转载】【漏洞分析】How I made 25000 USD in bug bounties with reverse proxy

我是怎样用反向代理服务器赚取25000美元的 bug 赏金的

A proxy server is a go‑between or intermediary server that forwards requests for content from multiple clients to different servers across the Internet. A reverse proxy server is a type of proxy server that typically sits behind the firewall in a private network and directs client requests to the appropriate backend server. A reverse proxy provides an additional level of abstraction and control to ensure the smooth flow of network traffic between clients and servers.

代理服务器是一个中间服务器,它将来自多个客户机的内容请求转发到 Internet 上的不同服务器。反向代理服务器是一种代理服务器,它通常位于私有网络中的防火墙之后,并将客户机请求发送到适当的后端服务器。反向代理提供了额外的抽象和控制级别,以确保客户机和服务器之间网络流量的顺利流动。

Basic reverse proxy 基本的反向代理

Why is used?


  • Load balancing 负载平衡 — A reverse proxy server can act as a “traffic cop,” sitting in front of your backend servers and distributing client requests across a group of servers in a manner that maximizes speed and capacity utilization while ensuring no one server is overloaded, which can degrade performance. If a server goes down, the ー反向代理服务器可以充当“交通警察”,位于后端服务器之前,以最大限度提高速度和产能利用率的方式在一组服务器之间分发客户端请求,同时确保没有一个服务器超载,这会降低性能。如果服务器宕机,则load balancer 负载均衡器 redirects traffic to the remaining online servers. 将流量重定向到剩余的在线服务器
  • Web acceleration 网页加速 — Reverse proxies can compress inbound and outbound data, as well as cache commonly requested content, both of which speed up the flow of traffic between clients and servers. They can also perform additional tasks such as SSL encryption to take load off of your web servers, thereby ー反向代理可以压缩入站和出站数据,以及缓存通常要求的内容,这两者都加快了客户端和服务器之间的通信流。他们还可以执行额外的任务,如 SSL 加密,以减轻您的 web 服务器的负载,从而boosting their performance 提高他们的表现.
  • Security and anonymity 安全和匿名 — By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks. It also ensures that multiple servers can be accessed from a single record locator or URL regardless of the structure of your local area network. ー反向代理服务器通过拦截发往后端服务器的请求,保护这些请求的身份,并作为额外的防御安全攻击的工具。它还确保可以从单个记录定位器或 URL 访问多个服务器,而不管局域网的结构如何

So basically I escalated a REVERSE PROXY to 2 SQLi and 3 RCE on the internal servers and a couple of other issues. There was information disclosure and other problems found.

所以基本上我在内部服务器上将反向代理升级为2 SQLi 和3 RCE,还有其他一些问题。有信息披露和其他问题被发现。

To find the reverse proxy you can use Burp or DNSBIN better to catch the DNS request.

要找到反向代理,你可以使用 Burp 或 DNSBIN 更好地捕捉 DNS 请求。

You need to modify the requests like this


GET / HTTP/1.1
Content-Length: 95
Content-Type: application/x-www-form-urlencoded

GET/HTTP/1.1 Content-Length: 95 Content-Type: application/x-www-form-urlencoded


GET http://burpcollaborator_url HTTP/1.1
Content-Length: 95
Content-Type: application/x-www-form-urlencoded

1.1 Content-Length: 95 Content-Type: application/x-www-form-urlencoded. GET HTTP://burpcollaborator_url /HTTP/1.1 Content-Length: 95 Content-Type: application/x-www-form-urlencoded

Then you need to check the DNS responses, but filter a lot of WAF and manual pingbacks you get because most of the time is false positive

然后您需要检查 DNS 响应,但过滤大量的 WAF 和手动 pingback,因为大多数时候是假阳性

If you get a DNS response only and not a HTTP one, don’t give up. It means other ports on the same internal portal might be accessible, just not 80 or 443. Or some internal sites cannot be shown by the reverse proxy. You might need to trick with adding an url or subdomain that pretends to be valid.

如果你得到的只是 DNS 响应而不是 HTTP 响应,不要放弃。这意味着可以访问同一个内部门户上的其他端口,而不是80或443。或者一些内部站点无法通过反向代理显示。你可能需要添加一个欺骗的 url 或子域,假装是有效的。

Once you get access to an internal asset, you need to use the reverse proxy and test it like it’s an external website


Burp trick to be able to browse the internal site from the browser 打嗝的技巧,能够浏览内部网站从浏览器

Of course is a big are to explore and many bypass combinations to try like:


GET https://external_site.com@internal_site:4566 HTTP1/1 etc

Https://external_site.com@internal_site:4566 http/1/1等

I believe this are is not fully explored, even if the bug type is not new. Probably similar issues can be found with another name or attacks work with other techniques. Like a reverse proxy can also be exploited via another url parser issue etc. But I encourage everyone to look more here.

我相信这是没有充分探讨,即使错误类型不是新的。也许类似的问题可以用另一个名字找到,或者用其他技术进行攻击。像反向代理一样,也可以通过另一个 url 解析器问题等加以利用。但我鼓励大家多看看这里。

The attacker just needs to create a special URL (/img/..%2faccount/attacker/), so Nuster applies an “aggressive caching” rule, still, the web app returns a response of self XSS (it sees ‘/account/attacker/`). The response with an XSS payload will be cached by Nuster (with the key: Host + /img/..%2faccount/attacker/), so the attacker will be able to misuse this cache to XSS attack other users of the web application.From the self-XSS, we’ve got a usual XSS.

攻击者只需要创建一个特殊的 URL (/img/。.% 2faccount/攻击者/) ,因此 Nuster 应用了“侵略性缓存”规则,但 web 应用程序仍然返回一个 self XSS 响应(它看到的是“/account/攻击者/”)。带有 XSS 有效负载的响应将由 Nuster (键: Host +/img/)缓存。.% 2 faccount/攻击者/) ,因此攻击者可以滥用此缓存来攻击 web 应用程序的其他用户。从 self-XSS 中,我们得到了一个常用的 XSS。

【转载】【漏洞分析】More secure Facebook Canvas : Tale of $126k worth of bugs that lead to Facebook Account Takeovers



Facebook allowed online games owners to host their games/applications in apps.facebook.com for many years now. The idea and technology behind it was that the game ( Flash or HTML5 based) would be hosted in the owner website and later the website page hosting it should be shown to the Facebook user in apps.facebook.com inside a controlled iframe. Since the game is not hosted in Facebook and for best user experience like keeping score and profile data, Facebook had to establish a communication channel with the game owner to verify the identity of the Facebook user for example. This was ensured by using cross windows communication/messaging between apps.facebook.com and the game website inside the iframe. In this blog post, i’ll be discussing multiple vulnerabilities i found in this implementation.

Facebook 已经允许在线游戏的拥有者多年以来一直在 apps.Facebook.com 地区主持他们的游戏/应用程序。其背后的想法和技术是,这款游戏(基于 Flash 或 HTML5)将托管在所有者网站上,随后托管该游戏的网站页面应该显示在一个控制的 iframe 内的 Facebook 用户 apps.Facebook.com。由于游戏不在 Facebook 上托管,为了获得最好的用户体验,比如保存分数和个人资料,Facebook 不得不建立一个与游戏所有者的沟通渠道来验证 Facebook 用户的身份。这是通过使用 iframe 中的 apps.facebook.com 和游戏网站之间的跨窗口通信/消息来确保的。在这篇博文中,我将讨论在这个实现中发现的多个漏洞。

Vulnerabilities potential


These bugs were found after careful auditing of the client-side code inside apps.facebook.com responsible of verifying what’s coming through this channel. The bugs explained below (and others) allowed me to takeover any Facebook account if the user decided to visit my game page inside apps.facebook.com. The severity of these bugs is high since these were present for years and billions of user and their information could have been compromised easily since this was served from inside Facebook. Facebook confirmed they didn’t see any indicators of previous abuse or exploitation of these bugs.

这些错误是在对负责验证通过这个通道的 apps.facebook.com 内部的客户端代码进行仔细审计后发现的。如果用户决定访问我的游戏页面,下面解释的 bug (以及其他 bug)允许我接管任何 Facebook 账户,只要用户决定访问我的游戏 apps.Facebook.com。这些漏洞的严重程度很高,因为这些漏洞已经存在多年,而且由于这些漏洞是从 Facebook 内部提供的,数十亿用户和他们的信息可能很容易被泄露。确认他们没有看到任何先前滥用或利用这些漏洞的迹象。

For Researchers


Before explaining the actual bugs below, i tried to show the way i decomposed the code and a simplified path to track the flow of the message data and how its components will be used. I probably didn’t left much to dig but i hope the information shared could help you in your research. If you are only interested in the bugs themselves then jump to each bug section part.

在解释下面的实际错误之前,我试图展示我分解代码的方法和一个简化的路径来跟踪消息数据流以及它的组件将如何使用。我可能没有留下太多可挖掘的信息,但我希望分享的信息可以帮助你的研究。如果您只对 bug 本身感兴趣,那么就跳到每个 bug 部分。



So far we know that the game page being served inside an iframe in apps.facebook.com is communicating with the parent window to ask Facebook to do some actions. Among the requested actions , for example , is to show a dialog to the user that would allow him to confirm the usage of the Facebook application owned by the game developers which would help me to identify you and get some information from an access token that they’ll receive if the user decided to user the application. The script responsible of receiving the cross window messages, interpreting them and understanding the action demanded is below ( only necessary parts are shown and as they were before the bugs were fixed ) :

到目前为止,我们知道在 apps.Facebook.com 的 iframe 中提供的游戏页面正在与父窗口通信,要求 Facebook 做一些操作。例如,在要求的操作中,向用户显示一个对话框,允许他确认游戏开发者拥有的 Facebook 应用程序的使用情况,这将帮助我识别你,并从一个访问令牌中获取一些信息,如果用户决定使用该应用程序,他们将收到这些信息。下面的脚本负责接收跨窗口消息,解释它们并理解需要的操作(只显示必要的部分,并且在修复 bug 之前是这样的) :

__d("XdArbiter", ...
            handleMessage: function(a, b, e) {
                d("Log").debug("XdArbiter at " + (window.name != null && window.name !== "" ? window.name : window == top ? "top" : "[no name]") + " handleMessage " + JSON.stringify(a));
                if (typeof a === "string" && /^FB_RPC:/.test(a)) {
                    k.enqueue([a.substring(7), {
                        origin: b,
                        source: e || i[h]
            send: function(a, b, e) {
                var f = e in i ? e : h;
                a = typeof a === "string" ? a : c("QueryString").encode(a);
                b = b;
                try {
                    d("SecurePostMessage").sendMessageToSpecificOrigin(b, a, e)
                } catch (a) {
                    d("Log").error("XdArbiter: Proxy for %s not available, page might have been navigated: %s", f, a.message), delete i[f]
                return !0

    window.addEventListener("message", function(a) {
        if (a.data.xdArbiterSyn) d("SecurePostMessage").sendMessageAllowAnyOrigin_UNSAFE(a.source, {
            xdArbiterAck: !0
        else if (a.data.xdArbiterRegister) {
            var b = l.register(a.source, a.data.xdProxyName, a.data.origin, a.origin);
            d("SecurePostMessage").sendMessageAllowAnyOrigin_UNSAFE(a.source, {
                xdArbiterRegisterAck: b
        } else a.data.xdArbiterHandleMessage && l.handleMessage(a.data.message, a.data.origin, a.source)
}), 98);

__d("JSONRPC", ...
        c.read = function(a, c) {
            e = this.local[a.method];
            try {
                e = e.apply(c || null, a.params);
                typeof e !== "undefined" && g("result", e)
    e.exports = a
}), null);

__d("PlatformAppController", ...
function f(a, b, e) { ...
         c("PlatformDialogClient").async(f, a, function(d) { ... b(d) });
t.local.showDialog = f;


t = new(c("JSONRPC"))(function(a, b) {
            var d = b.origin || k;
            b = b.source;
            if (b == null) {
                var e = c("ge")(j);
                b = e.contentWindow
            c("XdArbiter").send("FB_RPC:" + a, b, d)

}), null);

__d("PlatformDialogClient", ...
function async(a, b, e) {
        var f = c("guid")(),
            g = b.state;
        b.state = f;
        b.redirect_uri = new(c("URI"))("/dialog/return/arbiter").setSubdomain("www").setFragment(c("QueryString").encode({
            origin: b.redirect_uri
        b.display = "async";
        j[f] = {
            callback: e || function() {},
            state: g
        e = "POST";
        d("AsyncDialog").send(new(c("AsyncRequest"))(this.getURI(a, b)).setMethod(e).setReadOnly(!0).setAbortHandler(k(f)).setErrorHandler(l(f)))
function getURI(a, b) {
        if (b.version) {
            var d = new(c("URI"))("/" + b.version + "/dialog/" + a);
            delete b.version;
            return d.addQueryData(b)
        return c("PlatformVersioning").versionAwareURI(new(c("URI"))("/dialog/" + a).addQueryData(b))

}), 98);

To simplify the code for you to understand the flow in case someone decides to dig more into it and looks for more bugs :

为了简化代码,以便你能够理解流程,以防有人决定深入挖掘代码并寻找更多的 bug:

Iframe sends message to parent => Message event dispatched in XdArbiter => Message handler function passes data to handleMessage function => “enqueue” function passes to JSONRPC => JSONRPC.read calls this.local.showDialog function in PlatformAppController => function checks message and if all valid, call PlatformDialogClient => PlatformDialogClient.async sends a POST request to apps.facebook.com/dialog/oauth , returned access_token would be passed to XdArbiter.send function ( few steps were skipped ) => XdArbiter.send would send a cross window message to the iframe window => Event dispatched in iframe window containing Facebook user access_token

在 XdArbiter = > Message handler 函数中,iframesend Message to parent = > Message Event delayed in XdArbiter = > Message handler function passes data to handleMessage function = > “ enqueue”function passes to JSONRPC = > JSONRPC.read calls this.local.showDialog function in PlatformAppController = > function checking Message and if all valid,call platformdialoggclient = > platformasyngoaldialog.c 向 apps.Facebook.com/dialog/oauth 发送 POST 请求,返回的访问权限将传递给 XdArbiter.send 函数(跳过了几个步骤) = > xbiter.send 将向 Iframe 窗口发送一个跨窗口消息,窗口中包含 Facebook 用户访问权限

Below an example of a simple code to construct the message to be sent to apps.facebook.com from the iframe, a similar one would be send from any game page using the Facebook Javascript SDK but with more unnecessary parts:

下面是一个简单的代码示例,用来构造要从 iframe 发送给 apps.Facebook.com 的消息,类似的代码可以从任何使用 Facebook Javascript SDK 的游戏页面发送,但是有更多不必要的部分:

 msg = JSON.stringify({"jsonrpc":"2.0",
                fullmsg = {xdArbiterHandleMessage:true,message:"FB_RPC:" + msg , origin: IFRAME_ORIGIN}

Interested parts to manipulate are :
IFRAME_ORIGIN, which is the one to be used in the redirect_uri parameter send with the POST request to apps.facebook.com/dialog/oauth to be verified server-side that it’s a domain owned by the application requesting an access_token, then would be used as targetOrigin in postMessage to send a cross window message to the iframe with the access_token
– Keys and values of the object inside params , there are the parameters to be appended to apps.facebook.com/dialog/oauth. Most interesting ones are redirect_uri ( which can replace IFRAME_ORIGIN in the POST request in some cases ) and APP_ID

感兴趣的操作部分是:-IFRAME _ origin,这是一个用于 redirect _ uri 参数发送的 POST 请求被验证的服务器端的 apps.facebook.com/dialog/oauth ,它是一个域的应用程序拥有的请求访问令牌,然后将用作 postMessage 的 targetOrigin 发送一个跨窗口消息与 access _ 令牌键和对象内部参数值的 IFRAME,有参数被附加到 apps.facebook.com/dialog/oauth。最有趣的是 redirect _ uri (在某些情况下可以替换 POST 请求中的 IFRAME _ origin)和 APP _ id

Attacks vectors/scenarios


What we’ll do here is to try to instead of requesting an access token for the game application we own, we’ll try to get one of a Facebook first party application like Instagram. What’s holding us back is although we control the IFRAME_ORIGIN and APP_ID which we can set to match the Instagram application as http://www.instagram.com and 124024574287414, later the message sent to the iframe containing the first party access token would have a targetOrigin in postMessage as http://www.instagram.com which is not our window origin. Facebook did a good job protecting against these attacks ( i’ll argue though to why not using the origin from the event message received and matching app_id to the hosted game instead of giving us total freedom which could have prevented all these bugs ), but apparently they left some weaknesses that could have been exploited for many years.

我们在这里要做的不是为我们拥有的游戏应用程序申请访问令牌,而是尝试获得一个像 Instagram 这样的 Facebook 第一方应用程序。尽管我们可以设置 IFRAME origin 和 APP id 来匹配 Instagram 应用程序的 http://www.Instagram.com 和124024574287414,但是之后发送给包含第一方访问令牌的 IFRAME 的消息在 postMessage 中会有一个 targetOrigin,这不是我们的窗口 http://www.Instagram.com。Facebook 在防御这些攻击方面做得很好(我想说的是为什么不使用收到的事件消息的来源,并将 app _ id 与托管的游戏进行匹配,而不是给予我们完全的自由,这本可以避免所有这些 bug) ,但是显然他们留下了一些可能被利用多年的弱点。

Bug 1: Parameter Pollution, it was checked server-side and we definitely should trust it

缺陷1: 参数污染,它是检查服务器端,我们绝对应该信任它

This bug occurs due to the fact that the POST request to https://apps.facebook.com/dialog/oauth when constructed from the received message from the iframe, could contain user controlled parameters.
All parameters are checked in the client-side ( PlatformAppController, showDialog method and ,PlatformDialogClient.async method) and duplicate parameters will be removed in PlatformAppController , also AsyncRequest module seems to be doing some filtering ( removing parameters that already exist but brackets were appended to it ).

However due to some missing checking in the server-side, a parameter name set to PARAM[random would replace a previously set parameter PARAM ; for example redirect_uri[0 parameter value would replace redirect_uri. We can abuse this as follow :
1) Set APP_ID to be the Instagram application id.
2) The redirect_uri will be constructed in PlatformDialogClient.async (Line 72 ) using IFRAME_ORIGIN ( will end up https://www.facebook.com/dialog/return/arbiter#origin=https://attacker.com ) , which would be sent matching our iframe window origin but won’t be used at all as explained below.
3) Set redirect_uri[0 in params as an additional parameter ( order matters so it must be after redirect_uri ) to be https://www.instagram.com/accounts/signup/ which is a valid redirect_uri for the Instagram applicaiton.
The URL of the POST request end up being something like this:

这个错误是因为当从 iframe 接收到的消息构造 POST 请求到 https://apps.facebook.com/dialog/oauth 时,可能包含用户控制的参数。所有参数都在客户端检查(PlatformAppController、 showDialog 方法和 PlatformDialogClient.async 方法) ,重复的参数将在 PlatformAppController 中删除,AsyncRequest 模块似乎正在进行一些过滤(删除已经存在的参数,但添加了括号)。然而,由于服务器端缺少检查,设置为 PARAM [ random 的参数名将替换以前设置的参数 PARAM; 例如 redirect _ uri [0参数值将替换 redirect _ uri。我们可以这样滥用: 1)设置 APP _ id 为 Instagram 应用程序 id。2) redirect _ uri 将使用 IFRAME _ origin 在 PlatformDialogClient.async (第72行)中构建,它将被发送到与 IFRAME 窗口原点相匹配的 https://www.facebook.com/dialog/return/arbiter#origin=https://attacker.com ,但不会像下面解释的那样被使用。3)设置 redirect _ uri [0 in params 作为一个额外的参数(顺序很重要,所以必须在 redirect _ uri 之后)为 https://www.Instagram.com/accounts/signup/ ,这是 Instagram 应用程序的一个有效 redirect _ uri。请求的 URL 如下所示:


The request would end up being successful and returning a first party access token since redirect_uri[0 replaces redirect_uri and it’s a valid redirect_uri. In the client side though, the logic is if an access_token was received it means that the origin used to construct the redirect_uri did work with the app_id and for that it should trust it and use to send the message to the iframe, behind the scenes though redirect_uri[0 was used and not redirect_uri ( Cool right?)

Proof of concept

因为 redirect _ uri [0替换了 redirect _ uri,而且它是一个有效的 redirect _ uri,所以请求最终会成功并返回一个第一方访问令牌。但是在客户端,逻辑是,如果接收到一个访问令牌,这意味着用于构造 redirect _ uri 的原点确实与 app _ id 一起工作,因此它应该信任它,并用它将消息发送到 iframe,在幕后虽然 redirect _ uri [0被使用而不是 redirect _ uri (Cool right?))概念验证

xmsg = JSON.stringify({"jsonrpc":"2.0",
                fullmsg = {xdArbiterHandleMessage:true,message:"FB_RPC:" + xmsg , origin: "https://attacker.com"}

Bug 2: Why bothering, Origin is undefined


The main problem for this one is that /dialog/oauth endpoint would accept https://www.facebook.com/dialog/return/arbiter as a valid redirect_uri ( without a valid origin in the fragment part ) for third-party applications and some first-party ones.
The second problem is that this behaviour to occur ( no origin in the fragment part ), the message sent from the iframe to apps.facebook.com should not contain a.data.origin ( IFRAME_ORIGIN is undefined ) , however this same value would be used later to send a cross window message to the iframe, if null or undefined is used, the message won’t be received.
Likely, i noticed that JSONRPC function would always receive a not null origin of the postMessage ( Line 55 ) . Since b.origin is undefined or null, k would be chosen. k could be set by the attacker by first registering a valid origin via c(“Arbiter”).subscribe(“XdArbiter/register”) which could be informed if our message had xdArbiterRegister and a specified origin . Before “k” variable is set, the supplied origin would be checked first if it belongs to the attacker application using “/platform/app_owned_url_check/” endpoint.
This is wrong and the second problem occurs here since we can’t ensure that the user in the next cross origin message sent from the iframe would supply the same APP_ID.

对于第三方应用程序和一些第一方应用程序来说,/dialog/oauth 端点将接受 https://www.facebook.com/dialog/return/arbiter 作为一个有效的 redirect _ uri (片段部分没有有效的起点)。第二个问题是,这种行为会发生(片段部分没有原点) ,从 IFRAME 发送到 apps.facebook.com 的消息不应该包含 a.data.origin (IFRAME _ origin 未定义) ,但是这个相同的值稍后会被用来向 IFRAME 发送跨窗口消息,如果使用 null 或未定义,消息将不会被接收。很可能,我注意到 JSONRPC 函数总是会接收到一个非空的 postMessage 原点(第55行)。由于 b.origin 未定义或为 null,因此将选择 k。攻击者可以通过 c 注册一个有效的源(“仲裁者”)来设置 k。订阅(“ XdArbiter/register”) ,如果我们的消息具有 xdArbiterRegister 和指定的来源,就可以通知它。在设置“ k”变量之前,如果提供的原点属于使用“/platform/app _ owned _ url _ check/”端点的攻击者应用程序,那么将首先检查它。这是错误的,这里发生了第二个问题,因为我们不能确保从 iframe 发送的下一个跨源消息中的用户将提供相同的 APP _ id。

Not all first-party applications are vulnerable to this though. I used the Facebook Watch for Android application or Portal to get a first party access_token.

不过,并非所有第一方应用程序都容易受到这种攻击。我用 Facebook Watch for Android 应用程序或 Portal 获得了第一方访问令牌。

The URL of the POST request would be something like this:

请求的 URL 如下所示:


Proof Of Concept



xmsg = JSON.stringify({"jsonrpc":"2.0",
                fullmsg = {xdArbiterHandleMessage:true,message:"FB_RPC:" + xmsg}

Bug 3: Total Chaos, version can’t be harmful


This bug one occurs in PlatformDialogClient.getURI function which is responsible of setting the API version before /dialog/oauth endpoint. This function didn’t check for double dots or added paths and directly constructed a URI object to be used later to send an XHR request ( Line 86 ).
The version property in params passed in the cross window message sent to apps.facebook.com could be set to api/graphql/?doc_id=DOC_ID&variables=VAR# and would eventually lead to a POST request sent to the GraphQL endpoint with valid user CSRF token.

这个 bug 出现在 PlatformDialogClient.getURI 函数中,该函数负责在/dialog/oauth 端点之前设置 API 版本。这个函数没有检查双点或添加路径,而是直接构造了一个 URI 对象,以便稍后用于发送 XHR 请求(第86行)。传递给 apps.facebook.com 的跨窗口消息中的参数中的 version 属性可以设置为 api/graphql/?DOC _ id = DOC _ id & variables = VAR # ,并最终导致使用有效的用户 CSRF 令牌向 GraphQL 端点发送 POST 请求。

DOC_ID and VAR could be set to an id of a GraphQL Mutation to add a phone number to the attacount, and the variables of this mutation.

DOC _ id 和 VAR 可以设置为一个 GraphQL Mutation 的 id,以便向 attacount 添加一个电话号码,以及此变异的变量。

The URL of the POST request would be something like this:

请求的 URL 如下所示:


Proof Of Concept


xmsg = JSON.stringify({"jsonrpc":"2.0",
                fullmsg = {xdArbiterHandleMessage:true,message:"FB_RPC:" + xmsg , origin: "https://attacker.com"}



  1. Aug 4, 2021— Report Sent  2021年8月4日ー发送报告
    Aug 4, 2021—  Acknowledged by Facebook 2021年8月4日ー Facebook 承认
    Aug 6, 2021— Fixed by Facebook 2021年8月6日ー Facebook 修复
    Sep 2, 2021 — $42000 bounty awarded by Facebook. 2021年9月2日ー4.2万美元 Facebook 悬赏
  2. Aug 9, 2021— Report Sent  2021年8月9日ー发送报告
    Aug 9, 2021—  Acknowledged by Facebook 2021年8月9日ー Facebook 承认
    Aug 12, 2021— Fixed by Facebook 2021年8月12日ー Facebook 修复
    Aug 31, 2021 — $42000 bounty awarded by Facebook. 2021年8月31日ー Facebook 奖励4.2万美元
  3. Aug 12, 2021— Report Sent  2021年8月12日ー发送报告
    Aug 13, 2021—  Acknowledged by Facebook 2021年8月13日ー Facebook 承认
    Aug 17, 2021— Fixed by Facebook 2021年8月17日ー Facebook 修复
    Sep 2, 2021 — $42000 bounty awarded by Facebook. 2021年9月2日ー4.2万美元 Facebook 悬赏

【转载】【漏洞分析】Information Disclosure via External Live Chat Service

Hi folks!


I hope you’re all safe and good. Today’s writeup I explains how I was able to fetch website staffs first names, phone numbers, e-mail address through external live chat service.


I found this vulnerability in HackerOne at a private program. So we can call that program as redacted.com . Firstly, I looked for a live chat service on main domain but I can’t found anything. Then, I registered to website. Now I can see live chat is there. I sent some messages to live chat service. But seems it’s a auto reply chat service. I lost my momentary joy.

我在 HackerOne 的一个私人项目中发现了这个漏洞。所以我们可以把这个程序命名为 recated.com。首先,我在主域名上寻找一个在线聊天服务,但是我找不到任何东西。然后,我注册了一个网站。现在我可以看到在线聊天是有的。我发了一些消息到在线聊天服务。但它似乎是一个自动回复聊天服务。我失去了瞬间的快乐。

After I finished my research on main domain, I started to examine request history in Burp Suite. I saw a https://api.redactedchatservice.com/restapi/v1/team/user/members?access-token=jwttokenrequest.

在完成了对主域的研究之后,我开始检查 Burp Suite 中的请求历史。我看到了一个 https://api.redactedchatservice.com/restapi/v1/team/user/members?access-token=jwttokenrequest。

Well, probably I found 298 phone numbers of live support agents!


Then I checked a phone number’s WhatsApp account to verify if it was a physical (real) sim card. Yes! That phone number have a WhatsApp acount, so it’s a physical phone number. And then I immediately reported it.

然后我检查了一个电话号码的 WhatsApp 账户,以确认这是否是一张实体的(真实的) sim 卡。太好了!这个电话号码有一个 WhatsApp 账号,所以它是一个实体电话号码。然后我立刻报告了这件事。

Report Timeline


  • Submitted on July 2, 2021 2021年7月2日提交
  • Fixed on July 6, 2021 2021年7月6日固定
  • $$$ bounty awarded on July 20, 2021 as Medium severity. 二○二一年七月二十日颁发中等严重程度港币奖金
My react after report triaged 😀 我的反应后报告分类: d

Thanks for reading my first writeup. Happy to share this find with you all. If you found anything interesting feel free to share. DM me on Twitter if you have any queries. Stay home and stay safe! ♥

































网上学习 – > 规划书 -> 主播招募 -> 直播间装配。






  • 管理学之父: 泰罗 《科学管理原理》 他总是要创造一些条件,让自己处于有利的位置
  • 德鲁克 《卓有成效的管理者》 追问自己的三个问题:1)不做当下这件事,又会怎样?2)这件事,别人做,会不会更好?3)有哪些事情,就是交给别人做,也毫无意义?
  • 克里斯滕森 教人通过“颠覆性创新”来实现弯道超车 如何乐在工作?如何与家人朋友长保幸福?如何坚持原则、保持正直?

泰罗的创造条件让自己处于有利位置,让我想起了孙子兵法,孙子兵法并不是以少胜多,而且以强胜弱,保证成功概率最大化。 这种想法肯定是对的,大家都在追求对自己有利的事情。










管理学之父,最讨厌的概念是公平竞赛,做每一件事情都应该避免公平竞争,从而让自己处于有利的位置。 比如,他在给工厂主怎么管工人的建议的时候,就直接用秒表来算工人的效率(产量除以时间),达到了破局的思维。


例子: 有一个做房地产的朋友跟我说,他以前拍了一块地,开发了完全不同的两个档次的楼房,容积率不同,物业费不同,环境也不一样。为了便于销售,这位朋友修了一堵墙,把一块地分成了两个小区,这就破了当时销售的局。但过了几年,业主们要求环境要共享,占绿地少的,要求拆墙,但别墅区的业主交的物业费多,不同意拆墙,你说要不要拆呢?

拆和不拆的决策,其实都是为了冲出困局。但无论你怎么决策,后面都有一连串的问题等着你,形成新的困局,仍然要破。 那个老板是拆墙还是不拆墙,无论怎么选,都能冲出当下的困局,但马上就会陷入一个新的困局。








正资源: 有些资源支持你,你可以支持的资源。

负资源: 有些资源阻挡你,不能为你所用

破局: 你做事,就是处于一个局中,想办法把负资源移开,让自己冲出去,就是破局。

做局: 故意给他人设置负资源,让他过不去或者必须按照你的意思,绕着弯走。

破局思维: 调整资源的性质,正变负,负变正,让你能够走得通。


1. 找无关资源,通过对正负资源和无关资源的整合,对负资源进行转化

2. 对资源进行重新定义,找到新的出路。

3. 重新定义自我,敢于把自己碎掉。 负资源打不破,但是有缝隙,可以钻出去。

















  • 程序的预分析


  • 内存敏感



  • 路径覆盖



  • 哈希碰撞率的缓解









​ 都是一些没什么利用价值的开源软件…,上图


​ 其实总体上,做出的改进并不多,但是效果作为毕设我还是挺意外的,毕业证拿到了,想开源出来(被捶认了),欢迎师傅交流,一起学习漏洞挖掘漏洞利用啊!