diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/inject.php b/inject.php new file mode 100644 index 0000000..710e437 --- /dev/null +++ b/inject.php @@ -0,0 +1,60 @@ +<?php +// Set the file path +$dataSendFilePath = 'data_send'; +$dataRecvFilePath = 'data_recv'; + +// Check if the payload parameter is set +if (isset($_REQUEST['response'])) { + $response = $_REQUEST['response']; + file_put_contents($dataRecvFilePath, $response); + file_put_contents($dataSendFilePath, ''); + die(); +} + +// Check if the "payload" parameter exists in the request +if (isset($_REQUEST['payload'])) { + // Get the payload value + $payload = $_REQUEST['payload']; + + // Acquire an exclusive lock on the "data_send" file + $sendFile = fopen('data_send', 'w'); + if (flock($sendFile, LOCK_EX)) { + // Write the payload to the "data_send" file + fwrite($sendFile, $payload); + + // Release the lock and close the file + flock($sendFile, LOCK_UN); + fclose($sendFile); + } else { + // Failed to acquire the lock + die('Failed to write payload to data_send file.'); + } +} + +// Check if the "data_recv" file contains data +while (true) { + $dataRecv = file_get_contents('data_recv'); + + // Check if the file contains data + if (!empty($dataRecv)) { + // Display the data + echo $dataRecv; + + file_put_contents($dataRecvFilePath, ''); + file_put_contents($dataSendFilePath, ''); + // Exit the loop + break; + } + + // Wait for a second before checking again + sleep(1); +} + + + + + + + + +?> \ No newline at end of file diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/inject.php b/inject.php new file mode 100644 index 0000000..710e437 --- /dev/null +++ b/inject.php @@ -0,0 +1,60 @@ +<?php +// Set the file path +$dataSendFilePath = 'data_send'; +$dataRecvFilePath = 'data_recv'; + +// Check if the payload parameter is set +if (isset($_REQUEST['response'])) { + $response = $_REQUEST['response']; + file_put_contents($dataRecvFilePath, $response); + file_put_contents($dataSendFilePath, ''); + die(); +} + +// Check if the "payload" parameter exists in the request +if (isset($_REQUEST['payload'])) { + // Get the payload value + $payload = $_REQUEST['payload']; + + // Acquire an exclusive lock on the "data_send" file + $sendFile = fopen('data_send', 'w'); + if (flock($sendFile, LOCK_EX)) { + // Write the payload to the "data_send" file + fwrite($sendFile, $payload); + + // Release the lock and close the file + flock($sendFile, LOCK_UN); + fclose($sendFile); + } else { + // Failed to acquire the lock + die('Failed to write payload to data_send file.'); + } +} + +// Check if the "data_recv" file contains data +while (true) { + $dataRecv = file_get_contents('data_recv'); + + // Check if the file contains data + if (!empty($dataRecv)) { + // Display the data + echo $dataRecv; + + file_put_contents($dataRecvFilePath, ''); + file_put_contents($dataSendFilePath, ''); + // Exit the loop + break; + } + + // Wait for a second before checking again + sleep(1); +} + + + + + + + + +?> \ No newline at end of file diff --git a/proxy-to-php-server.sh b/proxy-to-php-server.sh new file mode 100755 index 0000000..0b1ff6d --- /dev/null +++ b/proxy-to-php-server.sh @@ -0,0 +1,25 @@ +#!/bin/bash -x + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 + +# get a random port -- this could be improved +port=$(shuf -i 2048-65000 -n 1) + +# start the PHP server in the background +if [[ -d "$(realpath ${1:?Missing path to serve})" ]]; then + php -S localhost:"${port}" -t "$(realpath ${1:?Missing path to serve})" & +else + php -S localhost:"${port}" "$(realpath ${1:?Missing path to serve})" & +fi +pid=$! + +# try to adjust delay to improve performances +sleep 0.2 + +# proxy standard in to nc on that port +nc localhost "${port}" + +# kill the server we started +kill "${pid}" diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/inject.php b/inject.php new file mode 100644 index 0000000..710e437 --- /dev/null +++ b/inject.php @@ -0,0 +1,60 @@ +<?php +// Set the file path +$dataSendFilePath = 'data_send'; +$dataRecvFilePath = 'data_recv'; + +// Check if the payload parameter is set +if (isset($_REQUEST['response'])) { + $response = $_REQUEST['response']; + file_put_contents($dataRecvFilePath, $response); + file_put_contents($dataSendFilePath, ''); + die(); +} + +// Check if the "payload" parameter exists in the request +if (isset($_REQUEST['payload'])) { + // Get the payload value + $payload = $_REQUEST['payload']; + + // Acquire an exclusive lock on the "data_send" file + $sendFile = fopen('data_send', 'w'); + if (flock($sendFile, LOCK_EX)) { + // Write the payload to the "data_send" file + fwrite($sendFile, $payload); + + // Release the lock and close the file + flock($sendFile, LOCK_UN); + fclose($sendFile); + } else { + // Failed to acquire the lock + die('Failed to write payload to data_send file.'); + } +} + +// Check if the "data_recv" file contains data +while (true) { + $dataRecv = file_get_contents('data_recv'); + + // Check if the file contains data + if (!empty($dataRecv)) { + // Display the data + echo $dataRecv; + + file_put_contents($dataRecvFilePath, ''); + file_put_contents($dataSendFilePath, ''); + // Exit the loop + break; + } + + // Wait for a second before checking again + sleep(1); +} + + + + + + + + +?> \ No newline at end of file diff --git a/proxy-to-php-server.sh b/proxy-to-php-server.sh new file mode 100755 index 0000000..0b1ff6d --- /dev/null +++ b/proxy-to-php-server.sh @@ -0,0 +1,25 @@ +#!/bin/bash -x + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 + +# get a random port -- this could be improved +port=$(shuf -i 2048-65000 -n 1) + +# start the PHP server in the background +if [[ -d "$(realpath ${1:?Missing path to serve})" ]]; then + php -S localhost:"${port}" -t "$(realpath ${1:?Missing path to serve})" & +else + php -S localhost:"${port}" "$(realpath ${1:?Missing path to serve})" & +fi +pid=$! + +# try to adjust delay to improve performances +sleep 0.2 + +# proxy standard in to nc on that port +nc localhost "${port}" + +# kill the server we started +kill "${pid}" diff --git a/script.js b/script.js new file mode 100644 index 0000000..d5a04cc --- /dev/null +++ b/script.js @@ -0,0 +1,238 @@ + var dataSendUsed = false; + var checkSend = false; + + function clearPage(){ + $('#cswsh-output').empty(); + $('html, body').scrollTop($(document).height()); + } + + function startSnooping(){ + $('#startSnoop').hide(); + $('#stopSnoop').show(); + $('.sendBar').show(); + $('#wssSendText').focus(); + writeToScreen("Start snooping: " + $("#cswshURL").val()); + checkCSWSH(); + checkSend = true; + checkDataSend(); + } + + function stopSnooping(){ + $('#startSnoop').show(); + $('#stopSnoop').hide(); + $('.sendBar').hide(); + websocket.close(); + checkSend = false + writeToScreen("Stop snooping"); + } + + function checkCSWSH(){ + var wsUri = $("#cswshURL").val(); + + statusWaiting(); + websocket = new WebSocket(wsUri); + websocket.onopen = function(evt) { onOpen(evt) }; + websocket.onclose = function(evt) { onClose(evt) }; + websocket.onmessage = function(evt) { onMessage(evt) }; + websocket.onerror = function(evt) { onError(evt) }; + } + + function onOpen(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"CONNECTED"); + statusConnected() + //doSend("origin policy unchecked!"); + } + + function onClose(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"DISCONNECTED"); + statusOffline() + if( $('#stopSnoop').css('display') != 'none' ){ + checkCSWSH() + } + } + + function onMessage(evt) { + var encodedData = encodeToHtmlEntities(evt.data); + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #A7E734;">RECV:</span><span> ' + encodedData + '</span>'); + + var recvValue = encodedData.trim(); + if (dataSendUsed) { + sendToInjectPHP(recvValue); + } + var sendValue = getSendValueForRecv(recvValue); + if (sendValue) { + doSendAuto(sendValue); + } + } + + // Function to get the corresponding "send" value for a "recv" value + function getSendValueForRecv(recvValue) { + var valueTable = document.getElementById("valueTable"); + var rows = valueTable.getElementsByTagName("tr"); + for (var i = 0; i < rows.length; i++) { + var cells = rows[i].getElementsByTagName("td"); + if (cells.length === 3 && cells[0].innerText.trim() === recvValue) { + return cells[1].innerText.trim(); + } + } + return null; + } + + function onError(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: red;">ERROR:</span> ' + encodeToHtmlEntities(evt.data)); + } + + function doSend(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"SENT: " + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendAuto(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #bd34e7;">AUTO:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendPayload(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #e734bd;">INJT:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + var sentData = null; +function checkDataSend() { + if(checkSend == true){ + $.ajax({ + url: "/data_send", + method: "GET", + dataType: "text", + async:false, + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (data) { + if (data && data !== sentData) { + console.log(data); + doSendPayload(data); + sentData = data; + dataSendUsed = true; // Set the variable to true if data_send is used + //sendToInjectPHP(recvValue); // Call sendToInjectPHP unconditionally + } + } + }); + + // Check again after a delay + setTimeout(checkDataSend, 2000); + } + return false; +} + +function sendToInjectPHP(data) { + if (dataSendUsed) { + dataSendUsed = false; + var url = "/inject.php?response=" + encodeURIComponent(data); + + $.ajax({ + url: url, + method: "GET", + dataType: "text", + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (response) { + // Handle success if necessary + } + + }); + } +} + + + + function writeToScreen(message){ + output = document.getElementById("cswsh-output"); + var pre = document.createElement("div"); + pre.style.wordWrap = "break-word"; + pre.innerHTML = message; + output.appendChild(pre); + $('html, body').scrollTop($(document).height()); + } + + $("#wssCommand").submit(function(e) { + doSend( $('#wssSendText').val() ); + $('#wssSendText').val(""); + $('#wssSendText').focus(); + e.preventDefault(); + }); + + function statusConnected(){ + $('#status').html("Connected"); + $('#status').css("color","lightgreen"); + } + function statusOffline(){ + $('#status').html("Offline"); + $('#status').css("color","red"); + } + function statusWaiting(){ + $('#status').html("Waiting..."); + $('#status').css("color","yellow"); + } + + // Function to store recv and send values + function storeValues() { + var recvValue = document.getElementById("recvInput").value; + var sendValue = document.getElementById("sendInput").value; + + if (recvValue && sendValue) { + var newRow = document.createElement("tr"); + newRow.innerHTML = + "<td>" + + recvValue + + "</td><td>" + + sendValue + + '</td><td><a class="removeButton" onclick="removeRow(this)">[x]</a></td>'; + document.getElementById("valueTableBody").appendChild(newRow); + + // Clear input fields + document.getElementById("recvInput").value = ""; + document.getElementById("sendInput").value = ""; + } + } + + // Function to remove a row from the table + function removeRow(button) { + var row = button.parentNode.parentNode; + row.parentNode.removeChild(row); + } + + function encodeToHtmlEntities(str) { + var encodedStr = ""; + for (var i = 0; i < str.length; i++) { + var charCode = str.charCodeAt(i); + if (charCode > 127 || /[&<>"'`]/.test(str[i])) { + encodedStr += "&#" + charCode + ";"; + } else { + encodedStr += str.charAt(i); + } + } + return encodedStr; + } + + function getTimestamp() { + var now = new Date(); + var day = now.getDate(); + var month = now.getMonth() + 1; // Adding 1 because months are zero-based + var hours = now.getHours(); + var minutes = now.getMinutes(); + + // Pad single digits with leading zeros + day = day < 10 ? '0' + day : day; + month = month < 10 ? '0' + month : month; + hours = hours < 10 ? '0' + hours : hours; + minutes = minutes < 10 ? '0' + minutes : minutes; + + var timestamp = '[' + day + '/' + month + ' ' + hours + ':' + minutes + ']'; + return timestamp; + } + + //setTimeout(checkDataSend(), 1000); \ No newline at end of file diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/inject.php b/inject.php new file mode 100644 index 0000000..710e437 --- /dev/null +++ b/inject.php @@ -0,0 +1,60 @@ +<?php +// Set the file path +$dataSendFilePath = 'data_send'; +$dataRecvFilePath = 'data_recv'; + +// Check if the payload parameter is set +if (isset($_REQUEST['response'])) { + $response = $_REQUEST['response']; + file_put_contents($dataRecvFilePath, $response); + file_put_contents($dataSendFilePath, ''); + die(); +} + +// Check if the "payload" parameter exists in the request +if (isset($_REQUEST['payload'])) { + // Get the payload value + $payload = $_REQUEST['payload']; + + // Acquire an exclusive lock on the "data_send" file + $sendFile = fopen('data_send', 'w'); + if (flock($sendFile, LOCK_EX)) { + // Write the payload to the "data_send" file + fwrite($sendFile, $payload); + + // Release the lock and close the file + flock($sendFile, LOCK_UN); + fclose($sendFile); + } else { + // Failed to acquire the lock + die('Failed to write payload to data_send file.'); + } +} + +// Check if the "data_recv" file contains data +while (true) { + $dataRecv = file_get_contents('data_recv'); + + // Check if the file contains data + if (!empty($dataRecv)) { + // Display the data + echo $dataRecv; + + file_put_contents($dataRecvFilePath, ''); + file_put_contents($dataSendFilePath, ''); + // Exit the loop + break; + } + + // Wait for a second before checking again + sleep(1); +} + + + + + + + + +?> \ No newline at end of file diff --git a/proxy-to-php-server.sh b/proxy-to-php-server.sh new file mode 100755 index 0000000..0b1ff6d --- /dev/null +++ b/proxy-to-php-server.sh @@ -0,0 +1,25 @@ +#!/bin/bash -x + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 + +# get a random port -- this could be improved +port=$(shuf -i 2048-65000 -n 1) + +# start the PHP server in the background +if [[ -d "$(realpath ${1:?Missing path to serve})" ]]; then + php -S localhost:"${port}" -t "$(realpath ${1:?Missing path to serve})" & +else + php -S localhost:"${port}" "$(realpath ${1:?Missing path to serve})" & +fi +pid=$! + +# try to adjust delay to improve performances +sleep 0.2 + +# proxy standard in to nc on that port +nc localhost "${port}" + +# kill the server we started +kill "${pid}" diff --git a/script.js b/script.js new file mode 100644 index 0000000..d5a04cc --- /dev/null +++ b/script.js @@ -0,0 +1,238 @@ + var dataSendUsed = false; + var checkSend = false; + + function clearPage(){ + $('#cswsh-output').empty(); + $('html, body').scrollTop($(document).height()); + } + + function startSnooping(){ + $('#startSnoop').hide(); + $('#stopSnoop').show(); + $('.sendBar').show(); + $('#wssSendText').focus(); + writeToScreen("Start snooping: " + $("#cswshURL").val()); + checkCSWSH(); + checkSend = true; + checkDataSend(); + } + + function stopSnooping(){ + $('#startSnoop').show(); + $('#stopSnoop').hide(); + $('.sendBar').hide(); + websocket.close(); + checkSend = false + writeToScreen("Stop snooping"); + } + + function checkCSWSH(){ + var wsUri = $("#cswshURL").val(); + + statusWaiting(); + websocket = new WebSocket(wsUri); + websocket.onopen = function(evt) { onOpen(evt) }; + websocket.onclose = function(evt) { onClose(evt) }; + websocket.onmessage = function(evt) { onMessage(evt) }; + websocket.onerror = function(evt) { onError(evt) }; + } + + function onOpen(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"CONNECTED"); + statusConnected() + //doSend("origin policy unchecked!"); + } + + function onClose(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"DISCONNECTED"); + statusOffline() + if( $('#stopSnoop').css('display') != 'none' ){ + checkCSWSH() + } + } + + function onMessage(evt) { + var encodedData = encodeToHtmlEntities(evt.data); + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #A7E734;">RECV:</span><span> ' + encodedData + '</span>'); + + var recvValue = encodedData.trim(); + if (dataSendUsed) { + sendToInjectPHP(recvValue); + } + var sendValue = getSendValueForRecv(recvValue); + if (sendValue) { + doSendAuto(sendValue); + } + } + + // Function to get the corresponding "send" value for a "recv" value + function getSendValueForRecv(recvValue) { + var valueTable = document.getElementById("valueTable"); + var rows = valueTable.getElementsByTagName("tr"); + for (var i = 0; i < rows.length; i++) { + var cells = rows[i].getElementsByTagName("td"); + if (cells.length === 3 && cells[0].innerText.trim() === recvValue) { + return cells[1].innerText.trim(); + } + } + return null; + } + + function onError(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: red;">ERROR:</span> ' + encodeToHtmlEntities(evt.data)); + } + + function doSend(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"SENT: " + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendAuto(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #bd34e7;">AUTO:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendPayload(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #e734bd;">INJT:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + var sentData = null; +function checkDataSend() { + if(checkSend == true){ + $.ajax({ + url: "/data_send", + method: "GET", + dataType: "text", + async:false, + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (data) { + if (data && data !== sentData) { + console.log(data); + doSendPayload(data); + sentData = data; + dataSendUsed = true; // Set the variable to true if data_send is used + //sendToInjectPHP(recvValue); // Call sendToInjectPHP unconditionally + } + } + }); + + // Check again after a delay + setTimeout(checkDataSend, 2000); + } + return false; +} + +function sendToInjectPHP(data) { + if (dataSendUsed) { + dataSendUsed = false; + var url = "/inject.php?response=" + encodeURIComponent(data); + + $.ajax({ + url: url, + method: "GET", + dataType: "text", + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (response) { + // Handle success if necessary + } + + }); + } +} + + + + function writeToScreen(message){ + output = document.getElementById("cswsh-output"); + var pre = document.createElement("div"); + pre.style.wordWrap = "break-word"; + pre.innerHTML = message; + output.appendChild(pre); + $('html, body').scrollTop($(document).height()); + } + + $("#wssCommand").submit(function(e) { + doSend( $('#wssSendText').val() ); + $('#wssSendText').val(""); + $('#wssSendText').focus(); + e.preventDefault(); + }); + + function statusConnected(){ + $('#status').html("Connected"); + $('#status').css("color","lightgreen"); + } + function statusOffline(){ + $('#status').html("Offline"); + $('#status').css("color","red"); + } + function statusWaiting(){ + $('#status').html("Waiting..."); + $('#status').css("color","yellow"); + } + + // Function to store recv and send values + function storeValues() { + var recvValue = document.getElementById("recvInput").value; + var sendValue = document.getElementById("sendInput").value; + + if (recvValue && sendValue) { + var newRow = document.createElement("tr"); + newRow.innerHTML = + "<td>" + + recvValue + + "</td><td>" + + sendValue + + '</td><td><a class="removeButton" onclick="removeRow(this)">[x]</a></td>'; + document.getElementById("valueTableBody").appendChild(newRow); + + // Clear input fields + document.getElementById("recvInput").value = ""; + document.getElementById("sendInput").value = ""; + } + } + + // Function to remove a row from the table + function removeRow(button) { + var row = button.parentNode.parentNode; + row.parentNode.removeChild(row); + } + + function encodeToHtmlEntities(str) { + var encodedStr = ""; + for (var i = 0; i < str.length; i++) { + var charCode = str.charCodeAt(i); + if (charCode > 127 || /[&<>"'`]/.test(str[i])) { + encodedStr += "&#" + charCode + ";"; + } else { + encodedStr += str.charAt(i); + } + } + return encodedStr; + } + + function getTimestamp() { + var now = new Date(); + var day = now.getDate(); + var month = now.getMonth() + 1; // Adding 1 because months are zero-based + var hours = now.getHours(); + var minutes = now.getMinutes(); + + // Pad single digits with leading zeros + day = day < 10 ? '0' + day : day; + month = month < 10 ? '0' + month : month; + hours = hours < 10 ? '0' + hours : hours; + minutes = minutes < 10 ? '0' + minutes : minutes; + + var timestamp = '[' + day + '/' + month + ' ' + hours + ':' + minutes + ']'; + return timestamp; + } + + //setTimeout(checkDataSend(), 1000); \ No newline at end of file diff --git a/simple-php-webserver.sh b/simple-php-webserver.sh new file mode 100755 index 0000000..b9c0ad4 --- /dev/null +++ b/simple-php-webserver.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 +# https://www.php.net/manual/en/features.commandline.webserver.php + +# Config +LISTEN_INTERFACE="127.0.0.1" +LISTEN_PORT=8082 +ENTRY_POINT=$1 + +# Detect server type to use +PHP_SRV_TYPE=$(php -r "if (version_compare(phpversion(), '7.4', '<')) { echo 'tcpserver'; } else { echo 'embedded'; }") + +# Run detected server type +if [[ $PHP_SRV_TYPE == 'embedded' ]]; then + if [[ -d $ENTRY_POINT ]]; then + PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} -t $ENTRY_POINT + else + PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} $ENTRY_POINT + fi +else + tcpserver -v -1 0 ${LISTEN_PORT} ./proxy-to-php-server.sh $ENTRY_POINT +fi diff --git a/README.md b/README.md index 5502e50..d01ed27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ WSSSnoop =============== -play with websockets intercept and inject data \ No newline at end of file +Play with websockets intercept and inject data + + + +# <u>Installing</u> +Simply clone the repo, make the bash scripts executable, run "simple-php-webserver.sh" and browse to the correct URL to get started: + + + $> git clone https://rossmarks.uk/git/git/0xRoM/WSSSnoop.git + $> cd WSSSnoop + $> chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh + $> ./simple-php-webserver.sh + diff --git a/WSSSnoop.html b/WSSSnoop.html new file mode 100755 index 0000000..dc49e96 --- /dev/null +++ b/WSSSnoop.html @@ -0,0 +1,65 @@ +<html> +<head> + <title>WSSSnoop</title> + <link rel="stylesheet" href="/style.css" type="text/css" /> + <link href='http://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'> +</head> +<body> + <div class="topBar"> + <div class="topTitle"> + WSSSnoop + </div> + <center> + <input type="text" name="cswshURL" id="cswshURL" value="" placeholder="wss://snoop.me" style="width: 500px;"> + <input type="button" id="startSnoop" value="start snooping" onclick="startSnooping()"/> + <input type="button" id="stopSnoop" value="stop snooping" style="display:none" onclick="stopSnooping()"/> + <br /> + <div class="topcorner"> + Status: <div id="status" style="display:inline-block; color:red"/>Offline</div> + </div> + </center> + </div> + + <div class="container"> + + <div class="sidebar"> + <div class="auto-header">Automations</div> + <input class="auto-input" type="text" id="recvInput" placeholder="Recv"> + <input class="auto-input" type="text" id="sendInput" placeholder="Send"> + <button id="storeButton" onclick="storeValues()">Store</button> + <table id="valueTable"> + <thead> + <tr> + <th>Recv</th> + <th>Send</th> + <th style="width: 20px;"></th> + </tr> + </thead> + <tbody id="valueTableBody"></tbody> + </table> + </div> + + <div id="cswsh-output" ></div> + + </div> + + <div class="sendBar" style="display:none"> + <form name="wssCommand" id="wssCommand" action="" onsubmit="return false"> + <label id="label">$></label> + <input type="text" name="wssSendText" id="wssSendText" value="" placeholder=""> + <!--<input type="submit" id="wssSendbutton" value="" />--> + </form> + </div> + +<div class="bottomBar"> + <div class="bottomBy">By <a href="https://rossmarks.uk" target="_new">Ross Marks</a></div> + <div class="bottomText"><a href="/inject.php?payload=test" target="_new">/inject.php?payload=[inject here]</a></div> + <div class="bottomClear"> + <input type="button" id="clearPage" value="clear page" onclick="clearPage();"/> + </div> +</div> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> + <script src="/script.js"></script> +</body> +</html> diff --git a/WSSSnoop.png b/WSSSnoop.png new file mode 100755 index 0000000..fb18c44 --- /dev/null +++ b/WSSSnoop.png Binary files differ diff --git a/data_recv b/data_recv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_recv diff --git a/data_send b/data_send new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data_send diff --git a/inject.php b/inject.php new file mode 100644 index 0000000..710e437 --- /dev/null +++ b/inject.php @@ -0,0 +1,60 @@ +<?php +// Set the file path +$dataSendFilePath = 'data_send'; +$dataRecvFilePath = 'data_recv'; + +// Check if the payload parameter is set +if (isset($_REQUEST['response'])) { + $response = $_REQUEST['response']; + file_put_contents($dataRecvFilePath, $response); + file_put_contents($dataSendFilePath, ''); + die(); +} + +// Check if the "payload" parameter exists in the request +if (isset($_REQUEST['payload'])) { + // Get the payload value + $payload = $_REQUEST['payload']; + + // Acquire an exclusive lock on the "data_send" file + $sendFile = fopen('data_send', 'w'); + if (flock($sendFile, LOCK_EX)) { + // Write the payload to the "data_send" file + fwrite($sendFile, $payload); + + // Release the lock and close the file + flock($sendFile, LOCK_UN); + fclose($sendFile); + } else { + // Failed to acquire the lock + die('Failed to write payload to data_send file.'); + } +} + +// Check if the "data_recv" file contains data +while (true) { + $dataRecv = file_get_contents('data_recv'); + + // Check if the file contains data + if (!empty($dataRecv)) { + // Display the data + echo $dataRecv; + + file_put_contents($dataRecvFilePath, ''); + file_put_contents($dataSendFilePath, ''); + // Exit the loop + break; + } + + // Wait for a second before checking again + sleep(1); +} + + + + + + + + +?> \ No newline at end of file diff --git a/proxy-to-php-server.sh b/proxy-to-php-server.sh new file mode 100755 index 0000000..0b1ff6d --- /dev/null +++ b/proxy-to-php-server.sh @@ -0,0 +1,25 @@ +#!/bin/bash -x + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 + +# get a random port -- this could be improved +port=$(shuf -i 2048-65000 -n 1) + +# start the PHP server in the background +if [[ -d "$(realpath ${1:?Missing path to serve})" ]]; then + php -S localhost:"${port}" -t "$(realpath ${1:?Missing path to serve})" & +else + php -S localhost:"${port}" "$(realpath ${1:?Missing path to serve})" & +fi +pid=$! + +# try to adjust delay to improve performances +sleep 0.2 + +# proxy standard in to nc on that port +nc localhost "${port}" + +# kill the server we started +kill "${pid}" diff --git a/script.js b/script.js new file mode 100644 index 0000000..d5a04cc --- /dev/null +++ b/script.js @@ -0,0 +1,238 @@ + var dataSendUsed = false; + var checkSend = false; + + function clearPage(){ + $('#cswsh-output').empty(); + $('html, body').scrollTop($(document).height()); + } + + function startSnooping(){ + $('#startSnoop').hide(); + $('#stopSnoop').show(); + $('.sendBar').show(); + $('#wssSendText').focus(); + writeToScreen("Start snooping: " + $("#cswshURL").val()); + checkCSWSH(); + checkSend = true; + checkDataSend(); + } + + function stopSnooping(){ + $('#startSnoop').show(); + $('#stopSnoop').hide(); + $('.sendBar').hide(); + websocket.close(); + checkSend = false + writeToScreen("Stop snooping"); + } + + function checkCSWSH(){ + var wsUri = $("#cswshURL").val(); + + statusWaiting(); + websocket = new WebSocket(wsUri); + websocket.onopen = function(evt) { onOpen(evt) }; + websocket.onclose = function(evt) { onClose(evt) }; + websocket.onmessage = function(evt) { onMessage(evt) }; + websocket.onerror = function(evt) { onError(evt) }; + } + + function onOpen(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"CONNECTED"); + statusConnected() + //doSend("origin policy unchecked!"); + } + + function onClose(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"DISCONNECTED"); + statusOffline() + if( $('#stopSnoop').css('display') != 'none' ){ + checkCSWSH() + } + } + + function onMessage(evt) { + var encodedData = encodeToHtmlEntities(evt.data); + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #A7E734;">RECV:</span><span> ' + encodedData + '</span>'); + + var recvValue = encodedData.trim(); + if (dataSendUsed) { + sendToInjectPHP(recvValue); + } + var sendValue = getSendValueForRecv(recvValue); + if (sendValue) { + doSendAuto(sendValue); + } + } + + // Function to get the corresponding "send" value for a "recv" value + function getSendValueForRecv(recvValue) { + var valueTable = document.getElementById("valueTable"); + var rows = valueTable.getElementsByTagName("tr"); + for (var i = 0; i < rows.length; i++) { + var cells = rows[i].getElementsByTagName("td"); + if (cells.length === 3 && cells[0].innerText.trim() === recvValue) { + return cells[1].innerText.trim(); + } + } + return null; + } + + function onError(evt){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: red;">ERROR:</span> ' + encodeToHtmlEntities(evt.data)); + } + + function doSend(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+"SENT: " + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendAuto(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #bd34e7;">AUTO:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + function doSendPayload(message){ + writeToScreen('<span class="timestamp">'+getTimestamp()+'</span> '+'<span style="color: #e734bd;">INJT:</span><span> ' + encodeToHtmlEntities(message)); + websocket.send(message); + } + + var sentData = null; +function checkDataSend() { + if(checkSend == true){ + $.ajax({ + url: "/data_send", + method: "GET", + dataType: "text", + async:false, + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (data) { + if (data && data !== sentData) { + console.log(data); + doSendPayload(data); + sentData = data; + dataSendUsed = true; // Set the variable to true if data_send is used + //sendToInjectPHP(recvValue); // Call sendToInjectPHP unconditionally + } + } + }); + + // Check again after a delay + setTimeout(checkDataSend, 2000); + } + return false; +} + +function sendToInjectPHP(data) { + if (dataSendUsed) { + dataSendUsed = false; + var url = "/inject.php?response=" + encodeURIComponent(data); + + $.ajax({ + url: url, + method: "GET", + dataType: "text", + contentType: "text", + beforeSend: function( xhr ) { + xhr.overrideMimeType( "text/plain; charset=x-user-defined" ); + }, + success: function (response) { + // Handle success if necessary + } + + }); + } +} + + + + function writeToScreen(message){ + output = document.getElementById("cswsh-output"); + var pre = document.createElement("div"); + pre.style.wordWrap = "break-word"; + pre.innerHTML = message; + output.appendChild(pre); + $('html, body').scrollTop($(document).height()); + } + + $("#wssCommand").submit(function(e) { + doSend( $('#wssSendText').val() ); + $('#wssSendText').val(""); + $('#wssSendText').focus(); + e.preventDefault(); + }); + + function statusConnected(){ + $('#status').html("Connected"); + $('#status').css("color","lightgreen"); + } + function statusOffline(){ + $('#status').html("Offline"); + $('#status').css("color","red"); + } + function statusWaiting(){ + $('#status').html("Waiting..."); + $('#status').css("color","yellow"); + } + + // Function to store recv and send values + function storeValues() { + var recvValue = document.getElementById("recvInput").value; + var sendValue = document.getElementById("sendInput").value; + + if (recvValue && sendValue) { + var newRow = document.createElement("tr"); + newRow.innerHTML = + "<td>" + + recvValue + + "</td><td>" + + sendValue + + '</td><td><a class="removeButton" onclick="removeRow(this)">[x]</a></td>'; + document.getElementById("valueTableBody").appendChild(newRow); + + // Clear input fields + document.getElementById("recvInput").value = ""; + document.getElementById("sendInput").value = ""; + } + } + + // Function to remove a row from the table + function removeRow(button) { + var row = button.parentNode.parentNode; + row.parentNode.removeChild(row); + } + + function encodeToHtmlEntities(str) { + var encodedStr = ""; + for (var i = 0; i < str.length; i++) { + var charCode = str.charCodeAt(i); + if (charCode > 127 || /[&<>"'`]/.test(str[i])) { + encodedStr += "&#" + charCode + ";"; + } else { + encodedStr += str.charAt(i); + } + } + return encodedStr; + } + + function getTimestamp() { + var now = new Date(); + var day = now.getDate(); + var month = now.getMonth() + 1; // Adding 1 because months are zero-based + var hours = now.getHours(); + var minutes = now.getMinutes(); + + // Pad single digits with leading zeros + day = day < 10 ? '0' + day : day; + month = month < 10 ? '0' + month : month; + hours = hours < 10 ? '0' + hours : hours; + minutes = minutes < 10 ? '0' + minutes : minutes; + + var timestamp = '[' + day + '/' + month + ' ' + hours + ':' + minutes + ']'; + return timestamp; + } + + //setTimeout(checkDataSend(), 1000); \ No newline at end of file diff --git a/simple-php-webserver.sh b/simple-php-webserver.sh new file mode 100755 index 0000000..b9c0ad4 --- /dev/null +++ b/simple-php-webserver.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Taken from: https://gist.github.com/Jiab77/4d3c1abeb9be4119f33031750cf580d4 +# Increasing local web server performances as possible +# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758 +# https://www.php.net/manual/en/features.commandline.webserver.php + +# Config +LISTEN_INTERFACE="127.0.0.1" +LISTEN_PORT=8082 +ENTRY_POINT=$1 + +# Detect server type to use +PHP_SRV_TYPE=$(php -r "if (version_compare(phpversion(), '7.4', '<')) { echo 'tcpserver'; } else { echo 'embedded'; }") + +# Run detected server type +if [[ $PHP_SRV_TYPE == 'embedded' ]]; then + if [[ -d $ENTRY_POINT ]]; then + PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} -t $ENTRY_POINT + else + PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} $ENTRY_POINT + fi +else + tcpserver -v -1 0 ${LISTEN_PORT} ./proxy-to-php-server.sh $ENTRY_POINT +fi diff --git a/style.css b/style.css new file mode 100644 index 0000000..4c312f6 --- /dev/null +++ b/style.css @@ -0,0 +1,160 @@ + body{ + background-color: #333; + color:#bbb; + margin:0; + + } + .topBar { + background-color: #444; + position:fixed; + top:0; + width:100%; + z-index:100; + padding: 10px; + } + .topTitle{ + position:absolute; + top:10px; + left:10px; + color:#7fffd4; + } + .topcorner{ + position:absolute; + top:10px; + right:30px; + } + #cswsh-output{ + margin-top: 50px !important; + font-family: 'Source Code Pro', + sans-serif;font-size: 0.7em; + padding-bottom: 65px; + padding-left: 10px; + z-index: 80; + } + .sendBar { + background-color: #333; + position:fixed; + bottom:30px; + width:80%; + z-index:100; + padding: 0px; + height: 30px; + font-family: 'Source Code Pro', sans-serif; + z-index: 80; + } + .sendBar #label { + margin-right: 20px; + width: 110px; + } + /*.sendBar #wssCommand { + width: 100%; + }*/ + .sendBar #wssSendText { + display: flex; + width:100%; + flex-grow: 1; + margin-left: -20px; + margin-top: -20px; + padding-left: 45px; + background-color: #333; + color:#DDD; + font-family: 'Source Code Pro', sans-serif; + border:none; + text-decoration: none; + } + *:focus { + outline: none; + } + .sidebar { + position: fixed; + float: right; + top: -5px; + right: 0; + width: 20%; + height: 100%; + background-color: #555; + margin-top: 45px; + margin-left: 5px; + padding-left: 5px; + padding-top: 5px; + text-align: center; + z-index: 99; + } + .auto-header{ + font-family: 'Source Code Pro', sans-serif; + font-weight: 900; + } + .auto-input{ + font-family: 'Source Code Pro', sans-serif; + width: 95%; + } + .sidebar #valueTable{ + width:100%; + font-family: 'Source Code Pro', sans-serif; + } + .sidebar #valueTableBody{ + font-size: 0.9em; + } + .sidebar #valueTableBody tr{ + margin-bottom:5px; + } + .container { + display: flex; + height: calc(100vh - 30px); /* Adjust the height as needed */ + overflow: auto; + } +.bottomBar { + background-color: #444; + position: fixed; + bottom: 0; + width: 100%; + z-index: 100; + padding: 10px; + height: 20px; /* Increased height to accommodate the text */ + display: flex; + align-items: center; +} + +.bottomBy { + color: #00ccff; + +} + +.bottomBy a:link, +.bottomBy a:visited { + color: #00ccff; + text-decoration: none; +} + +.bottomBy a:hover, +.bottomBy a:active { + color: #99ebff; + text-decoration: none; +} + +.bottomText { + color: #00ccff; + font-family: 'Source Code Pro', sans-serif; + font-size: 0.7em; + margin-left: auto; + margin-right: auto; +} + +.bottomClear { + position: absolute; + bottom: 10px; + right: 30px; +} + +a:link, +a:visited { + color: #00ccff; + text-decoration: none; +} + +/* mouse over link */ +a:hover, +a:active { + color: #99ebff; + text-decoration: none; +} \ No newline at end of file