抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

安全宝在情人节前出了一个网络安全闯关游戏,题目还是比较简单的。

Q1、世界上先有男人还是先有女人?

答案是“男人”。

Q2、世界上为什么先有男人?

答案是“先生”。

Q3、请从本页面找到密码并输入。

查看网页源码,可以看到一段源码:

1
2
3
4
5
6
7
8
9
<div class="page page-3 invisible">
<div class="dp c dp-4-1"></div>
<div class="password-form dp c">
<input type="text" class="text" name="" value="" id="password1"/>
<a href="javascript:;" class="form-button h" onclick="checkPassword(this)"></a>
</div>

<div class="dp c dp-logo"></div>
</div>

可见,输入密码后点击按钮会调用checkPassword函数,在源码里可以看到网页引用了一个index.js文件:

1
<script src="js/index.js" type="text/javascript"></script>

访问该文件,里面有一段被混淆的js代码:

1
(function(b,a,c,d){b.showPage=function(e){c(".page").filter(".page-"+e).show().siblings().hide()};b.checkPassword=function(f){var e=c(f).prev().val();if(e=="wo ai anquanbao"){showPage(4)}else{c(f).prev().val("").focus()}}})(window,document,window.jQuery);

格式化一下js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
(function(b, a, c, d) {
b.showPage = function(e) {
c(".page").filter(".page-" + e).show().siblings().hide()
};
b.checkPassword = function(f) {
var e = c(f).prev().val();
if (e == "wo ai anquanbao") {
showPage(4)
} else {
c(f).prev().val("").focus()
}
}
})(window, document, window.jQuery);

可见,checkPassword函数会判断输入的密码是否为"wo ai anquanbao",是的话就调用showPage(4)函数显示第4个问题。

Q4、在这里我用.htaccess限制了访问所有图片,来找找约会地点吧。

This is a picture without description

图片里提示了"yuehui.png",访问http://yuebaomei.com/yuehui.png,发现访问不了。
查看网络请求,发现页面访问了一个地址http://yuebaomei.com/show.php?p=dGlzaGkucG5n,打开是上面那张图片。
所以show.php就是用来显示图片的脚本,参数p的值"dGlzaGkucG5n"看起来像base64编码,解码结果为"tishi.png"

也就是说,参数p的值是图片名的base64编码,那么"yuehui.png"的base64编码为"eXVlaHVpLnBuZw=="
访问http://yuebaomei.com/show.php?p=eXVlaHVpLnBuZw==,成功得到了约会地点:
This is a picture without description

要拿终极大奖的话可以继续答题。

Q5、在这里宝妹有三个问题,任选其一做对就有终极大奖哦。

This is a picture without description

  • A、我没安卓手机,不好调试。
  • B、我对SQL注入不太熟悉。
  • C、所以只能选择PHP了。

选择PHP代码审计,可以看到一段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
<?php
$flag = "THIS IS FLAG";

if ("POST" == $_SERVER['REQUEST_METHOD'])
{
$password = $_POST['password'];

if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
{
echo 'Wrong Format';
exit;
}

while (TRUE)
{
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;

$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;

if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
?>

Google一下,可以找到正则表达式里一些单词代表的含义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[:graph:]     #打印字符,不包括空格
[:punct:] #打印字符,匹配任何标点符号
[:digit:] #匹配任何数字
[:upper:] #匹配任何大写字母
[:lower:] #匹配任何小写字母
[:alnum:] #字母和数字
[:alpha:] #字母
[:ascii:] #0-127的ascii字符
[:blank:] #空格和制表符
[:cntrl:] #控制字符
[:print:] #打印字符,包括空格
[:space:] #空白字符(比/s多个垂直指标)
[:word:] #单词字符(/w)
[:xdigit:] #匹配任何16进制数字

从代码可以看出password必须符合以下条件:

1
2
3
4
5
6
7
8
9
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
{
echo 'Wrong Format';
exit;
}

/*
分析:密码可以包含字母数字和字符,长度必须大于等于12位。
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$reg = '/([[:punct:]]+[[:digit:]]+[[:upper:]]+[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;

/*
分析:密码必须被字符,数字,大写字母,小写字母分割成至少6部分。
比如字符串"http://www.poboke.com"会被分割为7部分:
Array
(
[0] => http
[1] => ://
[2] => www
[3] => .
[4] => poboke
[5] => .
[6] => com
)
*/
1
2
3
4
5
6
7
8
9
10
11
12
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;

/*
分析:密码至少包含字符,数字,大写字母,小写字母中的3个。
*/
1
2
3
4
5
6
if ("42" == $password) echo $flag;
else echo 'Wrong password';

/*
分析:密码必须等于"42",才能输出flag。
*/

既然密码必须等于"42",那么就和上面密码长度必须大于等于12位矛盾了,所以密码应该是在和"42"做比较的时候被转成了数字。
一个字符串,包含了数字、标点、字母,而且会被转成数字,很容易就想到了科学计数法。
比如"0.42E+2"表示0.42 * 10^2 = 42。
"0.42E+2"刚好被各种字符分割成6部分,但是长度小于12,只需要补0就行了。
所以密码为"0.4200000E+2"

输入后成功通关了:
This is a picture without description

暂时还不知道奖品是什么,期待中……

评论