惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
Recorded Future
Recorded Future
人人都是产品经理
人人都是产品经理
S
SegmentFault 最新的问题
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
Know Your Adversary
Know Your Adversary
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tor Project blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
T
Threatpost
T
Tenable Blog
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
C
Cisco Blogs
H
Heimdal Security Blog
Attack and Defense Labs
Attack and Defense Labs
A
About on SuperTechFans
Last Week in AI
Last Week in AI
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
V
V2EX
Cyberwarzone
Cyberwarzone
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog RSS Feed
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
T
The Blog of Author Tim Ferriss
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
U
Unit 42
PCI Perspectives
PCI Perspectives
P
Privacy International News Feed
D
Docker

Black Hills Information Security, Inc.

Bad Habits: An ANTISOC Operation Same Problem, Different Angles: When Red Team and Blue Team Actually Talk to Each Other How to Identify and Exploit New Vulnerabilities Swapper – A Pure Regex Match/Replace Burp Extension A Practical Guide to BloodHound Data Collection Network Engineering Basics Signed, Trusted, and Abused: Proxy Execution via WebView2 Getting Started In Pentesting – Advice From The BHIS Pentest Lead Cloud Security: Tips and Resources for Securing the Cloud Lessons From A Chatbot Incident How to Lead Effective Tabletops Understanding GRC: How to Navigate Risks and Compliance Standards The “P” in PAM is for Persistence: Linux Persistence Technique Malware Analysis: How to Analyze and Understand Malware OSINT: How to Find, Use, and Control Open-Source Intelligence What to Do with Your First Home Lab When the SOC Goes to Deadwood: A Night to Remember Social Engineering and Microsoft SSPR: The Road to Pwnage is Paved with Good Intentions Common Cyber Threats Finding the Right Penetration Testing Company Deceptive-Auditing: An Active Directory Honeypots Tool The Curious Case of the Comburglar How to Set Smart Goals (That Actually Work For You) Inside the BHIS SOC: A Conversation with Hayden Covington Abusing Delegation with Impacket (Part 3): Resource-Based Constrained Delegation Why You Got Hacked – 2025 Super Edition Abusing Delegation with Impacket (Part 2): Constrained Delegation Abusing Delegation with Impacket (Part 1): Unconstrained Delegation GoSpoof – Turning Attacks into Intel Model Context Protocol (MCP) Bypassing WAFs Using Oversized Requests Getting Started with AI Hacking Part 2: Prompt Injection Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 2) DomCat: A Domain Categorization Tool Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 1) Microsoft Store and WinGet: Security Risks for Corporate Environments Default Web Content MailFail Commonly Abused Administrative Utilities: A Hidden Risk to Enterprise Security Stop Spoofing Yourself! Disabling M365 Direct Send Bypassing CSP with JSONP: Introducing JSONPeek and CSP B Gone Offensive Tooling Cheatsheets: An Infosec Survival Guide Resource DNS Triage Cheatsheet GraphRunner Cheatsheet Burp Suite Cheatsheet Impacket Cheatsheet Wireshark Cheatsheet Hashcat Cheatsheet EyeWitness Cheatsheet Nmap Cheatsheet Netcat (nc) Cheatsheet Hunt for Weak Spots in Your Wireless Network with Airodump-ng from the Aircrack-ng Suite Detecting ADCS Privilege Escalation Vulnerability Scanning with Nmap Getting Started with NetExec: Streamlining Network Discovery and Access How to Use Dirsearch Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 3: Arcanum Cyber Security Bot How to Design and Execute Effective Social Engineering Attacks by Phone Abusing S4U2Self for Active Directory Pivoting Why Use a Macro Pad? Espanso: Text Replacement, the Easy Way Caging Copilot: Lessons Learned in LLM Security Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 2: Copilot Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 1: Burpference Intercepting Traffic for Mobile Applications that Bypass the System Proxy How to Root Android Phones Communicating Security to the C-Suite: A Strategic Approach Offline Memory Forensics With Volatility Getting Started with AI Hacking: Part 1 Go-Spoof: A Tool for Cyber Deception How to Test Adversary-in-the-Middle Without Hacking Tools Canary in the Code: Alert()-ing on XSS Exploits How to Hack Wi-Fi with No Wi-Fi Why Your Org Needs a Penetration Test Program Burp Suite Extension: Copy For Light at the End of the Dark Web Wi-Fi Forge: Practice Wi-Fi Security Without Hardware Avoiding Dirty RAGs: Retrieval-Augmented Generation with Ollama and LangChain Gone Phishing: Installing GoPhish and Creating a Campaign 5 Things We Are Going to Continue to Ignore in 2025 John Strand’s 5 Phase Plan For Starting in Computer Security Questions From a Beginner Threat Hunter GRC for Security Managers: From Checklists to Influence AI Large Language Models and Supervised Fine Tuning Attack Tactics 9: Shadow Creds for PrivEsc w/ Kent & Jordan One Active Directory Account Can Be Your Best Early Warning Introduction to Zeek Log Analysis Indecent Exposure: Your Secrets are Showing Creating Burp Extensions: A Beginner’s Guide Pitting AI Against AI: Using PyRIT to Assess Large Language Models (LLMs) The Top Ten List of Why You Got Hacked This Year (2023/2024) ICS Hard Knocks: Mitigations to Scenarios Found in ICS/OT Backdoors & Breaches Intro to Data Analytics Using SQL Finding Access Control Vulnerabilities with Autorize The Detection Engineering Process Cyber Risk Lessons We Can Learn From Hurricane Preparedness Intro to Desktop Application Testing Methodology What Is Penetration Testing? Adversary in the Middle (AitM): Post-Exploitation Pentesting, Threat Hunting, and SOC: An Overview
How to Build a Pentest Robot With Selenium IDE
Kassie Kimball · 2023-02-03 · via Black Hills Information Security, Inc.

