Danny-Dasilva / CycleTLS

Spoof TLS/JA3 fingerprints in GO and Javascript
GNU General Public License v3.0
935 stars 173 forks source link

CycleTLS: JSON BODY support #67

Closed dev7machine closed 2 years ago

dev7machine commented 2 years ago

I am trying to post data to some API where server is accepting only json object. As CycleTLS supports String Body only, is there any way I can patch this? Thanks

dev7machine commented 2 years ago

is this issue specific to this repo? Couldnt you just use crypto/tls for this?

I am using this repo to bypass TLS fingerprinting. This is the only repo that has been working to bypass TLS fingerprinting for me but does't support JSON BODY. So, the feature request is specific to this repo

dev7machine commented 2 years ago

I have tried your repo. Couldn't bypass TLS fingerprinting..

package main

import "fmt"
import "github.com/89z/format/crypto"
import "net/http"

func TestTransport() {
   //hello, err := crypto.ParseJA3(crypto.AndroidAPI26)
   hello, err := crypto.ParseJA3("771,4866-4867-4865-49196-49200-49195-49199-52393-52392-159-158-52394-49327-49325-49326-49324-49188-49192-49187-49191-49162-49172-49161-49171-49315-49311-49314-49310-107-103-57-51-157-156-49313-49309-49312-49308-61-60-53-47-255,0-11-10-16-22-23-49-13-43-45-51-21,29-23-1035-25-24,0-1-2")
   if err != nil {
      fmt.Println(err)
   }
   req, err := http.NewRequest("GET", "https://api.example.com/xyz/", nil)
   if err != nil {
      fmt.Println(err)
   }
   res, err := crypto.Transport(hello).RoundTrip(req)
   if err != nil {
      fmt.Println(err)
   }
   fmt.Printf("%+v\n", res)
}

func main() {
    fmt.Println("Hello, World!")
    TestTransport()
}

Response:

https://imgur.com/a/JBq6mPg

Danny-Dasilva commented 2 years ago

If you want so send a json payload you can just stringify it

in js using JSON.stringify

const initCycleTLS = require('cycletls');
(async () => {
    const cycleTLS = await initCycleTLS();
    const jsonBody = {"hello": "world"}

    const resp = await cycleTLS('https://httpbin.org/post', {
        ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
        userAgent:
            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
        body: JSON.stringify(jsonBody)
    }, 'POST')

    console.log(resp);
})();

in Go just passing it in as a string

package main

import (
    "github.com/Danny-Dasilva/CycleTLS/cycletls"
    "log"

)

func main() {

    jsonBody := `{"hello":"world"}`
    client := cycletls.Init()
    response, err := client.Do("https://httpbin.org/post", cycletls.Options{
        Body:      jsonBody,
        Ja3:       "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0",
        UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
    }, "POST")
    if err != nil {
        log.Print("Request Failed: " + err.Error())
    }
    log.Println(response.Body)

}
dev7machine commented 2 years ago

I had tried that before opening the issue. Not working

const initCycleTLS = require('cycletls');
(async () => {
    const cycleTLS = await initCycleTLS();
    const jsonBody = {"amount":1}
    const mUrl = "https://api.example.com"

    const resp = await cycleTLS(mUrl, {
        ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
        userAgent:
            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
        body: JSON.stringify(jsonBody)
    }, 'PATCH')

    console.log(resp);
})();

Response: https://imgur.com/a/8jbJKAe

White2001Offl commented 2 years ago

I had tried that before opening the issue. Not working

const initCycleTLS = require('cycletls');
(async () => {
    const cycleTLS = await initCycleTLS();
    const jsonBody = {"amount":1}
    const mUrl = "https://api.s" + "andb"+ "ox.ga"+ "me/assetsi"+"gnedauctions/2710/book"

    const resp = await cycleTLS(mUrl, {
        ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
        userAgent:
            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
        body: JSON.stringify(jsonBody)
    }, 'PATCH')

    console.log(resp);
})();

Response: https://imgur.com/a/8jbJKAe

API Requests/Response from burpsuite https://imgur.com/a/HoZW3Wg

Did you send proper headers? I guess it's showing 400 status due to headers or the token which passed as cookie.

If you're sending then lmk I'll test on my end too

Danny-Dasilva commented 2 years ago

I'm not an expert on this api, but this appears to be 400 level API response with an error message specific to the request you're sending. This error is not one returned by CloudFlare due to TLS bypass issues I can also confirm that the json body is correctly being sent, I tested with https://requestbin.com/ but you can use any service and you'll see the json body is being delivered correctly

Danny-Dasilva commented 2 years ago

that being said if you set the "content-type": "application/json" in the headers the request returns a non-authenticated error. So as @White2001Offl said you may want to check your request headers

dev7machine commented 2 years ago

that being said if you set the "content-type": "application/json" in the headers the request returns a non-authenticated error. So as @White2001Offl said you may want to check your request headers

Yes. Figured out content-type header was the issue. I didn't know that we can pass custom headers with CycleTLS.

Thanks Man. Thanks for the help and this awesome tool.