PHP代码审计18—PHP代码审计小结
文章目录
- 一、前期准备
- 1、工具准备
- 2、审计环境准备
- 二、了解系统架构
- 1、使用了开发框架
- 1) ThinkPHP框架
- 2) laravel框架
- 2、没使用开发框架
- 三、参数过滤分析
- 1、MVC模式下的过滤情况分析
- 2、原生PHP模式下的过滤分析
- 四、常见漏洞审计方法总结
- 1、SQL注入
- 2、XSS漏洞
- 3、代码执行
- 4、文件上传、删除、下载
- 1) 文件上传漏洞
- 2)文件删除漏洞
- 3)文件下载漏洞
- 5、XXE漏洞
- 6、SSRF漏洞
- 五、相关审计技巧总结
- 1、钻GPC的空子
- 2、利用字符处理问题
- 1)利用字符处理函数报错
- 2)利用字符串截断
- 3、不严谨的正则表达式
- 五、参考资料
前言:经过一段时间的代码审计学习,在这里对代码审计这方面的知识做一个简单的小结,一部分是个人的的知识总结,为了能更全面的总结到代码审计的方法结论,所以也参考了很多的资料,都写在了文末。
一、前期准备
1、工具准备
这里总结我用到过的或者说我了解的比较好的一些工具。
PHP代码调试工具
- PHPstorm+xdebug
代码阅读工具
- notePad++
- cublimeTxt 3
静态代码审计工具
Fortify
HP出的一款静态代码审计工具,支持21种开发语言,是一款功能强大的商业代码审计工具。
Seay
Seay大佬协议的代码审计工具,国产、开源。
CodeQl
Githubt推出的代码审计项目,在国外受到众多安全研究着追捧。
Xcheck
Xcheck的php引擎支持原生php的安全检查,也支持对国内主流框架编写的web应用进行安全检查,覆盖包括Thinkphp,Laravel,CodeIgniter,Yii,Yaf等web框架。
RIPS
轻量级的代码审计工具,来源于国外专业的代码审计公司RIPS。但是RIPS的开源版本已经多年未更新,并且不支持面向对象的代码审计。
浏览器与插件
- 浏览器:FireFox
- 浏览器插件:HackBar、FoxyProxy、EditThisCookie
数据库管理软件
- Phpmyadmin
- Navicat
2、审计环境准备
操作系统
一般采用Windows系统进行审计,对于大多数审计工具来说,Windows系统下图形化界面在使用的时候会更加方便。
PHP集成环境
- phpStudy
- 宝塔面板
PHP版本
对于PHP版本的选择,为了使用实际使用环境,应该尽量使用php5.4以后的版本
数据库
对于数据库,对于PHP程序来说,一般都是采用的Mysql,在审计过程中,最好将mysql设置为5.7版本以后。
二、了解系统架构
对于系统架构,我们在确认了审计目标之后,在审计之前,需要先了解目标系统的基本架构,比如目录情况如何、是否使用了框架、存在那些路由、有没有安全过滤函数、有没有全局参数过滤等等。这里就要分为有框架和无框架来进行分析。
1、使用了开发框架
1) ThinkPHP框架
这里一ThinkPHP5为例,框架的大体目录结构如下:
www WEB部署目录(或者子目录)
├─application 应用目录
│ ├─common 公共模块目录(可以更改)
│ ├─module_name 模块目录
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ │
│ ├─command.php 命令行工具配置文件
│ ├─common.php 公共函数文件
│ ├─config.php 公共配置文件
│ ├─route.php 路由配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─database.php 数据库配置文件
│
├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
│
├─thinkphp 框架系统目录
│ ├─lang 语言文件目录
│ ├─library 框架类库目录
│ │ ├─think Think类库包目录
│ │ └─traits 系统Trait目录
│ │
│ ├─tpl 系统模板目录
│ ├─base.php 基础定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 框架惯例配置文件
│ ├─helper.php 助手函数文件
│ ├─phpunit.xml phpunit配置文件
│ └─start.php 框架入口文件
│
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor 第三方类库目录(Composer依赖库)
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
其中,applicatinon目录和我们的Public目录,使我们的应用程序文件目录和运行数据存放目录,属于重要关注对象。
同时application目录下的config.php、database.php、route.php分别是系统配置文件、数据库操作文件、系统路由文件,都需要仔细分析。
对于ThinkPHP框架开发的应用,其访问系统的URL通常是这样的:/index.php/模块名/控制器名/函数名/[参数名/参数值]
其中模块名对应了application目录下的文件夹的名字。控制器名对应了模块名目录下的controller文件夹下的php文件名。参数则是可选的,可以按照/参数名/参数值
的方式同时传入多个参数,也可以按照传统方式使用?参数1=参数值1&参数2=参数值2
的方式传入变量。
2) laravel框架
基本的目录结构:
|——app 包含了站点的controllers(控制器),models(模型),views(视图)和assets(资源|——bootstrap 存放系统启动时的必要文件,这些文件会被index.php这样的文件调用。|——public 系统运行的公开数据,包括静态资CSS文件、js文件等|——vender 第三方类库
与thinkPHP还是一样的,主要的应用程序文件都存放在了app目录下。
2、没使用开发框架
在没使用开发框架的情况下,我们就需要去判断应用程序是否采用了MVC模式,如果有的话,就需要去查看系统的路由文件,看看控制程序是如何通过路由定位的。比如PHPCMS,就是用了自己开发的MVC控制器来进行路由:
访问index.php,可以看到,包含了phpcms/base.php
define('PHPCMS_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR);include PHPCMS_PATH.'/phpcms/base.php';
进入base.php文件,就能看到,这里定义了特别多的路由以及初始化的一些类以及方法:
//PHPCMS框架路径
define('PC_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR);if(!defined('PHPCMS_PATH')) define('PHPCMS_PATH', PC_PATH.'..'.DIRECTORY_SEPARATOR);//缓存文件夹地址
define('CACHE_PATH', PHPCMS_PATH.'caches'.DIRECTORY_SEPARATOR);
//主机协议
define('SITE_PROTOCOL', isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://');
//当前访问的主机名
define('SITE_URL', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''));
//来源
define('HTTP_REFERER', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
//定义网站根路径
define('WEB_PATH',pc_base::load_config('system','web_path'));
//js 路径
define('JS_PATH',pc_base::load_config('system','js_path'));
//css 路径
define('CSS_PATH',pc_base::load_config('system','css_path'));
//img 路径
define('IMG_PATH',pc_base::load_config('system','img_path'));
//动态程序路径
define('APP_PATH',pc_base::load_config('system','app_path'));
//应用静态文件路径
define('PLUGIN_STATICS_PATH',WEB_PATH.'statics/plugin/');
class pc_base {......
}
对于没有使用框架,也没有使用自定义的MVC模型的程序,就只需要按照传统的脚本格式的访问方式就行,以index.php作为切入点,依次分析相关代码即可。
三、参数过滤分析
传统的参数过滤分析,通常会以函数的方式进行过滤,但是某些系统也可能会在参数传入后,进行全局参数过滤,所以我们在审计之前,就需要先了解应用程序采用了那些过滤方法,是否使用了全局参数过滤。
1、MVC模式下的过滤情况分析
首先以ThinkPHP来说,获取参数的方法有两种,一是通过原生的$_GET
等方式获取参数,二是通过$Request()对象获取参数。在审计thinkPHP程序的时候,就需要对这两种获取参数的方式进行审计。
在ThinkPHP中,会在config文件中定义一个默认的全局过滤器:
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
比如上面这样,默认的过滤器就为空。也就是说在使用$_GET
等原始方法获取参数的时候,就是不会进行过滤的。
然后我们再来看看$request对象获取参数的时候是如何进行的,比如erquest对象的get方法,是用于获取GET方式传入的参数的:
public function get($name = '', $default = null, $filter = ''){if (empty($this->get)) {$this->get = $_GET;}if (is_array($name)) {$this->param = [];return $this->get = array_merge($this->get, $name);}return $this->input($this->get, $name, $default, $filter);}
可以看到,这里定义了三个形参,分别是name、default、filter。其中name是我们要获取的变量名,而fileter则是我们要是用的过滤器,这里默认为空,也就是不进行任何过滤。
所以在进行审计的时候,我们就需要判断是否设置了默认的全局过滤选项,或者说是否在获取参数的时候,设置了新的过滤器。
2、原生PHP模式下的过滤分析
对于原生PHP开发的应用程序,往往是通过函数的方式来设置过滤规则,所以就需要在参数获取的地方来看看,是否调用了参数过滤函数来进行过滤,并判断是否是有效过滤。
这里以帝国CMS为例,进行一个简单的分析。帝国CMS的过滤函数在e/class/connect.php中,定义了三个参数处理函数,这里以其中一个为例,进行分析:
//参数处理函数
function RepPostVar($val){if($val!=addslashes($val)){exit();}CkPostStrChar($val);$val=str_replace("%","",$val);$val=str_replace(" ","",$val);$val=str_replace("`","",$val);$val=str_replace("\t","",$val);$val=str_replace("%20","",$val);$val=str_replace("%27","",$val);$val=str_replace("*","",$val);$val=str_replace("'","",$val);$val=str_replace("\"","",$val);$val=str_replace("/","",$val);$val=str_replace(";","",$val);$val=str_replace("#","",$val);$val=str_replace("--","",$val);$val=RepPostStr($val,1);$val=addslashes($val);//FireWallFWClearGetText($val);return $val;
}
可见,这里对%、空格、`、%20、%27、‘,“等进行了过滤。
然后我们就可以进入具体的文件中,看看传入的参数是否都调用了该函数进行过滤。
//审核评论
{$plid=$_POST['plid'];$id=$_POST['id'];$bclassid=$_POST['bclassid'];$classid=$_POST['classid'];CheckPl_all($plid,$id,$bclassid,$classid,$logininid,$loginin);
}function CheckPl_all($plid,$id,$bclassid,$classid,$userid,$username){global $empire,$class_r,$dbtbpre,$public_r;//验证权限$restb=(int)$_POST['restb'];$count=count($plid);if(empty($count)||!$restb){printerror("NotCheckPlid","history.go(-1)");}if(!strstr($public_r['pldatatbs'],','.$restb.',')){printerror("NotCheckPlid","history.go(-1)");}$add='';$docheck=(int)$_POST['docheck'];$docheck=$docheck?1:0;for($i=0;$i<$count;$i++){$add.="plid='".intval($plid[$i])."' or ";}$add=substr($add,0,strlen($add)-4);$sql=$empire->query("update {$dbtbpre}enewspl_{$restb} set checked='$docheck' where ".$add);if($sql){....}
}
比如这里,后台评论管理的地方,获取了评论给ID等参数,在未经过滤的情况下,传入了CheckPl_all()函数,可见这里的参数都没有调用了过滤函数进行处理,但是好在都对这些参数使用了int强制类型转换。还算是比较安全。
四、常见漏洞审计方法总结
1、SQL注入
首先需要了解SQL注入常见的业务场景与漏洞类型:
- 用户登录—万能密码
- 数据搜索—搜索型注入
- 获取HTTP头
- 商品购买—insert、update型注入等
- 信息查询—union联合注入、报错注入等
- …
可以说,任何与数据库进行交互的地方都可能存在SQL注入,对于其漏洞存场景也是多种多样,这里并不能很好的进行举例。
对于代码审计中的SQL注入审计方法,首先需要关注的就是数据库操作的关键字。
比如在PHP原生代码中,就可以多关注这些关键字:
select
mysqli_connect
mysqli_query
mysqli_fetch_row
mysqli_fetch_array
update
indert into
delete
.......
在一下CMS或者框架中,就需要多关注一下下面这些关键字或者方法:
name()
where()
find()
select()
.....
通过定位这些关键字,我们就能够定位到执行SQL语句的地方,然后去判断执行SQL语句中的参数是否采用了拼接SQL的方式,如果是则去判断是否存在参数过滤以及参数是否可控。
如果参数不可控,来源于某一条SQL语句查询出的结果,我们就需要重点关注这个参数是否来源于其他的用户输入,如果是,则需要考虑师傅存在二次注入的情况。
2、XSS漏洞
XSS漏洞重点需要关注的就是一些输出函数,比如下面这些:
print()
echo
print_f()
die()
var_dump()
print_r()
......
然后去判断输出的内容中是否存在可控变量,并检测这些变量在输如或者输出的时候,是否采用了Html实体编码,或者是否对输入进行了过滤。如果都没有,在输出内容可控的情况下则很可能存在XSS漏洞。
3、代码执行
这里的代码执行,包含了代码执行和命令执行两个部分。同样的,重点需要关注的也是一些函数:
代码执行:
eval()
assert()
preg_replace()
array_map()
call_user_funcn()
.....
命令执行:
system()
exec()
shell_exec()
passthru()
popen()
proc_open()
.....
对于代码执行函数来说,eval()函数是最常见的代码执行函数,需要重点关注。
assert()函数在PHP中与eval类似,但是只能执行一行代码,在PHP7中则取消了该函数执行动态代码的功能,也就是说执行执行固定的代码了。
其他的代码执行函数,大多数为回调函数,具备了调用php代码的功能。
对于命令执行漏洞来说,主要还是存在于一些获取系统信息的地方,可能会通过执行命令的方式来获取,若果说执行的命令可控的话,则可能导致命令执行。
对于命令执行的其中几个方法,存在一定的差异:
- system()是执行系统命令并返回执行结果。
- exec()则是执行命令后,返回一个结果句柄,并不直接返回结果。
- shell_exec()则是执行不返回命令执行后的任何信息。
但是对于代码执行和命令执行需要注意的是,在PHP中,通过{}
的方式同样能够执行代码,同时还能通过动态拼接代码的方式来执行PHP代码。通过使用双反引号的方式,也能够做到等同意system的命令执行效果。
4、文件上传、删除、下载
1) 文件上传漏洞
常见的业务场景:
- 头像上传
- 备份文件上传
- 配置文件上传
- …
对于文件上传漏洞,需要关注的函数为:move_uplaod_file()函数。
在审计的时候就只需要去搜欧索这一个函数,然后判断是否对文件上传的格式做限制,或者说是否可以绕过文件后缀限制。
如果说不能绕过的话,则需要去检测是否存在文件解析漏洞或者文件包含漏洞,然后进行绕过利用。
2)文件删除漏洞
对于文件删除漏洞,触发漏洞的函数同样只有一个,那就是unlink()函数,我们在审计的时候,判断文件名是否可控,同时检测是否允许文件命中存在路径穿越符,如果允许,则说明存在任意文件删除漏洞,危害较大。
3)文件下载漏洞
文件读取或者文件下载漏洞,常见的触发漏洞的函数如下:
file_get_content()
fopen()
readfile()
fread()
file()
......
对于这种漏洞,可以在黑盒的情况下先去找文件读取和下载的的功能点,然后通过请求的URL去分析功能对应的具体代码,再来判断读取的文件,其文件名是否可控,是否允许文件名存在路径穿越符等。
如果存在漏洞的情况下,利用方法一时读取系统文件,而是读取网站源码,在读取的时候,我们可以使用php的伪协议来读取源码。
5、XXE漏洞
XXE漏洞,我们需要关心的函数是:simplexml_load_string(),我们需要判断被解析的XML数据是否允许我们外部输入,并且是否允许代用外部实体,然后在进行详细的分析与利用。
6、SSRF漏洞
SSRF漏洞的引发函数主要是能用于远程请求资源的一些函数,比如:
file-get_content()
curl()
fopen()
readline()
......
常见的漏洞场景为:
- 社交分享
- 转码服务
- 在线翻译
- 没有使用img标签的远程图片加载
- …
对于检测方法主要也是通过判断这些函数获取的URL或者文件名是否可控,如果可控,则可能造成漏洞,同时也容易造成上面提到的任意文件读取漏洞。
五、相关审计技巧总结
1、钻GPC的空子
首先简单的介绍一下GPC,magic_quotes_gpc是php.ini里面的配置选项,在php5.2以前的版本默认开启,在php版本为5.2—5.4之间的版本则默认关闭。在PHP 5.4 以后的版本中则直接取消了这一个配置项。
该配置项的作用就是对我们传入的POST、GET、COOKIE变量中的'
,"
,\
,NULL
等字符前面加上反斜杠\
进行转义。
在PHP中,卡其GPC的方法有两种,一是在PHP.ini中配置 magic_quotes_gpc 选项的值为 on,还有一种就是在PHP代码中使用get_magic_quotes_gpc()函数判断是否开启该选项,如果没有则使用addslashes()函数进行转义。比如下面这样:
if (!get_magic_quotes_gpc()) { //magic_quotes_gpc 配置为 ON 则返回1,如果配置为OFF 则返回0$_POST['message'] = addslashes($_POST['message']);
} else {.......
}
在PHP中,我们提到了POST等变量会受导全局配置GPC的影响,但是有一个变量并不会,那就是$_SERVER,其中获取的http头并不收到GPC的保护,如果说获取的HTTP头存在于数据库交互的行为,则可能导致SQL注入的产生。
同时由于使用了GPC对特殊字符进行转义,我们都知道宽字节注入的漏洞原理,如果说在开启了GPC的情况下,还设置了数据库编码为GBK模式,则可能导致宽字节注入的存在。在PHP中设置数据库编码的方式有下面两种:
方法1: mysqli_set_charset($connnect,'GBK')
方法2: mysqli_query("set names 'gbk'")
这两种方法都能设置数据库的编码模式,在开启了GPC的情况下,就容易出现宽字节注入的问题。
2、利用字符处理问题
1)利用字符处理函数报错
在了解这个问题之前,我们需要知道,在PHP中,报错信息分为多个等级,可以通过配置PHP.ini的display_error =on 或者在代码中使用 error_reporting()来设置报错等级,常见的一些报错等级如下:
1、E_ERROR //致命的运行时错误。这类错误一般是不可恢复的情况,例如内存分配导致的问题。后果是导致脚本终止不再继续运行。
2、E_WARNING //运行时警告 (非致命错误)。仅给出提示信息,但是脚本不会终止运行。
3、E_PARSE //编译时语法解析错误。解析错误仅仅由分析器产生
4、E_NOTICE //运行时通知。
5、E_USER_ERROR //用户产生的错误信息。
6、E_USER_WARNING //用户产生的警告信息。
7、E_USER_NOTICE
8、E_STRICT //启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
9、E_ALL //E_STRICT除外的所有错误和警告信息。
在PHP中,大多数的错误都会显示错误的文件路径与集体位置,在渗透测试中,经常会遇到上传或者写入webshell的的情况需要知道网站绝对路径,这时候我们就可以考虑使用PHP报错来获取网站路径。
对于PHP程序来说,大多数开发者都会使用trim()函数来去除参数首尾的空调,但是当我们传入的参数是一个数组的时候,比如/index.php?a[]=test
,这时候如果采用trim($_GET('a'))
来去除a参数的空格的话,就会导致程序报错。
类似的函数有很多,比如:
addcslashes()
bin2hex()
chr()
exho()
explode()
crypto()
md5()
..........
2)利用字符串截断
字符串截断利用最多的则是在文件上传的时候,但是%00空字符即NULL,在开启了GPC的情况下会受到影响为不能正常利用。同时在PHP5.3以后,修复了这一问题,所以利用场景相对目前来比较少见。这里就只简单的提一下。
但是存在另外一种字符串截断的情况,那就是使用了iconv()函数进行编码转换时,比如UTF-8抓环为GBK编码,总会存在一些差异,导致转换出现乱码。所以在使用了iconv()函数进行转换时,如果出现了错误,则会不在进行转换,导致了字符串被截断的问题。
有大佬测试了相关问题,发现在使用iconv()函数将UTF-8编码准尉GBK编码的情况下,遇到cahr(128)—chr(255)之间的字符否存在被截断的可能。
3、不严谨的正则表达式
比如下面这样的情况:
$ip=$_SERVER('HTTP_CLIENT_IP');
if(preg_match('/\d+\.\d+\.\d+\.\d+/',$ip)){echo $ip;
}
这里如果我们传入client_ip为 127.0.0.1</scritp>alert(xss)</scritp>
则会成功的通过正则校验,输出IP信息,导致XSS漏洞的产生。
五、参考资料
- 代码审计方法总结
- 代码审计思路总结
- 代码审计工具介绍—Fortify
- 代码审计工具介绍—CodeQl
- PHP代码审计需要了解的一些函数
- 代码审计常见漏洞—SSRF
- PHP魔法函数—magic_quoptes_gpc
- 尹毅.《代码审计—企业级WEB代码安全架构》
PHP代码审计18—PHP代码审计小结相关推荐
- php代码审计工具_【学习笔记】PHP代码审计入门:代码审计实例2
第 35 课 代码审计实例之任意文件上传 课程入口(付费) 个人背景 李,本科,电子信息工程专业,毕业一年半,有JavaScript的,PHP,Python的语言基础,目前自学网络安全中. ...
- 常见代码审计工具,代码审计为什么不能只用工具?
代码审计是一种发现程序漏洞,安全分析为目标的程序源码分析方式.今天主要分享的是几款常用的代码审计工具,以及代码审计工具有哪些优缺点? 代码审计工具 seay代码审计工具,是一款开源的利用C#开发的一款 ...
- 【代码审计】那些代码审计的思路.md
前言 代码审计工具的实现都是基于代码审计经验开发出来用于优化工作效率的工具,我们要学好代码审计就必须要熟悉代码审计的思路.而且代码审计是基于PHP语言基础上学习的,学习代码审计最基本的要求就是能读懂代 ...
- 【代码审计】--- php代码审计方法
代码审计需要掌握的点 PHP编程语言的特性和基础 Web前端编程基础 漏洞形成原理 代码审计思路 不同系统.中间件之间的特性差异 代码审计思路 方法一 ---- 检查敏感函数的参数,然后回溯变量,判断 ...
- 【代码审计篇】 代码审计工具Fortify基本用法详解
文章目录 前言 一.工具介绍 二.安装过程 三.升级中文规则库 四.代码审计过程 五.代码审计结果 六.中文乱码解决 前言 本篇文章讲解代码审计工具Fortify的基本用法,感兴趣的小伙伴可以研究学习 ...
- python项目代码审计_Python 安全 -代码审计
Python 安全 -代码审计 杀戮 (有事请 at 大号园长) | 2014-12-02 12:23 这次来讲关于自动化审计方面的. OpenStack 团队出品过一个Python代码审计工具叫ba ...
- PHP代码审计17—CLTPHP代码审计
文章目录 一.系统架构分析 1.系统目录结构 2.系统路由 3.系统配置 4.系统参数获取与过滤 二.Xml外部实体注入分析 1.漏洞分析 2.Payload分析 三.任意文件删除与下载 1.黑盒测试 ...
- php代码审计zhuru,[php 代码审计]Espcms 暴力注入
*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担. 闲生寄别 落野彷徨云翳月,昏鸦倦鸟归缠绵 春风不晓霜林晚,但觉人间白发生 芸芸求索 ...
- 【代码审计】PHP代码审计---基础记录
PHP伪协议 PHP伪协议事实上是其支持的协议与封装协议,支持的种类有以下12种. * file:// - 访问本地文件系统 * http:// - 访问 HTTP(s) 网址 * ftp:// - ...
最新文章
- 西藏监狱首次奏响《婚礼进行曲》
- LA3989女士的选择
- Eclipse启动出现“Failed to create the Java Virtual Machine”错误
- 过滤掉空格( /r/n) 和html标签
- 肖战被抵制?Python爬虫揭秘关于肖战粉丝的人群画像
- PaddlePaddle训练营——公开课——AI核心技术掌握——第1章迈入现代人工智能的大门——多层感知机网络模型
- (*长期更新)软考网络工程师学习笔记——Section 12 Linux系统与文件管理命令
- 简单表单提交php教程,PHP 表单数据提交与接收 超级简单《SSS教程 10》
- linux下开发问题汇总
- graphpad如何检测方差齐_如何选择方差分析中“多重比较”的方法?
- Oracle GoldenGate For Big Data - Kafka Handler
- Rancher获4000万美元D轮融资,推动计算无处不在
- 利用MATLAB平台实现字的语音识别功能
- 泰山OFFICE笑而不语
- 函数式编程的兴衰(Composing Software 1)
- 雨滴桌面显示html,如何用雨滴桌面设置美观的桌面天气插件
- Android上拉查看详情实现
- 编码格式检测(中文乱码问题)
- ckfinder java 配置_JAVA里使用CKEditor和CKFinder的配置
- iOS/Android 纪念模式(黑白灰模式) 记录
热门文章
- 基于反馈结构的窄带宽陷波滤波器
- 怎样在群晖中安装GitLab用于项目代码管理
- 【爬虫笔记】关于Beautiful Soup 4
- 算法设计 - 二分法和三分法,洛谷P3382
- 吉林大学珠海学院计算机录取分数线,吉林大学珠海学院录取分数线2021是多少分(附历年录取分数线)...
- 算法:分治法之合并排序
- 异次元店铺 - 最适合你的个人店铺系统源码(原荔枝发卡)
- Linux驱动之 原子操作
- 数据挖掘经典十大算法_条件熵、信息增益介绍
- ubuntu 8.10安装配置经验(Intrepid Ibex)——转载