Sean Verity //

Have you ever been on a pentest and thought to yourself, “I wish I had a robot to do this testing for me right now cuz this is just too much work”?

I know I have. That’s how I came to use the QA tool, Selenium IDE, to automate things like:

  • Brute forcing complicated authentication protocols. See Amazon Cognito’s implementation of Secure Remote Password, for example.
  • Password spraying services where tooling is not available and there’s not enough time and/or willpower to figure out how to configure a Burp Suite Intruder attack with complicated CSRF mitigations.
  • Harvesting email addresses from organizations’ websites when they are dynamically rendered (i.e. nothing to grep from the HTML source).
  • Working around Google reCAPTCHA. Selenium IDE automation can help with the transparent sort of reCAPTCHA where a JavaScript challenge needs to be solved (not the annoying “Click all the panda bears in this grid” type of challenge).

Before we get started though, I want to point out that the demo to be presented in this blog was atypical insofar as there were some unique challenges presented with this particular app. My goal with this blog is to provide you with a reference for ideas on how to troubleshoot when your Selenium IDE tests aren’t working. It is typically much easier to automate your browser with Selenium IDE.

To show you how to build a pentest robot with Selenium IDE, we’ll take a look at how to brute force an example React app that I put together. The example app was built by following this excellent blog: Build an Authentication System with AWS Amplify, Cognito and React. The app uses Amazon Cognito’s SRP for authentication which, as we’ll see, is just about impossible to automate with Burp Suite’s Intruder module.

According to Wikipedia, SRP is “an augmented password-authenticated key exchange (PAKE) protocol” where “the password never leaves the client.”1 That second phrase already sounds like a deal breaker for running a Burp Intruder attack. Usually, when using Burp Intruder for authentication attacks, you need to mark the password position in the HTTP request. If the password never leaves the client though (i.e. password is not sent in HTTP request), how can you mark the password position?

Here’s what the login form looked like for my React app during authentication.

Requests were sent to “cognito-idp.us-east-2.amazonaws.com” after clicking the “Sign In” button. As can be seen in the following screenshot, the username was pretty easy to spot. The password…not so much. It seems that Wikipedia was right about the password not leaving the client.

Since using Burp Intruder won’t work for brute forcing this login form, I considered writing a Burp extension that implemented SRP. Before going down that rabbit hole, though, I took a peek at what would need to be implemented. The screenshot below was taken from a Stanford University webpage that describes the SRP Protocol Design.

Prime, modulo, salt, exponentiation, you say?

It would probably be easier to build a robot that would do this brute force testing for me. Ok, so maybe the robot idea isn’t actually feasible either. But what if there was a tool that was easy to install and easy to configure (most of the time) that would automatically fill in the login form fields and click the “Sign In” button? Ah, but there is such a tool! And its name is Selenium IDE (SIDE).

To find and install SIDE, you can search your browser’s extension store or favorite search engine for “selenium ide.” After installing SIDE, there’s some preliminary things to do like naming the project and setting the base URL. The base URL is where you want SIDE to start the test from. In the same window where you enter the base URL, there will be a button titled, “Start Recording.” This will open a new browser instance with a bubble at the bottom of the window that says, “Selenium IDE is recording…”. Since I’m going to be brute forcing the login form, I just need to fill out the login form and click the “Sign In” button like a typical user.

After logging in, I’m redirected to a very basic dashboard which indicates that I’ve authenticated.

All that I needed to record was the login process so I clicked the stop recording button and named the test. At this point, the next step is to verify that the login process was recorded successfully by clicking the “Play” button. There are a couple of “Play” buttons in the UI. The one on the left will play back all of the tests inside of a project whereas the one on the right will only play back the selected test. Since there is only one test at this point, either button would work.

After I clicked the “Play” button, SIDE ran the test and the log indicated that the test completed successfully. However, the browser was still on the login page as opposed to the dashboard after the login form was submitted. While watching the test run, there was no data being entered into either form field.

