I'm pretty new to Python but need to patch this glitch/exploit in an addon service.
My code looks like this:
#!/usr/bin/env python
import subprocess
import sys
import os
import yaml
from xml.dom import minidom
sys.path.append('/scripts')
import createvhosts
doc = minidom.parse(sys.stdin)
param0taglist = doc.getElementsByTagName('param0')
param1taglist = doc.getElementsByTagName('param1')
param0 = param0taglist[0].childNodes[0].toxml()
param1 = param1taglist[0].childNodes[0].toxml()
domain = param0 + '.' + param1
usertaglist = doc.getElementsByTagName('USER')
user = usertaglist[0].childNodes[0].toxml()
f = open('/var/cpanel/userdata/' + user + '/main')
ydata = yaml.load(f)
f.close()
sublist = ydata['sub_domains']
addondict = ydata['addon_domains']
parkedlist = ydata['parked_domains']
mainlist = ydata['main_domain']
serverip = createvhosts.getmainip()
if len(sublist) != 0:
slcont = 0
while slcont < len(sublist):
domain = sublist[slcont]
docroot, yip, alias = createvhosts.getvars(sublist[slcont])
if yip == serverip:
createvhosts.writeconfshared(user, domain, docroot, yip, alias)
else:
createvhosts.writeconfded(user, domain, docroot, yip, alias)
slcont = slcont + 1
proc = subprocess.Popen("/etc/init.d/nginx restart > /dev/null 2>&1", shell=True)
The issue is when you add a subdomain in CPanel with * it will crash the server because apparently nginx does not seem to allow and accept that. What I need help doing is figuring out how to replace/block * so it does not go in.
Does something like Param0.find( "*" ) !=-1 work?
The construct you're looking for is char in string.
>>> s = 'ab*de'
>>> '*' in s
True
Put this in a conditional and you've got what you want - something like:
if '*' in param0:
raise ValueError("Can't use '*'!")
This, along with a comprehensive list of the methods available on strings to do more involved work, is documented in the official docs, under Built-in Types.
Related
I am working with the following script from https://github.com/Isaacdelly/Plutus/blob/master/plutus.py
The script works for wallet addresses in the 2^160 range. I am curious where in the script I can change this to look at the 2^128 range or 2^n range. Would it be possible to even have a window? Like 2^0 - 2^100?
Not trying to do anything malicious, just trying to get data to show that even selecting ranges is futile due to the large number of addresses.
# Plutus Bitcoin Brute Forcer
# Made by Isaac Delly
# https://github.com/Isaacdelly/Plutus
try:
import sys
import os
import time
import hashlib
import binascii
import multiprocessing
from multiprocessing import Process, Queue
from multiprocessing.pool import ThreadPool
import threading
import base58
import ecdsa
import requests
except ImportError:
import subprocess
subprocess.check_call(["python", '-m', 'pip', 'install', 'base58==1.0.0'])
subprocess.check_call(["python", '-m', 'pip', 'install', 'ecdsa==0.13'])
subprocess.check_call(["python", '-m', 'pip', 'install', 'requests==2.19.1'])
import base58
import ecdsa
import requests
def generate_private_key():
return binascii.hexlify(os.urandom(32)).decode('utf-8')
def private_key_to_WIF(private_key):
var80 = "80" + str(private_key)
var = hashlib.sha256(binascii.unhexlify(hashlib.sha256(binascii.unhexlify(var80)).hexdigest())).hexdigest()
return str(base58.b58encode(binascii.unhexlify(str(var80) + str(var[0:8]))), 'utf-8')
def private_key_to_public_key(private_key):
sign = ecdsa.SigningKey.from_string(binascii.unhexlify(private_key), curve = ecdsa.SECP256k1)
return ('04' + binascii.hexlify(sign.verifying_key.to_string()).decode('utf-8'))
def public_key_to_address(public_key):
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
count = 0; val = 0
var = hashlib.new('ripemd160')
var.update(hashlib.sha256(binascii.unhexlify(public_key.encode())).digest())
doublehash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(('00' + var.hexdigest()).encode())).digest()).hexdigest()
address = '00' + var.hexdigest() + doublehash[0:8]
for char in address:
if (char != '0'):
break
count += 1
count = count // 2
n = int(address, 16)
output = []
while (n > 0):
n, remainder = divmod (n, 58)
output.append(alphabet[remainder])
while (val < count):
output.append(alphabet[0])
val += 1
return ''.join(output[::-1])
def get_balance(address):
try:
response = requests.get("https://bitaps.com/api/address/" + str(address))
return int(response.json()['balance'])
except:
return -1
def data_export(queue):
while True:
private_key = generate_private_key()
public_key = private_key_to_public_key(private_key)
address = public_key_to_address(public_key)
data = (private_key, address)
queue.put(data, block = False)
def worker(queue):
while True:
if not queue.empty():
data = queue.get(block = True)
balance = get_balance(data[1])
process(data, balance)
def process(data, balance):
private_key = data[0]
address = data[1]
if (balance == 0):
print("{:<34}".format(str(address)) + ": " + str(balance))
if (balance > 0):
file = open("plutus.txt","a")
file.write("address: " + str(address) + "\n" +
"private key: " + str(private_key) + "\n" +
"WIF private key: " + str(private_key_to_WIF(private_key)) + "\n" +
"public key: " + str(private_key_to_public_key(private_key)).upper() + "\n" +
"balance: " + str(balance) + "\n\n")
file.close()
def thread(iterator):
processes = []
data = Queue()
data_factory = Process(target = data_export, args = (data,))
data_factory.daemon = True
processes.append(data_factory)
data_factory.start()
work = Process(target = worker, args = (data,))
work.daemon = True
processes.append(work)
work.start()
data_factory.join()
if __name__ == '__main__':
try:
pool = ThreadPool(processes = multiprocessing.cpu_count()*2)
pool.map(thread, range(0, 10))
except:
pool.close()
exit()
Thank you
You seem to be misunderstanding the purpose of the 2^160 bit range.
Each standard bitcoin address is tied to the HASH160 of the public key. A HASH160 is 160 bits long, which is why your search space is 2^160. If you are able to find two private keys for which the HASH160 of the public keys are equal, any of those two private keys can spend coins sent to that address.
Searching a smaller space does not make sense since you are no longer searching for bitcoin addresses. If you just want to search random hash functions, then you simply need to replace RIPEMD160 hash function with another one that has an output in whatever bitsize you wish to search.
Note that if you do that, the rest of the code talking about checking balances etc. will be of no use, since your output will no longer be a bitcoin address.
How i can get fat32 attributes (like archived, hidden...) in linux without spawning a new process with fatattr utility call ? May be there is python binding for it or for linux/fs functions (fat_ioctl_get_attributes, http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/fs/fat/file.c). Or maybe it can be done with python-xattr ?
As you can see in the function name, the kernel function fat_ioctl_get_attributes is called from userspace via an ioctl, and I'm not aware of any other binding. Therefore, you can simply read the attributes by calling ioctl yourself, like this:
import array
import fcntl
import os
FAT_IOCTL_GET_ATTRIBUTES = 0x80047210
FATATTR_BITS = 'rhsvda67'
def get_fat_attrs(fn):
fd = os.open(fn, os.O_RDONLY)
try:
buf = array.array('L', [0])
try:
fcntl.ioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, buf, True)
except IOError as ioe:
if ioe.errno == 25: # Not a FAT volume
return None
else:
raise
return buf[0]
finally:
os.close(fd)
if __name__ == '__main__':
import sys
for fn in sys.argv[1:]:
attrv = get_fat_attrs(fn)
if attrv is None:
print(fn + ': Not on a FAT volume')
continue
s = ''.join((fb if (1 << idx) & attrv else ' ')
for idx,fb in enumerate(FATATTR_BITS))
print(fn + ': ' + s)
I am writing a Python script to do some admin functionality which involves running several other python scripts.
A snipet of my code looks like this:
import subprocess
PYTHON_BIN_DIR = '/usr/bin/python'
SCRIPTS_DIR = '/some/path'
if __name__ == "__main__":
dateparam = "05-Jan-2012"
command = [PYTHON_BIN_DIR]
command.extend(SCRIPTS_DIR + "/myfile1.py")
strparams = " --param1={0} ".format(123)
command.extend(strparams)
command.extend(dateparam)
retcode = subprocess.call(command)
if retcode != 0:
# do something
pass
else:
# do something else
pass
All the scripts I'm calling are using the if __name__ == ""__main__"" check/test. So what's causing the error?
As pointed out in comments you should use append instead of extend. I think your other problem is you've included spaces in your argument. I would split up each parameter, i.e. --param1=123:
import subprocess
import os.path
PYTHON_BIN_DIR = '/usr/bin/python'
SCRIPTS_DIR = '/some/path'
if __name__ == "__main__":
dateparam = "05-Jan-2012"
command = [PYTHON_BIN_DIR, os.path.join(SCRIPTS_DIR, 'myfile1.py'),
'--param1', 123, '--date', dateparam]
retcode = subprocess.call(command)
if retcode != 0:
# do something
pass
else:
# do something else
pass
I want to get stdout and stderr of a command along with the return code.
Can someone point me to a python function that already accomplishes this?
I modified a function that I found on this site as follows -- but I am not able to grab the return code of the command. In this snippet, sts always seems to be 0.
def Getstatusoutput(cmd):
"""Return (status, output) of executing cmd in a shell."""
import sys
mswindows = (sys.platform == "win32")
import os
if not mswindows:
cmd = '{ ' + cmd + '; }'
fi,fo,fe=os.popen3(cmd)
textOut = fo.read()
textErr = fe.read()
sts = fo.close()
if sts is None: sts = 0
if textOut[-1:] == '\n': textOut = textOut[:-1]
return sts, textOut, textErr
Use the subprocess module. This section shows how to replace os.popen3 calls.
i made simple web server like below.
import BaseHTTPServer, os, cgi
import cgitb; cgitb.enable()
html = """
<html>
<body>
<form action="" method="POST" enctype="multipart/form-data">
File upload: <input type="file" name="upfile">
<input type="submit" value="upload">
</form>
</body>
</html>
"""
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("content-type", "text/html;charset=utf-8")
self.end_headers()
self.wfile.write(html)
def do_POST(self):
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
query = cgi.parse_multipart(self.rfile, pdict)
upfilecontent = query.get('upfile')
if upfilecontent:
# i don't know how to get the file name.. so i named it 'tmp.dat'
fout = file(os.path.join('tmp', 'tmp.dat'), 'wb')
fout.write (upfilecontent[0])
fout.close()
self.do_GET()
if __name__ == '__main__':
server = BaseHTTPServer.HTTPServer(("127.0.0.1", 8080), Handler)
print('web server on 8080..')
server.serve_forever()
In the do_Post method of BaseHTTPRequestHandler, i got the uploaded file data successfully.
But i can't figure out how to get the original name of the uploaded file.
self.rfile.name is just a 'socket'
How can i get the uploaded file name?
Pretty broken code you're using there as a starting point (e.g. look at that global rootnode where name rootnode is used nowhere -- clearly half-edited source, and badly at that).
Anyway, what form are you using "client-side" for the POST? How does it set that upfile field?
Why aren't you using the normal FieldStorage approach, as documented in Python's docs? That way, you could use the .file attribute of the appropriate field to get a file-like object to read, or its .value attribute to read it all in memory and get it as a string, plus the .filename attribute of the field to know the uploaded file's name. More detailed, though concise, docs on FieldStorage, are here.
Edit: now that the OP has edited the Q to clarify, I see the problem: BaseHTTPServer does not set the environment according to the CGI specs, so the cgi module isn't very usable with it. Unfortunately the only simple approach to environment setting is to steal and hack a big piece of code from CGIHTTPServer.py (wasn't intented for reuse, whence the need for, sigh, copy and paste coding), e.g....:
def populenv(self):
path = self.path
dir, rest = '.', 'ciao'
# find an explicit query string, if present.
i = rest.rfind('?')
if i >= 0:
rest, query = rest[:i], rest[i+1:]
else:
query = ''
# dissect the part after the directory name into a script name &
# a possible additional path, to be stored in PATH_INFO.
i = rest.find('/')
if i >= 0:
script, rest = rest[:i], rest[i:]
else:
script, rest = rest, ''
# Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html
# XXX Much of the following could be prepared ahead of time!
env = {}
env['SERVER_SOFTWARE'] = self.version_string()
env['SERVER_NAME'] = self.server.server_name
env['GATEWAY_INTERFACE'] = 'CGI/1.1'
env['SERVER_PROTOCOL'] = self.protocol_version
env['SERVER_PORT'] = str(self.server.server_port)
env['REQUEST_METHOD'] = self.command
uqrest = urllib.unquote(rest)
env['PATH_INFO'] = uqrest
env['SCRIPT_NAME'] = 'ciao'
if query:
env['QUERY_STRING'] = query
host = self.address_string()
if host != self.client_address[0]:
env['REMOTE_HOST'] = host
env['REMOTE_ADDR'] = self.client_address[0]
authorization = self.headers.getheader("authorization")
if authorization:
authorization = authorization.split()
if len(authorization) == 2:
import base64, binascii
env['AUTH_TYPE'] = authorization[0]
if authorization[0].lower() == "basic":
try:
authorization = base64.decodestring(authorization[1])
except binascii.Error:
pass
else:
authorization = authorization.split(':')
if len(authorization) == 2:
env['REMOTE_USER'] = authorization[0]
# XXX REMOTE_IDENT
if self.headers.typeheader is None:
env['CONTENT_TYPE'] = self.headers.type
else:
env['CONTENT_TYPE'] = self.headers.typeheader
length = self.headers.getheader('content-length')
if length:
env['CONTENT_LENGTH'] = length
referer = self.headers.getheader('referer')
if referer:
env['HTTP_REFERER'] = referer
accept = []
for line in self.headers.getallmatchingheaders('accept'):
if line[:1] in "\t\n\r ":
accept.append(line.strip())
else:
accept = accept + line[7:].split(',')
env['HTTP_ACCEPT'] = ','.join(accept)
ua = self.headers.getheader('user-agent')
if ua:
env['HTTP_USER_AGENT'] = ua
co = filter(None, self.headers.getheaders('cookie'))
if co:
env['HTTP_COOKIE'] = ', '.join(co)
# XXX Other HTTP_* headers
# Since we're setting the env in the parent, provide empty
# values to override previously set values
for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH',
'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'):
env.setdefault(k, "")
os.environ.update(env)
This could be substantially simplified further, but not without spending some time and energy on that task:-(.
With this populenv function at hand, we can recode:
def do_POST(self):
populen(self)
form = cgi.FieldStorage(fp=self.rfile)
upfilecontent = form['upfile'].value
if upfilecontent:
fout = open(os.path.join('tmp', form['upfile'].filename), 'wb')
fout.write(upfilecontent)
fout.close()
self.do_GET()
...and live happily ever after;-). (Of course, using any decent WSGI server, or even the demo one, would be much easier, but this exercise is instructive about CGI and its internals;-).
By using cgi.FieldStorage you can easily extract the filename. Check the example below:
def do_POST(self):
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], })
filename = form['upfile'].filename
data = form['upfile'].file.read()
open("./%s"%filename, "wb").write(data)
self.do_GET()
...or use your own version of cgi.parse_multipart, especially fixing this:
# my fix: prefer 'filename' over 'name' field!
if 'filename' in params:
name = params['filename']
name = os.path.basename(name) # Edge, IE return abs path!
elif 'name' in params:
name = params['name']
else:
continue