0140454/hackbar

Add a feature that can send raw http request data in a window

NEX-S opened this issue ยท 37 comments

NEX-S commented

can hackbar add a feature that allows us to send raw HTTP request data in a window or panel? like burpsuite's repeater but the response result of the server is rendered by our browser. This feature will be fantastic if it can be implemented :D

Maybe I can make HackBar accept raw HTTP request from user.
However, due to the implementation limit, there are some limitations:

  • Only GET and POST verb can be used.
  • HTTP version in request is ignored.
  • Content-type only can be those listed in enctype combobox.
    In other words, you cannot use text/plain.
  • Request body may be modified.
    If you want to send a JSON but there is no equal sign in the body, HackBar will try to add some garbage value just like now.

If you can accept these limitations, I will try to implement it but there is no ETA now.

NEX-S commented

thanks :D that's verrrry coool !!! Appreciate for your reply ๐Ÿ‘

Before implementing it, I would like to know your scenario.

Is "loading a raw request and modifying it using current UI" acceptable to you? Like the following video, but type a raw request instead of cURL command.

record.mp4

Or you really need a big textarea like this?
If it's true, could you tell me your scenario to let me think how to make it more user-friendly?

image

NEX-S commented

I think the big text area is more convenient than another one.

In some cases, users need to select the network panel to see the response header. It's the most inconvenient thing when we pentesting or doing other stuff.
So I think the bigtext area might need to separate into two parts.

The left part can send a raw HTTP request
The right part can receive the raw HTTP response.
Another COOL stuff is that I think the EXECUTE panel can be linked with the new panel.
For example:

Every time we press the EXECUTE button, the new panel will auto-load the last HTTP raw request into the bigtext area.
When we are in the new panel, the EXECUTE button can send the raw HTTP request.
And I think maybe hackbar can move some encoding / decoding stuff into the right-click mouse panel.
It can save some space on the top bar and it's more user-friendly than the top bar.

I'm not a native English speaker and I don't know if my expression is accurate. Though the hackbar now it's very useful for us. If these recommendations can't be implemented we still think hackbar it's fantastic enough.

Thanks for your reply, have a nice day sir ๐Ÿ˜„

The left part can send a raw HTTP request
The right part can receive the raw HTTP response.

If I doesn't misunderstand your comment, what you want is a Fetch mode, which is implemented using fetch API, instead of Page mode?

"Page mode" is just a temporary name. Maybe you can give a nicer name.

  • Page mode (current behaviour)
    • Use different methods to implement GET/POST
      • GET: WebExtension API chrome.tabs.update
      • POST: Use chrome.tabs.executeScript to insert a form HTML element and submit it automatically
    • Only support GET/POST method, and has some limitation on POST body
    • The response is rendered in the page
  • Fetch mode
    • Use fetch API to get response, transform Response into a raw HTTP response and show it in the right panel
    • You can do anything supported by fetch
    • The response is NOT rendered in the page

About response rendering, Fetch mode will not render response. Or do you really want Fetch mode to render it?

Rendering in Fetch mode is possible by using document.write, but I think document.write behavior is not perfect to me.
That is why I prefer to not support it here. But if you really want it, I can try my best to do it.

Every time we press the EXECUTE button, the new panel will auto-load the last HTTP raw request into the bigtext area.
When we are in the new panel, the EXECUTE button can send the raw HTTP request.

Sorry that I cannot imagine the complete UI flow.
I think EXECUTE button is used to perform a request, not to load request.

And I think maybe hackbar can move some encoding / decoding stuff into the right-click mouse panel.
It can save some space on the top bar and it's more user-friendly than the top bar.

This is a good advice.
But I think it will not land in next release since it is needed to be designed.

BTW, I'm also not a native English speaker. ๐Ÿ˜†
I use English in GitHub just because I hope that others can know what we are talking about.

NEX-S commented

lol me 2 ๐Ÿ˜„

So Fetch mode have two panels that can send data like burpsute's repeater? I guess that is what we want ๐Ÿ‘

So we can call it the Repeater panel ?

Every time we press the EXECUTE button, the new panel will auto-load the last HTTP raw request into the bigtext area.
When we are in the new panel, the EXECUTE button can send the raw HTTP request.

I mean that EXECUTE can perform the request like it used to, but now whenever we press the EXECUTE button, hackbar can auto fill the HTTP request textarea in new Repeater for us.

For example ๐Ÿ˜ธ