After much blood, sweat, and tears were shed while putting together this demo, I learned that the problem lay in SIDE’s inability to find elements inside of a “shadow DOM.”2 Shadow DOM is basically a DOM that is nested inside of a DOM, which sounds to me like a recipe for use-after-free bugs, but that’s another topic and I’m sure there are really good reasons why shadow DOM exists, but I digress. Since both form fields lived in shadow DOMs, I had to try a different approach to populating the form fields. SIDE has an “execute script” command which will execute JavaScript inside of the DOM where your test is running. We can use this command to select and populate the form fields.

Now before we go and start rage coding JavaScript inside the SIDE UI like a crazy person, let’s take a step back and make sure that the JavaScript is sound, using the JavaScript console in 00DevTools. I decided to start with a simple task of writing a line of JavaScript that would select the username field and populate it with an arbitrary username. The first thing to figure out is how to access the username field. Usually, you can use something like the document.getElementById()3 method and pass the ID of the targeted element. In this case, it appeared that the username form field ID was “username.” It also looked like there was an event handler for “input” events attached to it.

If my assumptions were correct, then calling document.getElementById(“username”) would return the string, “abcdef”. Let’s test this theory out in the console tab.

Ugh. Looks like I need to dig a little deeper to come up with a way to select this form field. Not that we didn’t already know that, since I mentioned the shadow DOM issue earlier. If we take another look at where the username form field is located, we can see that it’s inside of a shadow DOM, which is nested inside of another shadow DOM, that is nested inside of the DOM. Easy peasy, yeah?

The other thing to take note of here is that there aren’t a whole lot of element IDs to traverse in the shadow DOMs, which means that we can’t use getElementById() to traverse the shadow DOMs. No big deal though. We can use the document.querySelector()4 method instead. To select the username form field, we’re going to:

  • Select the element right before the first shadow DOM root with querySelector()
  • Select the shadowRoot property
  • Select the element right before the second shadow DOM root
  • Select the shadowRoot property
  • At this point, we’ll be inside of the second shadow DOM so we can use getElementById(“username”) to select the username field

Here’s what all of that looks like in the console.

Now that we have some working JavaScript to get the username form field value, we just need to make a minor tweak to set the username value. The other piece that needs to be accounted for is the event handler that I highlighted earlier. This piece isn’t so bad though. We can use the same form field selector code then call dispatchEvent()5 method on it to send the “input” event. Here’s what the JavaScript looks like in the console tab.

At this point, we have all of the JavaScript needed to select and populate the username form field. The next step is to use the same techniques to populate the password field and call the click() method on the “Sign In” button. Here’s what the final JavaScript looked like.

Each line of JavaScript can be copied into a SIDE “execute script” command. BTW, I deleted all the “click” commands from the original test since they weren’t doing anything useful. Here’s what the final SIDE test to login looked like.

To make sure this works, let’s click the “Play” button. If all goes according to plan, the new SIDE test will login to the app and stop at the dashboard.

It worked! Now that we have the login piece automated, we need the SIDE test to loop through a list of passwords for brute forcing. We’ll use a little bit of JavaScript to create an array of passwords, SIDE’s “return” keyword to access the array, and SIDE’s “for each” command to iterate through the array. To start, right click on the first command inside of SIDE to insert a new command before the login process.

This first command will return an array of passwords to SIDE, named “passwordList”.

Next, I’ll add “for each” and “end” commands to loop through the passwordList array. The array name will go in the “Target” field and the iterator name will go in the “Value” field of the “for each” command. The “end” command is also needed at the very end of the test to close the loop.

The last step is to remove the hard-coded password from the command that populates the password form field, and replace it with the iterator variable. The syntax for accessing SIDE variables is ${variable}. One other change that I’m going to make to this test is adding a three second delay after each login attempt with the “pause” command. The duration is entered in milliseconds. SIDE warned me that “Hard coded sleeps are old hat,” but we know better, so I clicked on the OK button.

The delay gives the app enough time to process the login request. On a SIDE note 😉, when troubleshooting a SIDE test that fails to execute, my first move is to add a delay. I’ve found this to be pretty effective most of the time.

Here’s what the final SIDE test looked like to brute force the app. At a mere ten lines of “code,” that’s not too bad, eh?

I hope you’re not too disappointed that I didn’t show you how to build a robot, but hopefully you came up with some ideas on how you could use Selenium IDE on your next pentest or red team assessment when you’re short on time or tooling.

References

[1] https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol

[2] https://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/#:~:text=Shadow%20DOM%20refers%20to%20the,the%20main%20document%20DOM%20tree.

[3] https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

[4] https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

[5] https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent



Ready to learn more?

Level up your skills with affordable classes from Antisyphon!

Pay-What-You-Can Training

Available live/virtual and on-demand