when we use the hackbar as normal
image

after we hit the EXECUTE button to send the request to the server

now if we move into the new Repeater panel, we will get this:

Left Panel is the EXECUTE button's last send request

POST /post HTTP/1.1
Host: http://httpbin.org
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.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7
Cache-Control: no-cache
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Host: httpbin.org
Origin: http://httpbin.org
Pragma: no-cache
Proxy-Connection: keep-alive
Referer: http://httpbin.org/post
Upgrade-Insecure-Requests: 1
User-Agent: UUUUUSERAGENT
cookie: COOOOOOOOOKIEEEEEE
x-forwarded-for: 8.8.8.8

POOOOOOOOOOOOOOOST DATA

Right Panel is like this

HTTP/1.1 200 OK
Date: Sun, 02 Oct 2022 12:00:04 GMT
Content-Type: application/json
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: http://httpbin.org
Access-Control-Allow-Credentials: true
content-length: 908

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "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.9", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7", 
    "Cache-Control": "no-cache", 
    "Content-Length": "0", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Cookie": "COOOOOOOOOKIEEEEEE", 
    "Host": "httpbin.org", 
    "Origin": "http://httpbin.org", 
    "Pragma": "no-cache", 
    "Proxy-Connection": "keep-alive", 
    "Referer": "http://httpbin.org/post", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "UUUUUSERAGENT", 
    "X-Amzn-Trace-Id": "Root=1-63397d44-3ad67bce7ea053e3774e67b6"
  }, 
  "json": null, 
  "origin": "8.8.8.8, 159.138.40.195", 
  "url": "http://httpbin.org/post"
}

and now in the new repeater panel, the EXECUTE button can sent the data in the left textarea so don't need to design another button to send data.

Oh, so what you want is converting request from normal mode and auto-filling it in Fetch mode
Just like the following?

In normal mode
image

After change to Fetch mode
image

And no matter what changes made in the request, we can also see the changes after switching to another mode.
But the limitation of HTTP verbs / Content-type is only removed in Fetch mode.

NEX-S commented

yes!!!! ๐Ÿ˜„ that is what i want <3

NEX-S commented

I'll take a futher test to make hackbar more useful and user friendly ๐Ÿฅ‡

I have implemented a new mode called Raw mode.

You can build the latest version using mv3 branch or just download pre-built version from Release page.

BTW, since this issue, I set minimum_chrome_version to 107 in manifest.json for avoiding someone install it on Chrome <= 106.
Therefore, you need to wait for Chrome 107, or directly modify manifest.json to remove the limit if you want to try it immediately.

If there is any problem or suggestion, you can report it here. Or, I will close this issue after a while.

NEX-S commented

ohhhh, that's great!!!!!! I'll tell all of my friends to try it out :D

best wishes!

NEX-S commented

I have noticed that the new raw mode EXECUTE's result won't show on the current page we testing on (we need to hit the RENDER button to manually show result in browser's tab ), I don't know if this behavior is by design. Maybe can add a feature that will auto-render / show result in the browser's tab page just like basic mode?

BTW, I don't know if the browser cache will affect the hackbar's result, from now It seems the cache won't affect hackbar's EXECUTE result. If so, maybe can add a feature that can disable browser's cache ๐Ÿ’ฏ

Thank you ๐Ÿ†™

I don't know if this behavior is by design. Maybe can add a feature that will auto-render / show result in the browser's tab page.

Yes, it is by design now.
Since rendering is finished in extension page, I am afraid that there is some malicious code in rendered response, e.g. communicating with extension and sending other tab's request data to remote.
However, I think it may be able to mediated by checking connection issuer. I will take this advice into account latter.

I don't know if the browser cache will affect the hackbar's result, from now It seems the cache won't affect hackbar's EXECUTE result.

Currently, caching is disabled for any request issued in Raw mode.

If so, maybe can add a feature that can disable browser's cache.

Sorry that I don't understand your meaning. Since caching is disabled now, do you mean that you want a switch to enable caching? If so, because I think caching may affect pentester's judgement so that it should be disabled, may you describe your scenario?

NEX-S commented

it's my fault, just want to know if the cache is disabled by normal ( which is the expected behavior ) thx for your reply ๐Ÿ˜„

NEX-S commented

Yes, it is by design now.
Since rendering is finished in extension page, I am afraid that there is some malicious code in rendered response, e.g. communicating with extension and sending other tab's request data to remote.
However, I think it may be able to mediated by checking connection issuer. I will take this advice into account latter.

maybe can add an option called safe mode?

if safe mode is enabled, the page will be rendered in safe tabs

if it's not enabled, the page will be rendered in current tab

NEX-S commented

btw if safe mode is a good idea, we can add more stuff in it like disable web RTC to prevent real IP address leak ๐Ÿ’ฏ

NEX-S commented

btw if safe mode is a good idea, we can add more stuff in it like disabling web RTC to prevent real IP address leak

Oops, just get a new idea, maybe safe mode can be a page that contains many switches so we can set the safe feature we want separately

if safe mode is enabled, the page will be rendered in safe tabs
if it's not enabled, the page will be rendered in current tab

To render received response, there may be some solutions like the following:

  • Write HTML directly via document.open and document.write (Your second option)
    Since the origin is still the original one, I think it is totally unsafe.
    Scneario:
    1. Go to https://www.secret.com
    2. Render response, which contains code accessing to document.cookie, from https://www.malicious.com
  • Go to about:blank, and then call document.xxx like the first solution
    It seems that I cannot send necessary information for rendering, e.g. HTML, to injected content script.
    Therefore, I don't implement this solution.
  • Go to chrome-extension://yyy/render.html, where yyy is HackBar extension ID, and then call document.xxx (Your first option)
    If response contains code like chrome.runtime.connect, it can communicate with HackBar service worker, get some sensitive request data and then send back to remote server.
    Currently, I choose this solution because I may be mediated by checking connection creator (not yet implemented). Once implementation finished, I think we can make it automatically rendering response.

if safe mode is a good idea, we can add more stuff in it like disable web RTC to prevent real IP address leak

It's a good idea.

maybe safe mode can be a page that contains many switches so we can set the safe feature we want separately

What safe features do you want to have? Since chrome-extension://yyy/ already have some limitations, maybe what you want already exists.

NEX-S commented

What safe features do you want to have? Since chrome-extension://yyy/ already have some limitations, maybe what you want already exists.

I haven't learned JS so I don't know if there is any other Malicious JS code that can cause security flaws, from now just webRTC leak prevent ( actually there is a plugin that has already implemented this but it would be great if hackbar's safe-mode can integrate it so we don't have to install another plugin )

Write HTML directly via document.open and document.write (Your second option)
Since the origin is still the original one, I think it is totally unsafe.
Scneario:
Go to https://www.secret.com
Render response, which contains code accessing to document.cookie, from https://www.malicious.com

this sounds great! ๐Ÿ†™ because in testing we might need to send many requests to the server, In that case, we might need to get the response result in the current tab instead of the new tab.

If I didn't misunderstand you, go to about:blank and call document.xxx will open new tabs whenever the EXECUTE button being hit, in that case, tabs management will not that easy and that might not be the most people want ๐Ÿฅ‡

Go to chrome-extension://yyy/render.html, where yyy is HackBar extension ID, and then call document.xxx (Your first option)
If response contains code like chrome.runtime.connect, it can communicate with HackBar service worker, get some sensitive request data and then send back to remote server.
Currently, I choose this solution because I may be mediated by checking connection creator (not yet implemented). Once implementation finished, I think we can make it automatically rendering response.

It seems in the chrome-extension://yyy/asdf.html, other chrome plugins will be disabled, this might be a little unfriendly too users ๐Ÿ˜ฟ .

go to about:blank and call document.xxx will open new tabs

In fact, all solutions I mentioned use the same tab, not new one.

I haven't learned JS so I don't know if there is any other Malicious JS code that can cause security flaws

Oh, I forgot that it is impossible to execute malicious inline code in Manifest Version 3 because it is restricted by CSP.
So, there may be no security flaws now.

However, if we use solution 1, it will resend the original tab request (not the request in Raw mode) on clicking refresh button. I think it is not a good experience for user.

It seems in the chrome-extension://yyy/asdf.html, other chrome plugins will be disabled

No matter what solution we use, we finally call document.open and document.write to render the response.
I think other chrome plugins (e.g. JSON Viewer) will not works as expected even if we don't use chrome-extension://... because related content scripts are removed and there is no chance to insert scripts again.

If we want to solve this known issue, we need to figure out another solution, which is not mentioned above.

NEX-S commented

oh, if I didn't misunderstand your reply

  • if we use solution 1: we can't refresh the page and the other plugin will retain the first response status no matter how much we press the EXECEUTE button
  • if we use solution 2: every EXECUTE response will render in the same new tab and the other plugins will retain the first EXECUTE's response status, but it seems hard to implement.

I don't know if chrome provided any API that can inform the plugin refresh status ๐Ÿ˜ข

If I get any new idea, I will inform you, appreciate for your reply sir โค๏ธ

NEX-S commented

btw, is that possible to add HTML highlight in the response panel?

Here are some misunderstanding.

if we use solution 1: we can't refresh the page and the other plugin will retain the first response status no matter how much we press the EXECEUTE button

We can refresh the page but it sends the original request, and the plugin will be re-triggered.

Example:

  1. Go to https://www.google.com
  2. Execute a request https://www.example.com and render it
  3. Click refresh button
  4. It shows response from https://www.google.com, not from https://www.example.com

if we use solution 2: every EXECUTE response will render in the same new tab and the other plugins will retain the first EXECUTE's response status, but it seems hard to implement.

In fact, solution 2 cannot be implemented.

In theory, after executing a request https://www.example.com, I expect that it performs the following steps to render:

  1. Go to about:blank
  2. HackBar injects render script into the page, and it will register a listener to receive some data for rendering
  3. HackBar service worker send data to the page
  4. After receiving data, render script starts to render it

However, it failed in step 2.

I don't know if chrome provided any API that can inform the plugin refresh status

Unfortunately, there is no such API, otherwise I also want to trigger other plugins to make HackBar more perfect :(

is that possible to add HTML highlight in the response panel?

It cannot be done with current UI framework. However, I can try to introduce it via another way.

But I think it is out of this issue's scope. If you really want it, you can create a new issue for it.

Implemented :)

You can checkout testing branch and build it, then try solution 1 and 2.

Solution 1:

  1. Run php -S 127.0.0.1:8888 in contrib directory
  2. Go to https://www.example.com
  3. Execute http://127.0.0.1:8888/solution1.php and render it
  4. Click refresh button
  5. It shows https://www.example.com, not http://127.0.0.1:8888/solution1.php

Solution 2:

  1. Run php -S 127.0.0.1:8888 in contrib directory
  2. Go to https://www.example.com
  3. Execute http://127.0.0.1:8888/solution2.php and render it
  4. Open new tab and go to chrome://extensions/, you will find there is an error in HackBar
    image
NEX-S commented

got it! ๐Ÿ˜„

In my opinion, if directly rendering the page doesn't have any security flaws, directly rendering the response result might be more friendly than manual click the RENDER button. Here is my reason ๐Ÿ˜ธ

  • During the testing / CTF, we just modify the HTTP request and hit the EXECUTE button over and over again. The frequency of hitting EXECUTE is way larger than the RENDER button. In that case, most of us might wish to see the result immediately.

  • hackbar is using F12 panel and extra space to show HTTP response body is veeeery limited because most space is taken over by HTTP response header just like in the picture below.

image

so we have to scroll down to check out the HTML content or just press the RENDER button again to check out the render of the result, which is a little inconvenient compared with Basic MODE which could directly see the result on the right side.

  • If there is any unexpected behavior, our first instinct should be to press EXECUTE button again to resent the request. so fresh's bug seems not as important as the reason above. ( Even if we accidentally press the refresh button and our page roll back to the original request page, we still can press EXECUTE button to recover it.)

  • If we press the RENDER button in RENDER's result page chrome-extension://xxx/render.html the page will get blank, so we can't press the refresh button in solution 3 too.

solution 1 might not be perfect, but I think it is the closest to a perfect solution for now ๐Ÿ˜ธ

NEX-S commented

During these day's testing, I found that maybe hackbar can add this feature to improve the experience:

  • check if RAW MODE's Host is empty
    • if Host area is empty, the EXECUTE button will auto-load the current page's request and send it so we don't have to press LOAD and EXECUTE again, which is a verrry small improvement in user experience.
    • if Host area is already modified by the user with www.example.com/foo/bar/test.php, the EXECUTE button will parse URI for us and append the path in Request textarea like GET /foo/bar/test.php HTTP/1.1

image

this means if we got a very long URL, all we need to do is copy and paste it in Host Area and let Hackbar help us to parse it into Request Textarea so we don't need to manually cut the path behind the domain and paste it in Reqeust Textarea

Another problem is that Ctrl+f cant search in the current RAW MODE, I don't know if we can add a search box in RAW MODE and it would be great if this grep box can support regex which is very useful in HTTP crawler testing ๐Ÿ˜„

should I open another feature request? Now the hackbar is already very awesome, these new features can be implemented slowly, I hope you can rest well and have a nice day ๐Ÿ˜„

solution 1 might not be perfect, but I think it is the closest to a perfect solution for now

Okay, I think you are right if we consider HackBar's main target audience is pentester.

I will change it to solution 1 and support auto-rendering (enabled by default). But auto-rendering can be opt-out via a switch.

check if RAW MODE's Host is empty

Although it improves user experience, I think I will not implement the two function you mentioned. Here is the reason:

  • LOAD and EXECUTE can be triggered via hotkey
  • A function / field should only do its own job to make it maintainable

Another problem is that Ctrl+f cant search in the current RAW MODE, I don't know if we can add a search box in RAW MODE and it would be great if this grep box can support regex which is very useful in HTTP crawler testing

I can try to do this. You can create a new issue with some details (e.g. is it only needed for Response panel) for it.

NEX-S commented

bravo!

Oops, I found there is some problem if we use solution 1: base tag may be not respected by the browser.

This cause that img tag or other resouce cannot be rendered correctly since browser is unable to use correct URL to obtain them.

so we have to scroll down to check out the HTML content or just press the RENDER button again to check out the render of the result, which is a little inconvenient compared with Basic MODE which could directly see the result on the right side.

If refresh is not a problem to you and the point you care is auto-rendering, I think I prefer to continue to use solution 3 and implement auto-rendering.

Do you have other thought?

NEX-S commented

I donโ€™t know, just wish the RAW MODE can work like BASIC MODE ( send the request and get the reasult is just fine) I guess is the RAW MODEโ€™s implementation is difference than BASIC MODE?

NEX-S commented

btw i forgot to report the solution 3 have some render problem in some pages too, but I havenโ€™t take further test because I thought if RAW MODE response behavior can be like BASIC MODE ( not jump into chrome-extensions://xxx/render.html but the normal url just work well ) this problem will be solved too, now the things seems become more complicated, i guess we can just let it be๐Ÿฅฒ. maybe one day in the future we will get new idea to solve it perfectly :D

I guess is the RAW MODEโ€™s implementation is difference than BASIC MODE?

Yes, their implementation are different.

btw i forgot to report the solution 3 have some render problem in some pages too, but I havenโ€™t take further test because I thought if RAW MODE response behavior can be like BASIC MODE ( not jump into chrome-extensions://xxx/render.html but the normal url just work well ) this problem will be solved too, now the things seems become more complicated, i guess we can just let it be๐Ÿฅฒ. maybe one day in the future we will get new idea to solve it perfectly

Indeed, no matter which solution we use, there must be something cannot be rendered as expected since we use document.write to write HTML.

Just like you said, let it go until we get a new idea about rendering. :(

Related commits pushed

NEX-S commented

bravo! I'll take a try :D

NEX-S commented

I got a new idea: if RAW MODE can't work like BASIC MODE, maybe EXECUTE button can convert the RAW MODE's data into BASIC MODE in the background and send it (not jump into BASIC MODE) ( for now we need to do some editing in RAW MODE and change to BASIC MODE and EXECUTE to get normal Rendering and make other plugin works normal, it's little inconvenient )

but this idea got disadvantages: POST DATA must have = sign, if not, the POST DATA will not be sent ( which you explain in the previous issue )

so we can get a checker to check whether POST DATA has = or not.

  • if POST DATA have =, the RAW MODE's EXECUTE will parse the request panel and let BASIC MODE send it ( so we can use plugins like JSON-format / auto render / etc...) (which means we don't need the request data must be well-formated, it will improve the user-experience too)
  • if not, the RAW MODE will send the request itself.

is that possible?

From an implementation perspective, it is possible to use Basic implementation automatically.

However, it means that there are different behaviour in Raw mode:

  • POST data
    • contains = and is supported enctype -> Basic implementation
    • contains = but not supported enctype -> Raw implementation
    • doesn't contain = -> Raw implementation

If we use Basic implementation, raw response cannot be captured and displayed in Response panel. So, in the first situation, user may be confused.

Therefore, I prefer to add a hotkey for conveniently switching mode rather than make it generate different behaviour.

NEX-S commented

got it ๐Ÿ™Œ